Introduction
First, let me start by saying that I love Ghost. While this site isn’t built on it since it doesn’t quite align with my goals here, Ghost has been a perfect fit for several other projects I’ve worked on. After running smoothly for over two years, I decided it was time to apply a major upgrade and take advantage of all the new features ghost has to offer.
However, there was a catch—my current database wasn’t supported, and as it turns out, upgrading from MySQL 5 to 8 can be tricky under certain circumstances.
My Ghost blog is running via Docker, and this setup may have complicated things when I followed Ghost’s official upgrade documentation. I encountered issues where the upgrade either failed outright or appeared to succeed but caused my site to run sluggishly.
After much trial and error, I finally figured out a solution, and I hope this guide helps anyone else facing the same challenges. Here’s what my docker-compose.yml file looked like before the upgrade:
version: '3'
services:
ghost:
image: ghost:4.44
restart: always
depends_on:
- db
environment:
url: example.com
database__client: mysql
database__connection__host: db
database__connection__user: root
database__connection__password: ${GHOST_DB_PASSWORD}
database__connection__database: ghost
volumes:
- /opt/ghost_content:/var/lib/ghost/content
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- /opt/ghost_mysql:/var/lib/mysql
nginx:
build:
context: ./nginx
dockerfile: Dockerfile
restart: always
depends_on:
- ghost
ports:
- "80:80"
- "443:443"
volumes:
- /etc/letsencrypt/:/etc/letsencrypt/
- /usr/share/nginx/html:/usr/share/nginx/html
The first thing I did was ensure I had a recent backup—trust me, this process can fail, and you’ll be glad you have one.
While it might be tempting, simply changing the image versions:
image: ghost:4.44
image: mysql:5.7
to
image: ghost:latest
image: mysql:latest
s too good to be true, and I can confirm that it’s not the solution.
What did work? After some trial and error, I found success by creating a backup of my existing database:
docker exec your-db-container mysqldump -u your-username -p your-database > /path/to/backup.sql
Next, I spun up a version of MySQL 8 alongside my existing services:
version: '3'
services:
ghost:
image: ghost:5.82.11
restart: always
depends_on:
- db
environment:
url: example.com
database__client: mysql
database__connection__host: db2
database__connection__user: root
database__connection__password: ${GHOST_DB_PASSWORD}
database__connection__database: ghost
volumes:
- /opt/ghost_content:/var/lib/ghost/content
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- /opt/ghost_mysql:/var/lib/mysql
nginx:
build:
context: ./nginx
dockerfile: Dockerfile
restart: always
depends_on:
- ghost
ports:
- "80:80"
- "443:443"
volumes:
- /etc/letsencrypt/:/etc/letsencrypt/
- /usr/share/nginx/html:/usr/share/nginx/html
db2:
image: mysql:8
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- /opt/ghost_mysql_new:/var/lib/mysql
Then, I loaded the backup into the new MySQL 8 container:
docker exec -i new-db-container mysql -u youruser -p your-database < /backup.sql
Once that was done, I switched my Ghost container to use the new database:
ghost:
image: ghost:5.82.11
restart: always
depends_on:
- db2
After confirming everything was working smoothly, I updated Ghost to the latest version:
ghost:
image: ghost:latest
This solved the issue entirely. At this point, I no longer needed the old database, so I shut it down.
While this isn’t a comprehensive guide, I hope it helps if you find yourself in a similar situation.