A New, Better Way to Automatically Update Docker Containers
How I created Ouroboros, a Python-based Watchtower alternative which focuses on readability.
It Just Works
Docker is the buzz these days, right? Package your application with a
Dockerfile, build, push to a registry and somehow get it to your cloud provider. There are a million ways to skin this cat. 🐱
The reality of it is, someone sets up a container somewhere that “just works” and often forgets about it. I’ve seen a single container run for months on end. This results in missing functionality from newer versions of an application or—even worse—can lead to potential security vulnerabilities, all because somebody was too lazy to update the image and recreate the container on their on-prem server or in the cloud.
The proper way to handle such a scenario is to utilize rolling updates using Kubernetes or Docker Swarm, but to most developers, these are black boxes that “only ops people know how to use.” So what happens now? Usually a developer will just issue a
docker run... and say, “Cool, my app is deployed, now consumers can quit hounding me.”
It’s not ideal… but again… the reality.
Updating the Container
docker stop ...
docker rm ...
docker pull ...
docker run ...
Yep, we know how that goes.
Automate the Process
There’s a popular open source project called Watchtower that has the ability to “watch” running Docker containers on either the same local or remote host, check if there is a newer image in the remote registry, and then update the container with the new image using the same configuration options it was instantiated with. Pretty cool right?
This application really intrigued me, so naturally I started digging through the source, which is written in Go. The issue was I couldn’t follow a lot of what was going on in the application due to its lack of readability. I’m not a Go expert, but can still follow logic in most cases. This was not one of those cases…
I thought it was natural that it was written in Go since, well, Docker is. I knew there were two Docker SDK options available in Go and Python, so I thought to myself, “OK, Watchtower is the Go version of auto-updating containers, where’s the Python version?” Well, guess what… it didn’t exist.
Reinventing the Wheel
I was somewhat shocked to see someone had not done a similar thing using the Docker Python SDK. And so went the thought process, “Hey, I dig Python. I’ll try my hand at it.” It is the Hacktoberfest season after all.
After a weekend of playing with Docker Python SDK, I saw how feasible the implementation would be and had something minimal working.
I was pretty excited. Thus, Ouroboros was created!
Ouroboros is a Watchtower alternative which focuses on readability and of course is written in Python 3.
Really, not all that much. Watchtower has a few more bells and whistles, but my hope is that the open source community likes the Python implementation enough to chip-in feature wise.
It still performs the necessities of recreating the containers with the same options they were instantiated with, won’t bring down containers unless the new image has a different hash,
docker-compose compatibility, and Ouroboros can even update itself if you choose to do so!
How Do You Use It?
Ouroboros itself runs as a Docker image and interacts with the Docker API using the local socket.
By default, Ouroboros will wait 5 minutes in between polling the current image’s tag, but you can also provide a flag to go straight to
latest if you live dangerously.
So now you only need to set up your containers and Ouroboros once, then just wait. Your deploy stage would now just consist of pushing an updated tag to the registry and letting Ouroboros do the rest.
It should be mentioned that Ouroboros should only be utilized as a rapid prototyping tool in test environments—exposing the Docker API in production is bad and is a security risk.
Plus, you wouldn’t really want auto updates in production now, would you? Or maybe you do, your call.
So Much Configuration
Ouroboros does support many different configuration options, such as:
- Monitor and update containers on multiple remote servers running Docker
- Monitor the current image tag or go straight to
- Ignore specific containers
- Support for private registries
- Customize the polling interval
- Monitor select containers by name
- Change logging level for debugging/suppression
- Run ouroboros only one time to update, then terminate itself
- Remove old Docker image when creating a new container
- Exports Prometheus, Influx metrics to go on your Grafana Dashboard!
- Can trigger multiple webhooks when containers are updated. Supports discord, slack, pushover, and generic webhooks
- Can send emails when containers are updated
I can see how this wouldn’t work for everybody. In some cases, myself included. Regardless:
- I had a good time doing it.
- It actually turned into a decent sized open-source project.
- Learned better Python testing methodologies.
- The repo’s source can serve as a good example on how to interact and automate with the Docker API.
- I gave back to open-source for Hacktoberfest.
After a rapid increase in popularity and demand, Ouroboros has moved under its own organization called pyouroboros! The project was completely rewritten to be object-oriented with a ton of new features!
Thanks to a new maintainer (DirtyCajunRice), this project is going places!
Be sure to check out the wiki!