Überarbeitet am 8. September 2026.
Auf meinen Servern läuft Nginx gerne direkt auf dem Host, während Anwendungen in Docker-Containern stecken. Genau für dieses Szenario ist diese Anleitung gedacht: Ghost 6 + MySQL 8 in Docker Compose, davor ein bereits vorhandener Nginx.
Ghost selbst bietet seit Version 6 zusätzlich einen neuen offiziellen Docker-Compose-Stack als Preview an. Der bringt unter anderem Caddy und auf Wunsch die selbst gehosteten Social-Web-/Analytics-Dienste mit. Wer diesen kompletten Stack möchte, sollte direkt die offizielle Ghost-Dokumentation nutzen. Hier bleiben wir bewusst bei einem schlanken Setup mit dem offiziellen Ghost-Docker-Image und meinem externen Nginx.
Voraussetzungen
- Docker Engine und Docker Compose,
- Nginx auf dem Host,
- eine Domain mit DNS-Eintrag auf den Server,
- Port 80/443 für Nginx,
- ein SMTP-Dienst für produktive Ghost-E-Mails.
Falls Docker noch fehlt: Docker und Docker Compose installieren. Den Aufbau einer Compose-Datei erkläre ich außerdem in Docker Compose erklärt.
Projektordner anlegen
sudo mkdir -p /opt/ghost
sudo chown $USER:$USER /opt/ghost
cd /opt/ghost
Passwörter nicht in compose.yaml schreiben
Wir legen eine .env an:
nano .env
GHOST_URL=https://blog.example.de
MYSQL_DATABASE=ghost
MYSQL_USER=ghost
MYSQL_PASSWORD=ein-langes-zufaelliges-passwort
MYSQL_ROOT_PASSWORD=ein-anderes-langes-zufaelliges-passwort
Danach:
chmod 600 .env
Für besonders sensible Setups unterstützt das offizielle Ghost-Image inzwischen auch Docker-Secrets über Variablen mit dem Suffix _FILE. Für einen überschaubaren Einzelserver ist eine geschützte .env aber ein verständlicher Einstieg.
compose.yaml erstellen
services:
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h localhost -p$${MYSQL_ROOT_PASSWORD} --silent"]
interval: 10s
timeout: 5s
retries: 10
ghost:
image: ghost:6-alpine
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "127.0.0.1:2368:2368"
environment:
database__client: mysql
database__connection__host: db
database__connection__user: ${MYSQL_USER}
database__connection__password: ${MYSQL_PASSWORD}
database__connection__database: ${MYSQL_DATABASE}
url: ${GHOST_URL}
NODE_ENV: production
volumes:
- ghost_content:/var/lib/ghost/content
volumes:
db_data:
ghost_content:
Die zwei wichtigsten Sicherheitsdetails dabei:
- MySQL hat gar keinen veröffentlichten Host-Port.
- Ghost-Port 2368 ist nur an
127.0.0.1gebunden und damit nicht direkt aus dem Internet erreichbar.
Container starten
docker compose up -d
docker compose ps
docker compose logs --tail=100 ghost
Nginx als Reverse Proxy
Für die Domain kann ein schlanker Serverblock so aussehen:
server {
listen 80;
listen [::]:80;
server_name blog.example.de;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name blog.example.de;
ssl_certificate /etc/letsencrypt/live/blog.example.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/blog.example.de/privkey.pem;
location / {
proxy_pass http://127.0.0.1:2368;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto https;
}
}
Ghosts offizielles Docker-Image weist für Produktionsbetrieb ausdrücklich auf HTTPS sowie passende X-Forwarded-For-, X-Forwarded-Host– und X-Forwarded-Proto-Header hin.
Nginx testen
sudo nginx -t
sudo systemctl reload nginx
Danach erreichst du Ghost Admin unter:
https://blog.example.de/ghost/
Ghost aktualisieren
Vor größeren Versionssprüngen: Backup und Release Notes lesen. Für normale Image-Updates:
cd /opt/ghost
docker compose pull
docker compose up -d
Ich würde Ghost nicht blind in irgendeine nächtliche Auto-Update-Schleife werfen. Warum, erkläre ich in Docker-Container 2026 sicher aktualisieren.
Favicon und Branding
Nach der Installation brauchst du für ein normales Favicon keine alten Server-Tricks mehr. Ghost besitzt dafür das Publication Icon im Adminbereich. Dazu gibt es ebenfalls eine aktualisierte Anleitung: Favicon und Apple Touch Icon in Ghost einrichten.
Alternative: klassische Ghost-CLI
Ghost 6 lässt sich weiterhin ohne Docker auf dem offiziell unterstützten Ubuntu-/Node-/MySQL-/Nginx-Stack installieren: Ghost 6 unter Ubuntu 24.04 mit Ghost-CLI installieren.
Fazit
Wenn Nginx ohnehin auf dem Host läuft, brauche ich keinen zusätzlichen öffentlich erreichbaren Webserver-Container. Ghost und MySQL bleiben sauber im Docker-Umfeld, Ghost lauscht ausschließlich lokal und Nginx übernimmt TLS und den öffentlichen Zugriff.
Quellen: Docker Official Image: Ghost, Ghost: Docker Compose preview und Ghost: Ubuntu installation.
Wie ist deine Meinung?
Schreib gern einen Kommentar unter dem Artikel oder diskutiere mit anderen im Matrix-Kanal:
#dasnetzundich:matrix.org
… hat dies repostet!
… hat dies repostet!
… hat dies repostet!
… hat dies repostet!
… hat dies repostet!