Zum Inhalt

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 2368 im 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]

openssl rand -base64 24

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:

mkdir -p ~/ghost && cd ~/ghost

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 Port 2368 wird nach außen freigegeben.
  • url: Die öffentliche Adresse des Blogs. Für den ersten Test reicht http://localhost:2368. Bei Produktion mit Domain und HTTPS änderst du diesen Wert später auf https://deine-domain.de.
  • database__client, database__connection__*: Ghost-Konfiguration per Umgebungsvariablen. Die doppelten Unterstriche ersetzen die verschachtelte Config-Struktur von Ghost (z. B. database.client wird zu database__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:

docker compose up -d

Die erste Initialisierung dauert 30 bis 60 Sekunden, weil MySQL die Datenbankstruktur anlegt und Ghost anschließend sein Schema erstellt. Verfolge den Fortschritt mit:

docker compose logs -f

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:

http://<server-ip>:2368/ghost/

Ersetze <server-ip> durch die IP deines Docker-Servers, zum Beispiel 192.168.1.20.

Du siehst den Einrichtungsassistenten:

  1. Site title: Titel deines Blogs (z. B. „Mein Blog")
  2. Full name: Dein vollständiger Name
  3. Email address: Deine E‑Mail-Adresse (wichtig für Passwort-Reset und optional später für Newsletter)
  4. Password: Ein sicheres Passwort für den Admin-Zugang
  5. 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:

http://<server-ip>:2368/

Du solltest den Standard-Blog mit deinem Titel sehen. Klicke auf einen Beispiel-Beitrag oder schreibe einen eigenen Testbeitrag:

  1. Im Dashboard links auf Posts klicken
  2. Rechts oben auf New post klicken
  3. Einen Titel und etwas Text eingeben
  4. 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 Einstellungen
  • ghost-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:

docker compose up -d

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 → Email ein.

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 → Design kannst du ein neues Theme hochladen oder die Schriftarten anpassen.
  • Newsletter einrichten: Ghost bringt ein integriertes Newsletter-System mit. Unter Settings → Email trä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 → Membership die 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 -d aktualisiert 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.