Recently, I have been reviewing a massive collection of Dockerfiles and interacting with customers and ISVs alike. In this time, I have seen all sorts of actions being taken for container design and how those containers should be run. One such action I really struggle with is when users are either told or take the initiative themselves to update packages within a running container. For example, they execute something like:
docker run -it foobar yum -y update
While there could be a litany of reasons for doing this, consider the potential consequences:
- Only the container itself is updated, the image remains unchanged
- If you were running 10 of these containers, that would result in 10 separate yum updates
- With multiple updated containers, perhaps at different times, each container could potentially have different packages in it.
- The author of the image may not have tested with the updated packages and therefore you may encounter undesirable results.
That said, there are certainly a lot of images on various registries that have grown stale or are not updated with the frequency users desire. Clearly, in this case, it would be ideal if there was an automated build service from the provider to rebuild the images if its packages were updated.
Absent of that, I think there is a better way. If we follow the container paradigm, it would be more prudent to update the image in question rather than the container. This can simply be done with Docker, where you would use the image from the registry as a seed image and then run yum update
to create a new image. The Dockerfile could be as simple as:
# Use the image from the registry as a seed
FROM 192.168.122.161:5000/foobar
# Run yum update and then clean the cache
RUN yum -y update && yum clean all
Then build the image and name it with some obvious marker to differentiate it:
docker build -t foobar-updated .
Now, instead of running an image based on foobar
, use foobar-updated
instead.
By following this paradigm, you will now be able to push the image through your lifecycle testing and verify functionality. All you need to do is stop the existing containers and start new ones based on your newly updated image. You will now have consistent and well-formed images.
atomic verify Can Help
The verify
subcommand of the atomic application can also be helpful in this scenario. It can be used to determine if an image or its layers have been updated. verify
uses the Version
label to store its version as metadata within the image. For more information about labels, see the ContainerApplicationGenericLabels GitHub repository. Carrying our example from earlier, suppose we have pulled our foobar image from a registry, like so:
docker pull 192.168.122.161:5000/foobar
Using the advice from above, we can then use that image as a seed image to rebuild foobar
having run a yum update
and now have a foobar-updated
image present on our system. This can be observed with using Docker:
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
foobar-updated latest 9045d1c4d8c0 5 minutes ago 194.7 MB
192.168.122.161:5000/foobar latest ff7d910bca97 7 minutes ago 194.7 MB
Supposing the foobar image is updated, we can use atomic verify
to identify that:
# sudo ./atomic verify -v foobar-updated
foobar-updated contains the following images:
Local Version Latest Version
------------- --------------
foobar-updated-1.0-5-updated foobar-updated-1.0-5-updated
foobar-1.0-5 foobar-1.0-6 *
* = version difference
Notice how the version level has been updated from 1.0.5 to 1.0.6 on the remote registry. This is a sign we should now use the new version on the registry and, if desired, rebuild our local -updated
version updates as needed.