[docker-compose] Ghost 3 et Traefik v2
Le but de cette documentation est de vous fournir un fichier .yml clé en main pour installer le CMS Ghost derrière Traefik.
Article mis à jour suite aux commentaires de ldez oncernant un soucis de configuration côté Traefik (mélange entre conf’ statique et dynamique) (merci !!)
Mise à jour : 28/09/2020
- refonte des fichiers .yml de traefik (suppression des .toml)
- refonte du fichier docker-compose.yml
- utilisation des variables d’environnement (fichier .env)
Ghost est un CMS pour propulser des sites web type « blog », un peu comme ComputerZ Solutions ;). Cet outil nécessite une base de données dans laquelle y seront stockées toutes les données (pages, posts et configurations). J’utilise Traefik en frontal de Ghost – plus de détails à cette adresse (CZS).
Quelques pré-requis avant de se lancer : avoir Docker (pour Ubuntu ou CentOS 7) et docker-compose
installé sur votre machine. J’utilise le chemin « /srv/docker » sur mon serveur et y ait créé un dossier « conf » où sont stockés les fichiers de configuration pour les différents services, un dossier « traefikdynamic » pour les configurations personnalisés pour Traefik et enfin un dossier « logs » pour Traefik.
De plus, il est important de créer le fichier acme.json
dans le dossier « conf » avec les droits nécessaires avant de créer les conteneurs :
touch /srv/docker/conf/acme.json
chmod 0600 /srv/docker/conf/acme.json
Sans plus attendre, voici le fichier docker-compose.yml :
---
version: '3.6'
services:
traefik:
container_name: traefik
image: traefik:picodon
restart: unless-stopped
ports:
- 80:80
- 443:443
- 8080:8080 # used to have the traefik dashboard # used to have the traefik dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./conf/traefik.yml:/etc/traefik/traefik.yml:ro
- ./conf/traefikdynamic:/traefikdynamic:ro
- ./logs/traefik.log:/etc/traefik/applog.log
- ./conf/acme.json:/acme.json
sqlghost:
container_name: sqlghost
image: mariadb:bionic
restart: unless-stopped
volumes:
- datasqlghost:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: '1'
MYSQL_USER: ${MYSQLUSER}
MYSQL_PASSWORD: ${MYSQLPASSWORD}
MYSQL_DATABASE: ${MYSQLDB}
ghost:
container_name: cmsghost
image: ghost:3
restart: unless-stopped
volumes:
- dataghost:/var/lib/ghost/content
- ./conf/config.production.json:/var/lib/ghost/config.production.json:ro
depends_on:
- sqlghost
labels:
traefik.enable: true
traefik.http.routers.ghost-https.entrypoints: websecure
traefik.http.routers.ghost-https.rule: Host(`ghost.czs.local`)
traefik.http.routers.ghost-https.middlewares: compression@file, security@file
traefik.http.routers.ghost-https.tls: true
traefik.http.routers.ghost-https.tls.certresolver: "letsencrypt"
volumes:
datasqlghost:
dataghost:
Les lignes sont explicites : création du service « traefik » pour le conteneur reverse-proxy, le service « sqlghost » à base de MariaDB et le service « webghost » pour le CMS Ghost. Seul Ghost a des labels correspondant pour Traefik – avec ces quelques lignes, votre Ghost sera « routable » vers le web et automatiquement géré en SSL.
Vous remarquerez aussi des volumes complémentaires comme « /etc/timezone » et « /etc/localtime » – utilisé pour être en relation avec le serveur hôte (qui est à l’heure via NTP) et donc avoir un horodatage cohérent. Les fichiers de configurations sont à côté du docker-compose.yml, libre à vous de les placer ailleurs (et de modifier le chemin dans la conf)
Les labels Traefik mis en place dans ce fichier docker-compose.yml sont dit en « configuration statique ». Avant de lancer les conteneurs, vous devez encore créer des fichiers, notamment deux pour Traefik :
fichier « traefik.yml »
global:
sendAnonymousUsage: false
checkNewVersion: false
api:
#insecure: true
dashboard: true
#debug: true
log:
filePath: "/etc/traefik/applog.log"
level: INFO
providers:
docker:
endpoint: unix:///var/run/docker.sock
exposedByDefault: false
watch: true
swarmMode: false
file:
directory: /traefikdynamic
watch: true
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: contact@czs.local
# caServer: https://acme-staging-v02.api.letsencrypt.org/directory
caServer: https://acme-v02.api.letsencrypt.org/directory
storage: acme.json
keyType: EC256
httpChallenge:
entryPoint: web
Le fichier de configuration Traefik se décompose sous forme de blocs – tout est assez explicite, je ne vais pas faire une description pour chaque ligne.
Le second fichier traefik_dynamic.yml
est à placer dans un dossier « traefikdynamic », dans le dossier « conf » précédement initialisé.
tls:
options:
default:
minVersion: VersionTLS12
sniStrict: true
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
curvePreferences:
- CurveP521
- CurveP384
http:
middlewares:
compression:
compress:
excludedContentTypes:
- text/event-stream
security:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
#accessControlAllowOriginList = "*"
accessControlMaxAge: 100
addVaryHeader: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
frameDeny: true
sslRedirect: true
sslForceHost: true
stsPreload: true
#ContentSecurityPolicy = "default-src 'self' 'unsafe-inline'"
customFrameOptionsValue: SAMEORIGIN
referrerPolicy: same-origin
featurePolicy: vibrate 'self'
stsSeconds: 315360000
authentification:
basicAuth:
users: # admon / totolasticot
- admon:$2y$10$4IgUsvlCwENsF18B9t7AoegQ7eWZVfWxPFRhNfBWz7F00h1X2oZFe
Ghost a aussi besoin d’un fichier de configuration pour être exploitable. Suivez bien le formalisme du fichier .json requis – ci-dessous un exemple de conf’ :
{
"url": "https://ghost.czs.local",
"server": {
"port": 2368,
"host": "0.0.0.0"
},
"database": {
"client": "mysql",
"connection": {
"host": "sqlghost",
"user": "ghost",
"port": "3306",
"password": "sqlghostuserpassword",
"database": "ghost"
}
},
"privacy": {
"useUpdateCheck": false,
"useGravatar": false,
"useRpcPing": false,
"useStructuredData": true
},
"process": "systemd",
"paths": {
"contentPath": "/var/lib/ghost/content"
}
}
config.production.json
Enfin, créer à la racine du dossier (à côté du fichier docker-compose.yml) un fichier intitulé .env
, qui contiendra les variables quant aux identifiants SQL et les versions des applications.
MYSQLUSER=ghost
MYSQLPASSWORD=sqlghostuserpassword
MYSQLDB=ghost
Maintenant que vos fichiers sont créés, vous pouvez initier un « docker-compose up -d » et voir la magie s’opérer… 🙂 Le site web sous Ghost sera accessible au nom de domaine stipulé dans la conf’, Traefik effectuera automatiquement le lien/la redirection et le tout avec du HTTPS via Let’s Encrypt.
Vous pouvez trouver l’ensemble des scripts à cette adresse Github.