version: '3.7'
services:
acme:
container_name: acme
image: nginx:latest
restart: unless-stopped
networks:
- traefik
environment:
- PGID=1000
- PUID=1000
volumes:
- ./acme:/usr/share/nginx/html
expose:
- 80
labels:
- traefik.enable=true
- traefik.http.routers.acme.rule=(Host(`www.acme.com`) || Host(`acme.com`))
- traefik.http.routers.acme.entrypoints=websecure
- traefik.http.routers.acme.tls=true
- traefik.http.routers.acme.tls.certresolver=l
- traefik.http.routers.acme.priority=10
ghost:
container_name: acme-blog
image: ghost
restart: unless-stopped
expose:
- 2368
depends_on:
- db
networks:
- traefik
- ghost
volumes:
- ./acme-blog/content:/var/lib/ghost/content
environment:
# see https://ghost.org/docs/config/#configuration-options
database__client: mysql
database__connection__host: db
database__connection__user: root
database__connection__password: super_secret_password
database__connection__database: ghost
url: https://www.acme.com/blog
# contrary to the default mentioned in the linked documentation,
# this image defaults to NODE_ENV=production (so development mode
# needs to be explicitly specified if desired)
#NODE_ENV: development
labels:
- traefik.enable=true
- "traefik.http.routers.acme_blog.rule=(Host(`www.acme.com`) && PathPrefix(`/blog`)) || (Host(`acme.com`) && PathPrefix(`/blog`))"
- traefik.http.services.acme_blog.loadbalancer.server.port=2368
- "traefik.http.middlewares.acme_blog-strip.stripprefix.prefixes=/blog"
- traefik.http.routers.acme_blog.entrypoints=websecure
- traefik.http.routers.acme_blog.tls=true
- traefik.http.routers.acme_blog.tls.certresolver=le
- traefik.http.routers.acme_blog.priority=100
db:
image: mysql:8.0
restart: unless-stopped
volumes:
- ./acme-blog/db:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
expose:
- 3306
networks:
- ghost
environment:
MYSQL_ROOT_PASSWORD: super_secret_password
networks:
ghost:
traefik:
external: true
Design & Deployment Notes
- All data/volumes for this stack are intended to be contained in a user folder. Docker will create the appropriate folders when it starts up the containers for the first time. If docker creates the folders they will have root permissions/ownership. It is recommended that ownership is change to a standard user account. Alternatively, one can create the folders prior to starting the stack.
- The priority needs to be defined otherwise traefik will route www.acme.com/blog to the nginx container and not the ghost container.
- The traefik priority will not work in docker-compose.yml files 3.1. Articles on the Internet that version 3.2 or higher will work. Version 3.7 does work.
- On initial startup it takes a while for the mysql container to startup and initialize this can delay ghost from starting up, so you may see ghost failing with an exit code of zero or two. Be patient. Eventually, the InnoDB initialization will complete and ghost will startup properly.
- The stripprefix line is required because the ghost application expects to be at the root URL path (i.e. "/") and not in a folder/subpath.