DEV Community

Oracle Sean  ♠️
Oracle Sean ♠️

Posted on • Originally published at Medium

Visual Docker: Images are Immutable

Changing an image alters the rules mid-game

This is the second article in a series dedicated to visually explaining Docker and container concepts using a game of Tic-Tac-Toe and little or no code. It's focused on image immutability and tags, and demonstrates why images can't change.

The last post in this series used a game of Tic-Tac-Toe to show how containers are thin layers projected onto images. The image is the Tic-Tac-Toe board and includes the game's rules. It's shared by every Tic-Tac-Toe game container. Individual containers are layers that start out empty. As players add moves, they're recorded in the container layer.

The game only makes sense when you see both pieces together. On its own, the container layer is just random X's and O's. The game board in the image is perpetually empty because it can't change. In the container world, we say that images are immutable and, therefore, also stateless since altering the state requires saving those changes somewhere.

Change ≠ Replace

Is that really true, though? After all, I can change a Dockerfile and rebuild the image using the same name, which would seem to change the image. More accurately, I replaced the old image and assigned the same name.

It's an important distinction. To illustrate why, let's list the images on the system:

> docker images
REPOSITORY   TAG           IMAGE ID       CREATED      SIZE
games        tic-tac-toe   ec616ed52b3b   1 hour ago   100KB
Enter fullscreen mode Exit fullscreen mode

Then, start a new game container using that image. The "friendly" image name is its REPOSITORY and TAG, joined by a colon:

docker run games:tic-tac-toe
Enter fullscreen mode Exit fullscreen mode

When I list the containers running on my system, I see my game:

> docker ps -a
CONTAINER ID  IMAGE        COMMAND           CREATED       STATUS                 PORTS   NAMES
f8763546a856  ec616ed52b3b "/bin/tictactoe"  1 minute ago  Up 1 minute (healthy)          abundant_fun
Enter fullscreen mode Exit fullscreen mode

Inside the container, players make a series of moves ending in a stalemate:

Recall that the moves are saved in the container layer, but the game board and all of the rules are part of the image. What if I could change the existing image used by a running container? Perhaps rewriting the Dockerfile and shifting the board to the right:

If the container used the changed image, moves in the leftmost column of the container layer would fall off the board, while three new spaces open up on the right! The game is no longer a stalemate! Now, Player O has two paths to victory courtesy of the repositioned game board in the new image, and Player X can block only one!

That demonstrates what would happen if you could change an existing image. But it does raise a question: what happens when you replace an image?

The Repo

Recall the original image was named games:tic-tac-toe. If there were no containers using the image, Docker simply removes and replaces the image. But in the example above, a container was using the "old" image. So, does Docker respond by removing the container? Does it crash or stop responding when its image is replaced? Fortunately not!

In this case, Docker preserves the original image by un-tagging it—removing the friendly name—making the games:tic-tac-toe tag available to the newly built image. Once untagged, the image no longer has a friendly name, which I'll see when I once again list the images on the system:

> docker images
REPOSITORY   TAG           IMAGE ID       CREATED       SIZE
games        tic-tac-toe   2fafb511dc00   1 hour ago    100KB
<none>       <none>        ec616ed52b3b   2 hours ago   100KB
Enter fullscreen mode Exit fullscreen mode

One shows <none> for the REPOSITORY and TAG. Look closely, and you'll see the IMAGE ID matches the original image. By rebuilding the image, Docker untagged the old one but didn't delete it! Any containers that used the "old" image continue to work as before, without any change!

If you see <none> listed for an image repository and tag, it just means it was untagged or replaced while still in use by a running container.

Top comments (0)