Prerequisites

Please ensure you already have the following components installed before getting started:

In this tutorial, I will deploy the latest version of Ghost as a Docker container on Ubuntu 21.10. This is one of the most convenient and flexible way if you want to have a Ghost blog deployed quickly.

Assume that I want to deploy a new blog at domain ghost.nth.vn

Let’s get started!

Step 1: Create the folder structure for our blog.

mkdir -p ghost.nth.vn/ghost/content
cd ghost.nth.vn
touch docker-compose.yml
touch config.production.json

Result:

├── ghost.nth.vn
│   ├── docker-compose.yml
│   └── ghost
│       ├── config.production.json
│       └── content

Step 2: Edit docker-compose.yml file as following example
(Replace ghost.nth.vn with your domain)

version: '3.7'

services:
  ghost:
    image: ghost:alpine
    container_name: ghost-blog
    environment:
      NODE_ENV: development
    volumes:
      - ./ghost/content:/var/lib/ghost/content
      - ./ghost/config.production.json:/var/lib/ghost/config.production.json
    networks:
      - traefiknet
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefiknet"
      - "traefik.http.routers.ghost-secure.entrypoints=https"
      - "traefik.http.routers.ghost-secure.rule=Host(`ghost.nth.vn`)"
      - "traefik.http.routers.ghost-secure.tls=true"
      - "traefik.http.routers.ghost-secure.tls.certresolver=cloudflare"
      - "traefik.http.routers.ghost-secure.service=ghost-service"
      - "traefik.http.services.ghost-service.loadbalancer.server.port=2368"

networks:
  traefiknet:
    external: true

Note that I will use a free HTTPS certificate by Cloudflare.

Step 3: Edit config.production.json file:
(Replace ghost.nth.vn with your domain)

 {
  "url": "https://ghost.nth.vn",
  "server": {
    "port": 2368,
    "host": "0.0.0.0"
  },
  "database": {
    "client": "sqlite3",
    "connection": {
      "filename": "/var/lib/ghost/content/data/ghost.db"
    }
  },
  "mail": {
    "transport": "Direct"
  },
  "logging": {
    "path": "/var/lib/ghost/content/logs/",
    "level": "info",
    "rotation": {
      "enabled": true,
      "count": 15,
      "period": "1d"
    },
    "transports": ["stdout", "file"]
  },
  "paths": {
    "contentPath": "/var/lib/ghost/content"
  }
}

Step 4: Config email sender (optional) section in config.production.json file. (Without doing this step, your blog will send email from noreply@your-domain-name)

"mail": {
    "from": "'Ghost Support' <YOUR_EMAIL>",
    "transport": "SMTP",
    "options": {
        "host": "smtp.gmail.com",
        "port": 465,
        "secureConnection": true,
        "auth": {
          "user": "YOUR_EMAIL",
          "pass": "YOUR_EMAIL_PASSWORD"
        }
    }
}

Step 5: At the same folder with docker-compose.yml file, run the following command create and deploy Ghost docker container:

docker-compose up -d

If there is no errors, then, congratulations, go straight to your domain and test your new blog!

Reference

  1. https://tech.aufomm.com/deploy-ghost-with-docker-and-traefik-2/