No More Ugly Upgrades

No More Ugly Upgrades

Gone are the days I used to sit in front of a green screen sweating with fear as a cursor blinked in front of me. The upgrade command seemed to wrap several times around the screen with so many flags, switches and built in hacks that we use to play rock-paper-scissors to see who would hit the enter key and be ultimately responsible for the upgrade. Finally, we used to place a book on the spacebar to prevent the upgrade from going idle during the upgrade all while sleeping on server room floors. The book was our CI/CD tool.

Today, working with Docker & containers makes upgrades light years easier with a whole slew of additional options. Upgrading OS versions, Application versions or everything as a big bang if wanted is easier than ever. Do you want to upgrade with no downtime using Blue/Green deployments or how about rolling updates to upgrade? This is all possible. The most difficult part of upgrading today is deciding what and how to upgrade.

This blog is powered by Ghost and is also an official image on Docker Hub. The Ghost team seems to be increasing the rate of speed in which new features and releases become available. With the power of Docker Compose it is a matter of seconds not minutes or hours to upgrade to the next version.

When a new version of Ghost is released I quickly devour the release notes and understand everything about the upgrade, features and bug fixes. Next, I backup up my entire server with the AWS S3 CLI tool. The AWS CLI tool backups my Docker environment, container configs and data up just to ensure everything is current and it works really well (This runs daily as a cron as well). Finally, I pull the latest version of Ghost and restart my container. Done! Yeah, that's it. Pull, restart and go get another coffee is my upgrade procedure.

Ghost Configuration

Before we can run off and start upgrading things it's important to understand what is actually running in my Ghost environment. This blog setup includes a docker-compose.yml file which makes this entire process a lot easier.

The compose file includes pulling the image directly from Docker Hub instead of building it ourselves. Also, I store the data (DB, themes & images) in a data container which allows me to separate Ghost from the Application container. This allows Ghost to be upgraded and still persist data. Important if you want to keep your data.

Ghost docker-compose.yml file:

  ghost:
  image: ghost
    environment:
       - VIRTUAL_HOST=brianchristner.io
       - NODE_ENV=production
       - PUBLIC_URL=https://www.brianchristner.io
       - GHOST_CONTENT=/usr/src/ghost/content
       - GHOST_SOURCE=/usr/src/ghost

 volumes_from:
  - data-store
 ports:
   - "80:2368"
 restart: always

Ghost Configuration

Upgrading Ghost

So how does a standard Docker update look like in practice? We will use the Ghost compose file from above as our upgrade example. All these commands are run from the Ghost project directory.

  1. Run docker-compose ps. This tells us the current scenario and ensures everything looks correct before we begin.
    $ docker-compose ps

  2. Pull the latest image from Docker Hub. The pull is downloading the latest version and storing it locally on your Docker Host. Don't worry the old version is still available if need to rollback.
    $ docker-compose pull

  3. Restart the container.
    $ docker-compose restart ghost

  4. Grab a coffee and marvel at your achievement.

Ghost Upgrade

Conclusion

The Ghost upgrade example above is one of the many possibilities to upgrade a container. My blog is not mission critical so downtime is completely acceptable. The downtime in my upgrade is minimal and offline only for the time it takes to restart the container. However, if you require no downtime upgrades then it would be beneficial to look into Blue/Green deployments which creates 2 separate installations of your stack or rolling upgrades which upgrades each instance of your service allowing for multiple versions to run at the same time until the upgrade is complete. Don't forget if the upgrade fails it is just as easy to rollback to previous versions.

Whatever upgrade method you choose will contain pros and cons for your environment. However, these upgrade options is what makes Docker and containers so amazing. The ability to pick and choose our path rather than be forced down a monolithic upgrade path is what helps me sleep at night (No longer on server room floors).

Related Article