I have been using Dokku for years to host personal sites and pet projects on a cheap web-server. Dokku allows you to deploy your projects through git-ops. The experience is very similar to deploying to other git-ops platforms like Heroku. This had been working smoothly for my previous personal blog which was a Wordpress app. When I decided to switch my personal site to Ghost I wasn't willing to sacrifice my Dokku setup. This made me figure out how to deploy a Ghost application to Dokku.

The main difference between my Wordpress setup and Ghost, is that there is no code repository managed by Git for my Ghost setup. Since Dokku is based on git-ops there is no clear way to deploy Ghost to a Dokku environment.

Fortunately Dokku allows you to directly deploy Docker images directly, be it a bit of an obscure feature, it works remarkably well. Directly deploying a Docker image gives us the advantage of not having to create a custom code repository for our Ghost deployment, saving us time spent on maintenance.

Guide

Prerequisites: I assume you have a server running Dokku, if you don't it is quite easy to spin one up on Digitalocean. This guide is tested against Dokku v0.14.6

Start by creating a new Dokku application

$ dokku apps:create my-ghost-app

Once you have an application setup you can pull in the latest Ghost docker image

$ docker pull ghost:latest

For Dokku to recognize a docker image from your local repository it should be name dokku/name-of-app:tag. So let's tag our Docker image with the correct name:

$ docker tag ghost:latest dokku/my-ghost-app:latest

Now that we have tagged the Docker image we can deploy it:

dokku tags:deploy my-ghost-app latest

We should now have a docker container that is running Ghost (you can check by issuing the command docker ps). But before we can reach our Ghost application from the outside world we need to expose it's port:

$ dokku proxy:ports-add my-ghost-app http:80:2368

This command tells Dokku to route all incoming traffic on port 80 to port 2368 inside our Ghost Docker container.

Since Docker containers are ephemeral and do not persist across restarts we should mount a storage volume to make sure we do not lose any content when that happens.

$ dokku storage:mount my-ghost-app /opt/my-ghost-app/ghost/content:/var/lib/ghost/content

And create the directory.

$ mkdir -p /opt/my-ghost-app/ghost/content

Now configure one of Ghost's environment variables to instruct it for which Host it can receive traffic:

$ dokku config:set my-ghost-app url=http://my-ghost-app.com

Since this domain is not known by the Nginx server operated by Dokku we need to add it through the Dokku command-line:

$ dokku domains:add my-ghost-app my-ghost-app.com

This should be enough for your blog to be running. Now you can start using you Ghost deployment. Or you could leverage any of the other Dokku features to for instance improve your deployment's security.

Troubleshooting In the case something is wrong you can troubleshoot by looking at the Docker container logs, through $ dokku logs my-ghost-app. If this gives you zero output please check that the Ghost docker image is actually running $ docker ps.