Upgrade to Ghost v4 with Docker Compose
When Ghost 4 was released earlier this year, I've looked into the upgrade from the initial v3 based setup in docker-compose. Unfortunately, the container based setup is not officially supported, and there were no upgrade guides available.
Time goes by, and after the 3rd time googling for Ghost 4 Docker upgrade
, thankfully I've found more resources. I'll document my learning story in this blog post; if you are only interested in the solution, do the backup and skip to the 2nd attempt.
Preparations: Backup Ghost
- Navigate to the admin interface into
Settings > Labs
and export all data - SSH into the server and take a copy of the
content
directory. Also, connect to the database container and take a full DB backup.
First attempt: Docker exec live upgrade
I wanted to perform the same ghost-cli steps shown in the official guide, and later persist the Docker image using the same software versions from v4. This was suggested in this post.
First, ensure that docker-compose.yml
is using a pinned image version. I made the mistake of using ghost:latest
in my original installation.
ghost-server:
image: ghost:3
Second, pull the latest image for v3 and boot into it. The reason is that NodeJS is a custom installation on /usr/local/bin/node
and all attempts to upgrade the NodeJS using apt or apk package managers will fail.
$ docker compose pull && docker-compose down && docker-compose up -d
$ docker ps
$ docker exec -ti <id> bash
node -v
which node
/usr/local/bin/node
npm install -g npm
npm install -g ghost-cli@latest
Changing to the node user and running ghost update
led to file permission problems, which are shown as a first command:
$ find ./ ! -path "./versions/*" -type f -exec chmod 664 {} \;
$ su node
$ ghost update
Unfortunately I changed my setup from SQLite as default, to MySQL ... and the detection failed. At this point, I gave up trying to trick the CLI into the container image upgrade.
Second attempt: Docker image upgrade
Stop the containers with docker-compose down
and run docker-compose up
in foreground to see the CLI and database operations. From there, I figured that every Ghost startup does software and database sanity checks and applies missing DB migrations. Both containers start and Ghost does a cyclic check to verify the database being available.
Using this knowledge, I've edited the docker-compose.yml
and tried the upgrade directly.
ghost-server:
image: ghost:4
$ docker compose pull && docker-compose down && docker-compose up -d
It worked :-)
Third attempt: MySQL 8 upgrade
MySQL 5.7 is EOL in October 2023, still, I prefer to stay up-to-date with MySQL 8. Ghost added support for MySQL 8 - there is one shortcoming though with a changed authorization plugin causing troubles with plain text passwords.
Thanks to this issue comment, I did not run into problems and added the command directly into docker-compose.yml
prior to upgrading the DB base image.
ghost-db:
image: mysql:8
restart: always
command: --default-authentication-plugin=mysql_native_password
After pulling & restarting the docker-compose setup, everything works like a charm, as you can see :-)
The blog post live preview (screenshot in the header) is amazing. 😍
PS: The full docker-compose.yml
looks like this:
version: '3'
services:
ghost-server:
image: ghost:4
restart: always
ports:
- 2368:2368
depends_on:
- ghost-db
environment:
url: https://dnsmichi.at
database__client: mysql
database__connection__host: ghost-db
database__connection__user: root
database__connection__password: supersecret
database__connection__database: ghost
volumes:
- /docker/ghost/content:/var/lib/ghost/content
ghost-db:
image: mysql:8
restart: always
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: supersecret
volumes:
- /docker/ghost/mysql:/var/lib/mysql