In diesem Artikel beschriebe ich, wie man von einer klassischen Ghost Installation auf Ubuntu in einen Docker Container migrieren kann.
Exportieren der alten Daten
Ghost speichert alle seine Daten in einer externen Datenbank, in meinem Fall MySQL. Um die Daten auf den neuen Server zu übernehmen, musste ich sie also aus der Datenbank exportieren. Das geht mit einem SQL-Dump.
mysqldump -u <user> -p <Name-der-ghost-Datenbank> > ghost.sql
So wird der gesamte Inhalt der Ghost-Datenbank in eine SQL Datei kopiert. Diese können wir per SCP auf den neuen Server kopieren.
scp ghost.sql <user>@<neuerServer>:/pfad/für/den/dockercontainer
Der Pfad für den Docker-Container ist frei wählbar. In meinem Fall habe ich ein extra Verzeichnis angelegt, in dem ich meine Container-Daten sammle.
Docker-Compose Stack erstellen
Um den Docker-Container zu starten nutze ich Docker-Compose. Hier können alle Parameter und Einstellungen des Containers in einer Datei geschrieben werden, ohne viele CLI Argumente zu nutzen. Dazu legt man im Verzeichnis des Docker-Containers die Date docker-compose.yml
an.
version: "3"
services:
mysql:
image: mysql:8.0.29-debian
container_name: mysql
restart: unless-stopped
volumes:
- ./db_data:/var/lib/mysql
- ./db_backup:/backup
networks:
- ghost_net
environment:
MYSQL_ROOT_PASSWORD: DatabasePassword
ghost:
image: ghost:4.47.1
container_name: ghost
expose:
- 2368
restart: unless-stopped
volumes:
- ./ghost_data:/var/lib/ghost/content
environment:
database__client: mysql
database__connection__host: mysql
database__connection__user: root
database__connection__password: DatabasePassword
url: https://blog.jrehkemper.de
networks:
- net #optional: Traefik Network
- ghost_net
depends_on:
- mysql
labels:
- "traefik.enable=true"
- "traefik.http.routers.ghost.rule=Host(`blog.jrehkemper.de`)"
- "traefik.http.routers.ghost.entrypoints=https"
- "traefik.http.routers.ghost.tls=true"
- "traefik.http.routers.ghost.tls.certresolver=production"
- "traefik.http.services.ghost.loadbalancer.server.port=2368"
- "traefik.docker.network=net"
networks:
ghost_net:
net: #optinal: Traefik Network
external:
name: net
Als Speicherort können natürlich auch richtigen Volumes genutzt werden, allerdings ist meine Backup-Strategie auf die Bind-Mounts ausgelegt.
Unter den Labels findet sich meine Traefik-Konfiguration. Sollte Traefik nicht genutzt werden, kann der Teil gelöscht werden. Dafür müssen aber die entsprechenden Ports beim Host freigegeben werden.
ports:
- 2368:2368
Am Ende startet man die Container mit docker-compose up -d
.
Daten in die Datenbank importieren
Als nächstes müssen wir unsere Daten in die MySQL Datenbank importieren. Dazu habe ich das Verzeichnis db_backup als Bind-Mount in den Container der Datenbank gemountet. Nach dort kopiere ich die ghost.sql
Datei.
Dadurch ist sie aus dem Container erreichbar und kann eingespielt werden.
Um Commands in dem Container auszuführen nutze ich Portainer als grafische Oberfläche, obwohl docker exec
natürlich auch funktioniert. In dem Container führe ich folgenden Befehl aus um die Daten zu importieren.
mysql -u root -p < /backup/ghost.sql
Das Passwort ist das in der docker-compose.yml
definierte Root-Password.
Ghost Medien kopieren
Als nächstes müssen die Medien, also Bilder, Screenshots, Themes etc. auf den neuen Server kopiert werden. Auf dem alten Server liegen diese unter dem Pfad /Pfad zu Themes
. Auch hier kann zum kopieren SCP genutzt werden.
scp -r /var/www/ghost/content <user>@<neuerServer>:/Pfad/zu/docker/ghost_data
ghost_data
ist hier wieder das Verzeichnis, das im Ghost-Container gemountet ist. So kann Ghost auch auf die Dateien zugreifen.
Nun muss der Container noch einmal neugestartet werden und der Ghost Blog sollte erreichbar sein.
docker-compose restart
Datenbank in anderem Stack nutzen
Wenn man mehrere Applikation betreibt, die eine Datenbank nutzen, ist es nicht unbedingt ratsam, für jede Applikation einen neuen Datenbank-Container aufzusetzen. Daher habe ich meine MySQL Datenbank in einem eigenen Stack mit PhpMyAdmin als grafische Verwaltungsoberfläche. Außerdem kann man so Container neu starten, ohne immer die Datenbank neustarten zu müssen.
Wichtig ist hierbei, dass alle Container, die auf die Datenbank zugreifen sollen, im gleichen Netzwerk sein müssen. Dazu habe ich ein externen Netzwerk angelegt.
docker network create mysql-net
Nun muss die Docker-Compose-Datei von Ghost angepasst werden und eine neue in einem neuen Ordner für den MySQL-Stack angelegt werden.
version: "3"
services:
ghost:
image: ghost:4.47.1
container_name: ghost
expose:
- 2368
restart: unless-stopped
volumes:
- ./ghost_data:/var/lib/ghost/content
environment:
database__client: mysql
database__connection__host: mysql_main
database__connection__user: root
database__connection__password: DatabasePassword
url: https://blog.jrehkemper.de
networks:
- mysql-net
- net
- ghost_net
labels: #optional for Traefik
- "traefik.enable=true"
- "traefik.http.routers.ghost.rule=Host(`blog.jrehkemper.de`)"
- "traefik.http.routers.ghost.entrypoints=https"
- "traefik.http.routers.ghost.tls=true"
- "traefik.http.routers.ghost.tls.certresolver=production"
- "traefik.http.services.ghost.loadbalancer.server.port=2368"
- "traefik.docker.network=net"
networks:
mysql-net:
external:
name: mysql-net
ghost_net:
net:
external:
name: net
version: "3"
services:
mysql:
image: mysql:8.0.29-debian
container_name: mysql_main
restart: unless-stopped
volumes:
- ./db_data:/var/lib/mysql
- ./db_backup:/backup
networks:
- mysql-net
environment:
MYSQL_ROOT_PASSWORD: DatabasePassword
phpmyadmin:
image: phpmyadmin:5.2.0
restart: unless-stopped
networks:
- mysql-net
- net
environment:
- PMA_HOST=mysql
- MYSQL_ROOT_PASSWORD=DatabasePassword
depends_on:
- mysql
labels:
- "traefik.enable=true"
- "traefik.docker.network=net"
- "traefik.http.routers.phpmyadmin.rule=Host(`example.de`)"
- "traefik.http.routers.phpmyadmin.tls=true"
- "traefik.http.routers.phpmyadmin.tls.certresolver=production"
- "traefik.http.services.phpmyadmin.loadbalancer.server.port=80"
networks:
mysql-net:
external:
name: mysql-net
net:
external:
name: net
Natürlich müssen auch hier die Daten des SQL Dump in die Datenbank importiert werden. Die Prozedur ist dabei die gleiche.
Nun hat man die Möglichkeit mehre Datenbanken auf dem gleichen Server zu verwalten. Allerdings sollte man darauf achten, für jeden Dienst einen Nutzer anzulegen, und diesen nur auf die entsprechende Datenbank zu berechtigen.