Ghost zu Docker migrieren

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
docker-compose.yml

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
ghost/docker-compose.yml
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
mysql/docker-compose.yml

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.

Kommentare anzeigen

Wir nutzen Cookies

Um die Nutzung der Website zu verbessern, nutzen wir Cookies.
Desweiteren werden Google-Dienste für das schalten von Werbung verwendet. Mit der Nutzung der Website geben Sie ihr Einverständnis.
Sollte die Nutzung von Cookies abgelehnt werden, kann dies Auswirkung auf die Nutzung der Website haben.