Run Ghost inside a Docker container on DigitalOcean

Stefan CosmaStefan Cosma
3 min read

Recently I created a new theme for Ghost, that you can find here and can currently experience on this website. I wanted a way of showing it off, so anyone that wants to contribute to it or just plain use it, can get a feel of what it looks like in a live environment.

Initially I looked at Heroku, but I soon fell into a rabbit hole of errors, because Docker doesn't play nice with Heroku and I didn't like that I would have to jump through hoops just to keep the app online. Keep in mind that this is an open source project and having to pay for keeping the Heroku app was not something I was prepared to do at that moment.

But, Stefan, you already have a server, where you host your website! Why don't you use that? Initially, I wanted to keep my server clean off other systems and just use it for my website. I changed my mind and here we are.

Enough backstory, let's get to the actual implementation. Bellow is my current stack and the process I followed that works for my setup. It may work differently for you and your stack.

My whole stack is like this:

  1. I have the stefancosma.xyz domain registered and I use Cloudflare as a DNS provider.
  2. The website itself is hosted on a DigitalOcean droplet, that runs their Ghost image (an older version but I keep it up to date).

Nothing fancy, right?

So, the first thing I did was to get Docker working on my droplet. After running apt-get update I installed Docker using this:

apt-get install docker.io

Once that was done, I just spun up a new Docker container for Ghost. Luckily there is already a Docker image for Ghost. You can check it out here.

Now the tricky part. I ran this command to expose the Ghost instance in the Docker container, to the outside world.

docker run -d --name name_your_container -p 3001:2368 -e url=https://ghost_url ghost

So, what this command does, is that it runs a new container with a custom name and it exposes the Ghost port 2368 on the host's 3001 port. Of course you can use a different port on your machine, if you so desire. Another cool thing is that this Docker image accepts, as parameters, any Ghost configuration parameters, found here. The Docker image name is ghost.

So now, if you access your droplets IP followed by the 3001 port, you should see a new Ghost instance up and running.

The last thing I did was to spin up a new subdomain inside Nginx and add it to Cloudflare. The configuration I used for Nginx is similar to the one bellow:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name subdomain.domain.com;

    ssl_certificate certificate.cert;
    ssl_certificate_key key.key;
    include conf.conf;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://127.0.0.1:3001;

    }

    location ~ /.well-known {
        allow all;
    }

    client_max_body_size 50m;
}

Besides the above configuration, I've added a CNAME record with the subdomain name that points to the root domain.

And that's it. All good and done.

Nothing out of the ordinary. How would you have done it differently? Tweet @stefanbc or email me hello@stefancosma.xyz.

Until next time, code long and prosper.

0
Subscribe to my newsletter

Read articles from Stefan Cosma directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Stefan Cosma
Stefan Cosma

Hello there! ๐Ÿ‘‹ I am a seasoned senior software engineer at Ropardo, a prominent company based in Sibiu. My expertise lies in frontend development, which is where I mainly focus my work efforts. In the past, I have contributed to various projects for SmartBill, spearheaded a community of over 1.5 million members, and developed exceptional products for Koding, a San Francisco-based company. Furthermore, I have built and helped with the development of presentation websites and online stores for small businesses at Sensmedia. As a passionate advocate of the open-source movement, I am always on the lookout for fresh and innovative projects to work on. Currently, I am dedicated to constructing a local web community called @SibiuWebMeetup in Sibiu. If you need to contact me, please don't hesitate to drop me an email at hello@stefancosma.xyz or look me up on most social media platforms using the handle @stefanbc. On a personal note, I am an avid comics enthusiast and amateur photographer, and you can often find me indulging in these hobbies in my free time. Please note that I usually respond to messages within 1-2 business days.