Deploy Ghost blog with Dokku (production & scalable)

three cool guys

Step-by-step guide on how I created and deployed my Ghost.io-based personal blog with Dokku PaaS (free & open-source Heroku alternative). Now you can do it too! Deploy production-ready & scalable blogs on any server.

Read this article on my personal blog which was deployed using this tutorial https://okhlopkov.com/deploy-ghost-blog-with-dokku/.

Ghost.io is a modern open-source blog builder that looks and feels like Medium and also has powerful SEO tools built-in. Dokku is an open-source PaaS that can drastically speed up your deployment for staging and production.

Step 1: Rent a server

I prefer using DigitalOcean because it is really easy to create, monitor, and scale your droplets. I’d always suggest having a server with at least 2CPU and 2Gb RAM. My referral link with $100 bonus: https://m.do.co/c/260555f64021

Step 2: Install Dokku

Unlike Heroku, Dokku doesn’t have a handy web interface where you can just press buttons. If you are not familiar with Heroku CLI (which is similar to the Dokku interface), don’t worry: I’ll give you all the necessary commands you’ll need below.

I’d strongly recommend installing the latest Dokku from their website, here is the current latest version (July 2021):

wget https://raw.githubusercontent.com/dokku/dokku/v0.24.10/bootstrap.sh
sudo DOKKU_TAG=v0.24.10 bash bootstrap.sh

⚠️ Don’t forget to enter your server IP address in the browser to finish Dokku setup: it will require confirming some stuff through its web interface (which still has only one page).

Step 3: Create & Setup Dokku app

Imagine that you have bought a domain okhlopkov.com for your blog. I’ll use this URL for demo purposes.

Create Dokku app

dokku apps:create ghost

Install MySQL addon and link it to the app:

dokku plugin:install https://github.com/dokku/dokku-mysql.git mysql
dokku mysql:create ghost
dokku mysql:link ghost ghost

Now connect MySQL the proper way

Let’s connect MySQL database the way that Ghost will understand. Let’s find out our DATABASE_URL in the config:

dokku config:show ghost

My DATABASE_URL looks like this:

mysql://mysql:b35543396688d777c@dokku-mysql-ghost:3306/ghost

According to the official docs, we need to set connection params separately. Check how I split this URL into different environment variables:

dokku config:set ghost \
database__connection__host=dokku-mysql-ghost \
database__connection__user=mysql \
database__connection__password=b35543396688d777 \
database__connection__database=ghost

You will also require these environment variables:

dokku config:set ghost NODE_ENV=production url=https://okhlopkov.com database__client=mysql

Now the hardest part. You need to update MySQL from inside its CLI (read comments):

# remember root password
cat /var/lib/dokku/services/mysql/ghost/ROOTPASSWORD
# Enter MySQL container
dokku mysql:enter ghost
# login as root
mysql -u root -p
# then copy-paste the root password you gathered before
# and then in mysql> console:
# don't forget to replace password from your DATABASE_URL
ALTER USER 'mysql' IDENTIFIED WITH mysql_native_password by 'b35543396688d777';
FLUSH PRIVILEGES;

More Dokku tweaks

Allow Nginx to receive uploads up to 50Mb:

dokku nginx:set ghost client-max-body-size 50m
dokku proxy:build-config ghost

Specify docker persistent storage for the images you uploaded through Ghost Admin:

mkdir -p /root/ghost/content
dokku storage:mount ghost /root/ghost/content:/var/lib/ghost/content

Finally, deploy from the official Docker image:

dokku git:from-image ghost ghost:latest
dokku proxy:ports-set ghost http:80:2368

Attach domain and create Letsencrypt SSL certificates for HTTPS (don’t forget to create ‘A record’ to point your domain to your server IP in your DNS provider). If it is the first time you setup Letsencrypt with Dokku, you may be asked to enter your email:

dokku config:set --global DOKKU_LETSENCRYPT_EMAIL=jeff@bezos.comdokku domains:set ghost okhlopkov.com
dokku letsencrypt:enable ghost

🎉 That’s all folks! Now your blog is deployed in production! 🎉

P.S. Helpful snippets

If you want to check Ghost logs, use this Dokku command

dokku logs ghost -t

If you want to update the ghost docker image, just deploy again:

dokku git:from-image ghost ghost:latest

Follow me on Medium and on Twitter for more Dokku tutorials. This is my favorite tool that I use for all my production deployments and I’ve already prepared a huge amount of stories and how-tos. 🎉

Daniil Okhlopkov