The misunderstood Docker tag: latest
Docker images have a tag named latest which doesn’t work as you expect. I’ve listened to numerous speakers and Docker 101 talks only to see this misrepresented too often. Because tags and versions are so very instrumental in almost all deployment processes, it’s very important to fully understand how they work before designing a production deployment process that involves Docker.
To illustrate how the latest tag actually works, let’s create a pretty basic Dockerfile. The contents of this are here:
FROM busybox:ubuntu-14.04RUN echo “#!/bin/sh\n” > /test.sh
RUN echo “echo \”this is version 1\”” >> /test.shENTRYPOINT [“sh”, “/test.sh”]
(This is just an example and I wanted to exclude external dependencies, so forgive the echo-to-build-a-script-file thing happening here)
Because I want to push this image to Docker Hub, I’m going to build, tag and version my image.
sudo docker build -t marc/test .
Next, I should test the image to make sure it works:
$ sudo docker run marc/test
this is version 1
That’s exactly what I expected. But I’m planning to have future versions of my image, so I’m going to tag this as version 1:
sudo docker tag marc/test marc/test:1
Now, I’m going to push this to Docker Hub using:
$ sudo docker push marc/test
The push refers to a repository [marc/test] (len: 2)
Sending image list
Pushing repository marc/test (2 tags)
511136ea3c5a: Image already pushed, skipping
... (truncated)
Cool. It pushed. It’s safe on Docker Hub and I can even see it on their UI:
I can pull it, everything is fine. But now it’s time for an update to my image. I replace the contents of the Dockerfile with these new and improved contents:
FROM busybox:ubuntu-14.04RUN echo “#!/bin/sh\n” > /test.sh
RUN echo “echo \”this is version 2\”” >> /test.shENTRYPOINT [“sh”, “/test.sh”]
Repeating the process, I’m going to build this, tag it and push it to Docker Hub:
sudo docker build -t marc/test:2 .
sudo docker push marc/test
Now I want to run my new image:
$ sudo docker run marc/test
this is version 1
Hmph. I was expecting 2? Ok, let’s pull this from Docker Hub:
$ sudo docker pull marc/test
Pulling repository marc/test
fdf416e5c66e: Download complete
511136ea3c5a: Download complete
df7546f9f060: Download complete
e8a999563c47: Download complete
f6169d24347d: Download complete
d3dbb7dd473f: Download complete
304a1af73537: Download complete
Status: Image is up to date for marc/test:latest
$ sudo docker run marc/test
this is version 1
That’s still version 1. Ok, let’s explicitly pull the latest version:
$ sudo docker pull marc/test:latest
Pulling repository marc/test
fdf416e5c66e: Download complete
511136ea3c5a: Download complete
df7546f9f060: Download complete
e8a999563c47: Download complete
f6169d24347d: Download complete
d3dbb7dd473f: Download complete
304a1af73537: Download complete
Status: Image is up to date for marc/test:latest
$ sudo docker run marc/test
this is version 1
And it’s still version 1. But I created a version 2 and pushed it after I pushed version 1. What’s going on here?
Latest is just a tag with a special name.
It doesn’t mean anything special unless you use a pretty specific build/tag/push/pull/run pattern.
“Latest” simply means “the last build/tag that ran without a specific tag/version specified”.
In other words, you could build new versions like this:
sudo docker build -t marc/test .
sudo docker tag marc/test marc/test:2
...
sudo docker build -t marc/test .
sudo docker tag marc/test:3
...
But this is a little odd. Why would I have to tag everything twice?
If you are shipping Docker images to a production environment, you should just ignore the latest tag. Don’t use it. Don’t be tempted by it. It’s easy to look at it and think that your deployment script should just pull “latest” and your build process will ensure that’s valid. It takes a lot of discipline to make that work. Just version your tags. Every time.
— -
If you’re using Docker to ship your SaaS application, you should check out www.Replicated.com to power an enterprise, installable version of your product.