Join us

Ghost on Docker with Traefik


In this Article, I will show you how to host your own Ghost Instance with Docker and use Traefik as a Reverse Proxy.

So let’s start with the things we need:

  • Some kind of server where everything will be deployed. I took a Hetzner Cloud Instance with 2 vCPUs and 2 GB RAM running Ubuntu 20.04
  • In addition, I have a DNS Record for pointing to my cloud instance

We begin by setting up docker on our server, which is explained here on their page. It is fairly simple, so I will just list the commands that need to be executed.

After these steps, Docker is running on our server, and we installed docker-compose in addition. This is a handy tool when deploying more than one container, which we are planing to do. Now we can start with our docker-compose.yml file which will contain all the configuration for Traefik, Ghost and a Percona Database. We start with the version definition and create two networks. One for the traffic flowing between Ghost and our database, and one for the traffic between Traefik and Ghost.

Now we can add the definition for Traefik. Our Server should accept traffic on port 80 (http) and 443 (https). Each request on port 80 will be automatically redirected to port 443 by Traefik. In the command section, we define a certificate resolver which will handle our LetsEncrypt certificates. Here we need to define an email address, and we also define the path to a file where the resolver should store its information. This is mounted to a path on our docker host, so we do not necessarily need to fetch new certificates if we deploy a new traefik version.

After we have configured Traefik, we can now configure Ghost. We use the Docker image, which is maintained directly by Docker. As mentioned before, we connect the ghost instance with both our networks, so that traefik can redirect traffic to ghost and ghost can access our database. An important point here is the last line, where we define the Since Ghost is connected with two networks we have to tell Traefik with this label which is the network it should use. Traefik sees everything happening on the docker host, this means Traefik can see both networks, but it can only use the one it is connected to. Networks created by docker-compose always start with the project name. We will name our project blog, therefore the network name will be blog_frontend_net. You should also change the host from to whatever your domain name is.

In addition to this, we also need a config file for ghost. We try to keep that file simple, so just set the URL and the database connection information.

After all, we need a database to store our data. I choose a Percona which is compatible to MySQL. Of course, you could pick a MariaDB or MySQL instead, but I like Percona.

For our database we also need a file containing some environment variables which should not be visible for everyone since they contain passwords. This information will be used when the Percona is initialized.

Since all configurations are in place now, we can start the project with one simple command.

This might take some time because we need to fetch some docker images from the hub and extract them, but in the end you should be able to visit your Ghost instance under the domain name you have chosen. For me, it was If there is a warning about an insecure page, you may need to wait a few moments until Traefik had the time to fetch your SSL certificate.

After everything is set up, we want to create our first user and login with this. For creating the initial user, visit https://your.domain/ghost and fill in your information. You can also invite other users if you plan to use ghost with some colleagues.

Now we are done, and you can start writing your blog!


I think Ghost is a nice tool for writing blogs with an active community, but since the Docker Image is not supported, it can be sometimes tricky to configure and to debug if something is not working. For not technical users, a Ghost instance from might be a far better choice. Above all, the fees are really reasonable when you consider how much time and nerves you can save. I just decided to host it myself, because for me, it is just another container running somewhere, and I like to play around with those tools.

What comes next?

You may have noticed that there is no Nginx proxying the requests to Ghost. This might be of interest to you if you expect much more traffic, but then it would also be a good idea to run more than one container with Ghost. Traefik as a reverse proxy does a quite good job for my use case. Furthermore, there is just a single database server, which might not be ideal. There is still work to be done which I will summarize.

  • Migrate Ghost to my Kubernetes Cluster once it is running smoothly and scale to at least 2 instances for high availability.
  • Migrate the database to a central cluster, which will be a Percona XtraDB cluster in my case.
  • And of course revise the design. (Hardest part for me 😅)

Previously posted on

Only registered users can post comments. Please, login or signup.

Start blogging about your favorite technologies, reach more readers and earn rewards!

Join other developers and claim your FAUN account now!


Daniel Niecke

Founder, dynamic_qr

Co-Founder of @dynamic_qr I like hysterically grown monoliths 🧟
User Popularity



Total Hits