Deploy Ghost with Docker and Traefik 2

If you are into blogging, there are so many blogging platforms to choose from nowadays but you can’t get away from WordPress to start with. Based on W3techs article, WordPress has more than 60% of market share. I’ve already covered installing WordPress in my previous article. It is no doubt the easiest platform to use but as there are so many users, even if you can customize the theme, you still lose some uniqueness of your personal blog. Today I want o talk about another platform - Ghost.

My first impression of Ghost is similar to this post.

A blogging platform which is just for blogging? Having a neat markdown editor? This amazing dashboard? SEO right out of the box? Ways to extend via plugins and themes? Oh boy, John, you got me sold.

Please find file structure as below, let’s get started.

1
2
3
4
5
├── ghost-blog/
│ ├── docker-compose.yml
│ └── ghost/
│ ├── config.production.json
│ └── content/

Let’s create the folder and files first.

1
2
3
mkdir -p ghost-blog/ghost/content
touch ghost-blog/docker-compose.yml
touch ghost-blog/ghost/config.production.json

Next, let me post my docker-compose.yml file.

Please note, my docker-compose.yml is meant to be used with my Traefik configurations. It might not work with your set ups. You can find my Traefik configuration at this link

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
version: '3.7'

services:
ghost:
image: ghost:3-alpine
container_name: ghost
environment:
NODE_ENV: production
volumes:
- ./ghost/content:/var/lib/ghost/content
- ./ghost/config.production.json:/var/lib/ghost/config.production.json
networks:
- proxy
restart: always
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.ghost-secure.entrypoints=websecure"
- "traefik.http.routers.ghost-secure.rule=Host(`blog.yourdomain`)"
- "traefik.http.routers.ghost-secure.service=ghost-service"
- "traefik.http.services.ghost-service.loadbalancer.server.port=2368"

networks:
proxy:
external: true

You can find all configurations from official website. I want to cover some important ones in my settings.

  1. NODE_ENV:
    I set my blog in productions environment hence I need to load config.production.json on my docker-compose.yml file.
  2. Here is the content my config.production.json. The only thing you need to change is url.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 {
"url": "https://blog.yourdomain",
"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"
}
}
  1. (optional) If you invite another author with above config, the invitation will be sent from noreply@blog.yourdomain. If you want to change this default email address or the sender’s name, you can config your own email. Example below:
1
2
3
4
5
6
7
8
9
10
11
12
13
"mail": {
"from": "'Ghost Support' <YOUR_EMAIL>",
"transport": "SMTP",
"options": {
"host": "smtp.exmail.qq.com",
"port": 465,
"secureConnection": true,
"auth": {
"user": "YOUR_EMAIL",
"pass": "YOUR_EMAIL_PASSWORD"
}
}
}

If you follow my config exactly, now you just need to run docker-compose up -d to deploy your ghost blog.

Thanks for reading, see you next time.