Ghost per Docker installieren: Eigene Blog-Plattform für Texte, Newsletter und Mitgliederbereiche¶
Veröffentlicht am 6. Oktober 2026 · Geschätzte Lesezeit: 7 Minuten
Ghost ist eine auf Node.js basierende Open-Source-Publishing-Plattform, die sich auf schnelles Schreiben, integrierte Newsletter und Mitgliederverwaltung konzentriert. Die Einrichtung mit Docker und MySQL dauert etwa 30 Minuten und du erhältst eine moderne Blog-Umgebung, die ohne Werbung oder Tracking Dritter auskommt.[1][2]
Voraussetzungen
- Ein Linux-Server mit Docker und Docker Compose
- Ein freier TCP-Port
2368im Heimnetz (für den ersten Test; später leitest du HTTPS über einen Reverse Proxy wie Caddy oder Nginx weiter) - Die IP-Adresse des Docker-Servers
- Terminal-Zugriff mit
sudo-Rechten - Mindestens 1 GB freier Arbeitsspeicher
1. Datenbank-Passwörter festlegen¶
Ghost benötigt MySQL 8 als Datenbank-Backend. Lege zwei sichere Passwörter fest – eines für den Ghost-Datenbank-Benutzer und eines für den MySQL-Root-Zugang:[3]
Der Befehl erzeugt einen zufälligen String wie aB3xK9mPqR7vW2yL5nC8sT0uZ. Führe ihn zweimal aus und notiere beide Werte. Du brauchst sie in Schritt 2 für die Platzhalter GHOST_DB_PASSWORD und MYSQL_ROOT_PASSWORD.
Passwörter sicher aufbewahren
Die MySQL-Passwörter sind der einzige Schutz deiner Blog-Daten. Speichere sie in einem Passwort-Tresor (zum Beispiel Vaultwarden oder Bitwarden) und nicht in einer unverschlüsselten Textdatei.
2. Projektordner anlegen und Umgebungsvariablen hinterlegen¶
Erstelle einen eigenen Ordner für Ghost und wechsle hinein:
Erstelle eine .env-Datei mit den Zugangsdaten. Ersetze die Platzhalter durch die in Schritt 1 generierten Werte:
cat > .env << 'EOF'
GHOST_DB_PASSWORD=<ghost-datenbank-passwort>
MYSQL_ROOT_PASSWORD=<mysql-root-passwort>
EOF
Ersetze <ghost-datenbank-passwort> und <mysql-root-passwort> durch die in Schritt 1 generierten Werte.
| Platzhalter | Bedeutung |
|---|---|
<ghost-datenbank-passwort> |
Passwort für den Ghost-Datenbank-Benutzer |
<mysql-root-passwort> |
Root-Passwort für MySQL |
Die .env-Datei wird automatisch von Docker Compose eingelesen. Commite die Datei niemals in ein Git-Repository – füge sie stattdessen in eine .gitignore ein.
3. docker-compose.yml erstellen¶
Erstelle die Datei compose.yaml mit folgendem Inhalt:[1]
services:
ghost:
image: ghost:6-alpine
restart: always
ports:
- "2368:2368"
environment:
url: http://localhost:2368
database__client: mysql
database__connection__host: db
database__connection__user: ghost
database__connection__password: ${GHOST_DB_PASSWORD}
database__connection__database: ghost
volumes:
- ghost-content:/var/lib/ghost/content
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ghost
MYSQL_USER: ghost
MYSQL_PASSWORD: ${GHOST_DB_PASSWORD}
volumes:
- ghost-db:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
volumes:
ghost-content:
ghost-db:
Jeder Block hat eine bestimmte Aufgabe:
- ghost (Service): Startet den Ghost-Container auf Basis des offiziellen
ghost:6-alpine-Images. Der Port2368wird nach außen freigegeben. url: Die öffentliche Adresse des Blogs. Für den ersten Test reichthttp://localhost:2368. Bei Produktion mit Domain und HTTPS änderst du diesen Wert später aufhttps://deine-domain.de.database__client,database__connection__*: Ghost-Konfiguration per Umgebungsvariablen. Die doppelten Unterstriche ersetzen die verschachtelte Config-Struktur von Ghost (z. B.database.clientwird zudatabase__client).[3]db(Service): MySQL 8 als Datenbank mit eigenem Daten-Volume.healthcheck: Prüft alle 10 Sekunden, ob MySQL bereit ist. Ghost startet erst, wenn die Datenbank antwortet.volumes:: Zwei persistente Docker-Volumes für Ghost-Inhalte (Themes, Bilder, Uploads) und MySQL-Daten.
Zusammenspiel der Dienste¶
Der depends_on-Block mit condition: service_healthy stellt sicher, dass MySQL vollständ gestartet ist, bevor Ghost seine Tabellen anlegt. Ohne diesen Mechanismus würde Ghost starten, keine Datenbank finden und fehlschlagen.
4. Ghost starten¶
Starte den Stack im Hintergrund:
Die erste Initialisierung dauert 30 bis 60 Sekunden, weil MySQL die Datenbankstruktur anlegt und Ghost anschließend sein Schema erstellt. Verfolge den Fortschritt mit:
Sobald die Ausgabe Ghost booted oder ähnliche Meldungen wie INFO Creating table: zeigt, ist Ghost bereit.
5. Admin-Konto anlegen¶
Öffne einen Browser und rufe die Adresse deines Servers auf:
Ersetze <server-ip> durch die IP deines Docker-Servers, zum Beispiel 192.168.1.20.
Du siehst den Einrichtungsassistenten:
- Site title: Titel deines Blogs (z. B. „Mein Blog")
- Full name: Dein vollständiger Name
- Email address: Deine E‑Mail-Adresse (wichtig für Passwort-Reset und optional später für Newsletter)
- Password: Ein sicheres Passwort für den Admin-Zugang
- Klicke auf „Create account & start publishing"
Erster Besucher wird Administrator
Der erste Besucher der Seite /ghost/ wird automatisch zum Administrator. Lasse diese URL daher nicht offen im Internet zugänglich, bis du dein Konto angelegt hast. Ein lokaler Test über das Heimnetz ist sicher.
Nach der Anmeldung gelangst du ins Dashboard. Du kannst sofort den ersten Beitrag schreiben (Posts → New post) oder unter Settings das Aussehen anpassen.
6. Blog-Inhalte prüfen¶
Rufe die öffentliche Blog-Seite auf:
Du solltest den Standard-Blog mit deinem Titel sehen. Klicke auf einen Beispiel-Beitrag oder schreibe einen eigenen Testbeitrag:
- Im Dashboard links auf Posts klicken
- Rechts oben auf New post klicken
- Einen Titel und etwas Text eingeben
- Rechts oben auf Publish klicken
Der veröffentlichte Beitrag erscheint sofort auf der Startseite.
7. Backup und Wiederherstellung¶
Die wichtigen Daten liegen in zwei Docker-Volumes:
ghost-content: Themes, hochgeladene Bilder, benutzerdefinierte Einstellungenghost-db: Die eigentliche MySQL-Datenbank mit allen Beiträgen und Benutzern
Ein komplettes Backup erstellst du mit:
docker compose down
docker run --rm -v ghost-content:/data -v $(pwd)/backup:/backup alpine tar czf /backup/ghost-content-$(date +%F).tar.gz -C /data .
docker run --rm -v ghost-db:/data -v $(pwd)/backup:/backup alpine tar czf /backup/ghost-db-$(date +%F).tar.gz -C /data .
Die Sicherungen liegen dann im Unterordner backup/. Für die Wiederherstellung entpackst du die Archive an die gleiche Stelle und startest den Stack neu:
Eine elegantere Methode ist der Einsatz von docker compose exec db mysqldump zur laufenden Datenbanksicherung – siehe den Hinweis unter Erweiterte Tipps.
8. Risiken und Sicherheitshinweise¶
- Port 2368 nicht direkt ins Internet freigeben – Ghost liefert standardmäßig unverschlüsseltes HTTP aus. Setze stattdessen einen Reverse Proxy (Caddy, Nginx, Traefik) davor, der HTTPS mit Let's Encrypt bereitstellt. Eine Anleitung für Caddy findest du im Artikel Docker-Dienst mit Caddy und HTTPS absichern.
- MySQL aktualisieren: Das offizielle Ghost-Image wird regelmäßig aktualisiert (
ghost:6-alpine). MySQL 8.0 erhält noch Sicherheitsupdates, aber achte bei größeren Versionssprüngen auf die Ghost-Release-Notes. - Regelmäßige Backups: Ohne Backup sind alle Beiträge beim Verlust des Docker-Hosts weg. Richte eine automatische Sicherung ein (zum Beispiel mit restic, Duplicati oder einem Cron-Job mit
mysqldump). - E-Mail-Versand: Ghost benötigt einen SMTP-Server für Passwort-Reset-E-Mails und optional für Newsletter. Ohne SMTP-Konfiguration kannst du dein Passwort nicht zurücksetzen. Trage die SMTP-Daten nach der ersten Einrichtung unter
Settings→Emailein.
9. Typische Fehler und ihre Lösung¶
| Problem | Ursache | Lösung |
|---|---|---|
Connection refused beim Aufruf von Port 2368 |
Ghost braucht Zeit für die Initialisierung | docker compose logs -f ghost abwarten |
MySQL startet nicht – Fehler Can't connect to local MySQL server |
Port 3306 ist belegt | Prüfe mit sudo ss -tlnp | grep 3306 und stoppe den anderen MySQL-Dienst |
| Ghost zeigt „Page not found" | Die url-Einstellung passt nicht zur tatsächlichen Adresse |
Korrigiere url in der compose.yaml auf die echte Adresse und starte neu (docker compose up -d) |
/ghost/ leitet auf localhost weiter |
Die url-Variable zeigt auf localhost statt auf die Server-IP |
10. Nächste Schritte¶
- Domain einrichten: Weise eine Domain (z. B.
blog.deine-domain.de) per A‑Record auf deine Server-IP und setze einen Reverse Proxy mit HTTPS davor. - Theme anpassen: Unter
Settings→Designkannst du ein neues Theme hochladen oder die Schriftarten anpassen. - Newsletter einrichten: Ghost bringt ein integriertes Newsletter-System mit. Unter
Settings→Emailträgst du deine SMTP-Zugangsdaten ein (zum Beispiel von Mailgun oder deinem E-Mail-Anbieter). - Mitgliederbereiche: Ghost kann bestimmte Beiträge nur für angemeldete oder zahlende Mitglieder freigeben. Aktiviere unter
Settings→Membershipdie gewünschte Option.
Erweiterte Tipps¶
- mysqldump für laufende Sicherung: Sichere die Datenbank ohne herunterzufahren:
docker compose exec -T db mysqldump -u ghost -p"${GHOST_DB_PASSWORD}" ghost > backup-$(date +%F).sql - Ghost aktualisieren:
docker compose pull ghost && docker compose up -daktualisiert das Ghost-Image. Prüfe vorher die Ghost-Release-Notes auf Breaking Changes. - Performance: Für mehr als 10.000 Besucher pro Monat empfehlen die Ghost-Entwickler einen Redis-Cache und einen Reverse Proxy mit Static-File-Caching.[1]
Sources¶
[1] https://hub.docker.com/_/ghost — Official Ghost Docker Image [2] https://docs.ghost.org/install/docker — Ghost Official Docker Install Guide [3] https://ghost.org/docs/config — Ghost Configuration Options
Fertig¶
Nach dem Start unter http://<server-ip>:2368/ solltest du die Ghost-Startseite sehen. Klicke auf /ghost/, lege dein Admin-Konto an, schreibe einen ersten Beitrag und veröffentliche ihn. Prüfe, ob der Beitrag auf der Startseite und in der Beitragsliste erscheint. Der Blog läuft nun auf deinem eigenen Server – ohne Werbung, ohne Tracking, ohne monatliche Plattformgebühren.