docker-ghost-template 0

Docker composition of Ghost blog with Node, NGINX proxy, database, etc.

3 years after


Docker composition of Ghost blog with Node, NGINX proxy with SSL termination, database, etc.

Software Used

Docker version 1.10.3

docker-compose version 1.6.2

The Stack

  • Node.js
    • proxying port 80 calls to the Node web server on port 2368
  • MySQL database
    • using UTFMB4 encoding (MySQL's UTF8 implementation was limited. UTFMB4 includes Emoji)

Inherited Image Versions

  • Ghost: 0.11.0
  • NGINX: 1.10
  • MySQL: 5.7.15

What You'll Need

  • A server somewhere, like Amazon EC2 or Google Compute Cloud
  • A domain name.
  • An SSL certificate and key for your domain.
  • Access to your domain's DNS.
  • An account with an email sending service (SMTP service) (Mailgun, Sendgrid, etc.). I'm using Mailgun, which is free for low volume.
  • An Amazon S3 bucket.
  • An Amazon CloudFront distribution set up to serve your S3 bucket.

How to Use It

  1. Clone project to your server's filesystem.
  2. Edit environment settings in docker-compose.yml
    • blog domain
    • database settings - in 2 places - under ghost, and under mysql.
    • mail server settings
    • S3 bucket and S3 info
    • CloudFront domain
  3. Add your SSL certificate and key to nginx/volumes/ssl/ (there are placeholders there)
  4. Set the blog domain (server_name) in nginx/copy/default.conf (must match the common name in your SSL certificate)
  5. Run from within your Linux environment or Docker Toolbox environment:
    1. docker-compose build
    2. docker-compose up -d (you can remove the -d if you want to see logs, then Ctrl+C to stop all containers)
  6. If using Docker Toolbox, look up the host IP address with: docker-machine ip default
  7. On Linux, you'll just use "localhost" or "".
  8. Switch your domain's DNS to point to the address. Go to the domain in our browser and you'll see your new blog.
  9. Go to https://YOUR_DOMAIN/admin to set up your blog.
  10. Once you've made your admin account using that wizard, go back to: https://YOUR_DOMAIN/admin
  11. Log in and enjoy.

Ghost Content Directory

The directory ghost/volumes/content will be populated with 5 directories and a file the first time you start the container.

Ghost will create these directories:

  • apps - for future use when ghost supports apps
  • data - would normally hold a SQLite db, but won't for us since we're using MySQL
  • images - for uploaded images, but will stay empty since we'll use S3 for storage
  • storage - created in our Dockerfile for S3 image support
  • themes - You can add more themes here. Default is Casper theme.
  • index.js - It's a symlink. Don't edit or remove it.

How to back up your database

  1. Run "docker-compose ps" to get a list of running containers.
  2. Locate the name of the mysql container.
  3. Run this command to get the container's internal IP: docker inspect --format='{{.NetworkSettings.IPAddress}}' THAT_CONTAINER-NAME
  4. In your favorite database GUI tool (like Navicat or DataGrip), create a new connection via SSH tunnel to the host machine
  5. Use the internal IP address and database user and password to connect to database once SSH tunnel is established to host.
  6. You'll have access to the data so you can view data and run backups.


The default theme is Casper. I have a minor fork of this theme here:

It includes Disqus support, so all you have to do is change the identifiers to your blog's Disqus ID and domain and you're good to go. See the README in that repo.

To install another theme

Stop docker-compose with:

docker-compose stop

Copy the new theme to docker-ghost-template/ghost/volumes/content/themes/ so that your theme folder sits next to the casper folder in the themes directory

Now run: docker-compose up -d

Log in to the Ghost admin, go to Settings > General, and at the bottom is the Theme dropdown. Select your theme and click Save.

How does that work?

The ghost/volumes/content directory (on docker host machine) gets mounted inside your ghost container at /var/lib/ghost when the container runs. See the docker-compose.yml to see where this volume mount is happening.


  • Only NGINX's ports (80, 443) are exposed at host level.
  • Other ports are available only from inside host and linked containers.

To Upgrade from an Earlier Ghost version

Docker containers are meant to be disposable, so you'll need to export your Ghost data first.

  1. Export your data:
  2. Set up a new server with the repo.
  3. Set it up as directed.
  4. Create your admin account via the web-based wizard.
  5. Delete the starter post.
  6. Go to Labs and import your data.

That's it!

MySQL memory

I'm running this on an EC2 t2.micro at 1GB RAM. I tried to limit MySQL's memory limit because it was taking up, what in my opinion, was too much.

Adding this to the mysql: block in docker-compose.yml will limit memory:

mem_limit: 384m

I tried 256 and 384. Both caused issues with MySQL. Instead of continuing to experiment, or trying to tune MySQL in a container (no thanks), I just removed the limit.

Related Repositories



A list of semi to fully remote-friendly companies in tech ...



A collection of awesome penetration testing resources, tools and other shiny thi ...



Vulnerability scanner for Linux/FreeBSD, agentless, written in Go ...



Awesome resources for coding and learning: open source projects, websites, books ...



Docker VM Extension for Microsoft Azure :whale: ...

Top Contributors