Upgrading Self-Hosted Dockerized Ghost Blog to Ghost V2
Previously I wrote about how I moved my old blog from Drupal to Ghost, and lived happily ever after.If you don't wanna read it, tl;dr: my blog now runs off a very tiny digital Ocean Droplet from a docker container.
I try to write blog regularly, and today I had a different topic in mind, but when I logged into the ghost control panel, I was greeted with a message that a new version of Ghost has been released. And not just a minor version, it's a shiny new major release. I was super intrigued. I jumped on the migration documents, but there was nothing on the Docker version. went to docker hub ghost page and looked for the upgrade documentation there, but no luck. I had to figure it out myself. for my setup: I also had a Volume configured for data persistency. And for me, It took some failed attempts before I had success upgrading. Here are the things I did:
Disclaimer: If you are planning to do anything similar: be sure to take a backup / snapshot of the server first. I did the same. The commands are dangerous and might accidentally kill John Wick's dog.
btw, You can skip the Failed attempts for saving time. However you can read them for the sake of fun and science.
Failed Attempt # 1:
I accessed the server with ssh
and updated my docker-compose.yml
file. I changed ghost version from 1.25
to 2
there. Then rebuilt the container. And it failed miserably. The docker container was shutting down immediately after starting up.Maybe because it was trying to load old version's configuration from the volume. I rolled back the changes.
Failed Attempt # 2:
I was reading through the step-by-step guide on how to migrate to v2 using the ghost
CLI tool and I thought to myself: Wait a minute! shouldn't there be an instance of the CLI inside the docker container? How about I use it to update from inside the container. So from inside the ghost folder in the server, I accessed the shell of the container with:
docker-compose exec ghost sh
And yeah! there's a ghost CLI inside. I went to the ghost directory /var/lib/ghost
and tried to run ghost update
and it complained that CLI cannot run as root. I tried to add a new user, install sudo, give the user sudo permission and ran the command as that user only to find out there's a new error. I was frustrated and also thought this will never be a good portable solution. It also conflicts with the reason I wanted to do it with Docker in the first place. So I trashed that idea too.
Successful Attempt:
I logged into the ghost control panel of my blog and from the Labs section, chose export content. It downloaded as a JSON file.
Then accessed server with ssh
, went to the ghost directory with my docker-compose.yml
file and stopped the docker container(s) with the command:
docker-compose stop
then I created a new directory outside, copied the docker-compose.yml
file.Then I opened the compose file, changed two things there.
- Changed ghost version to
2
- and changed the volume to a new one, keeping the mount point same inside the container.
If you are using named volumes, change the name, so that it creates a new volume and doesn't use the old one. If you are using bind mounts like me, change the host folder to a new folder.
Once that was done, I started up the container(s) from the new compose file with the command:
docker-compose up -d
And the blog was up again as a fresh instance running Ghost V2. I created an account and then cleaned up the default posts. Then went to the labs section. And from the import section, imported the backup (export) JSON file.
And all my contents, Settings, and even analytics code injections were instantly imported. The blog posts that were using unsplash images, also got the images. But the only remaining problem was the uploaded images I used in the posts. They were missing. To fix that problem, I went into the old bind mount folder and copied the images
folder to the new mount folder.
And my blog was up and running again, fully functional with Ghost v2.
Cleaning Up:
I downloaded the old mount folder and then deleted it from the server. I also removed old version ghost docker container and images. I did these mainly because I wanted to use as less space on the server as possible.
This method worked for me, but still it's not the official method yet, Please do it at your own risk.