Update Docker images when base image changes

Roundcube Webmail is also available as Docker images in various flavors. All of them use the official PHP builds as base image. Because Roundcube releases are way less frequent than PHP updates and the latter ones are often security relevant and therefore critical for production systems serving Roundcube from a Docker image, we needed to find a way to automatically re-build our images when the underlying PHP image changes. Although Docker Hub has a feature to trigger automatic builds when base images changes, this apparently doesn’t work with official base images like PHP is one. Thus we came up with our own solution to automate the monitoring and re-build of Docker images.

Blueprint

So what do you need for this?

  • A script to check the latest build date of the base image
  • A persistent storage of the last check or build date
  • A webhook to trigger Docker builds
  • A cron job or service to periodically run that script

Because we don’t have a dedicated server to install and run arbitrary cron jobs and you don’t what to do run this on your workstation, a cloud service can do this. The most popular candidates are AWS Lambda or Google Cloud Functions. Both providers also come with services for persistent storage. And both providers have plans that offer basic usage of their services for free. Our function only needs to run once a day and therefor we’d stay below the limits and quota of the free plans. Great!

The solution

We first tried AWS Lambda but the setup with a Redis store, virtual networks and all the necessary routing turned out to be way too complicated if you’re not already an AWS master. Setting up a Google Cloud Function with a Firebase database was much easier and straight forward for the rather simple use case of ours.

The setup is very simple. First, register at the Google Firebase Console and create a new project. Second, make yourself familiar with Google Cloud Functions and create a new database for persistent storage. Our weapon of choice was JavaScript to write the function. Third, register a webhook to trigger builds at Docker Hub. A simple POST request can be sent from the cloud function to fire a new build. Finally, register your function at the Cloud Scheduler to run periodically and without direct interaction. This is as simple as registering a Pub/Sub event that is triggered by a Cloud Scheduler job. The SDK even provides a function for this:

require('firebase-functions')
  .pubsub.schedule('0 9 * * *')
  .onRun(async (context) => {
    // your code here
  });

Note that for using the Google Cloud Scheduler you need to sign up for the “Blaze” plan which is still free for a limited number of executions.

All done. Our scheduled function now runs every day and fetches the build date of the PHP base images directly from the Docker Hub API and stores the dates in the Firebase database. If a build is newer that the stored date, the Docker Hub webhook is called to trigger a new build. The cloud function code is published as a Github Gist. Feel free to use and modify it for your own project.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s