Jan 4, 2023 2 min read

The docker compose Pitfall: Why Your Docker Container's Image Isn't Updating Despite Changes to the Dockerfile

The docker compose Pitfall: Why Your Docker Container's Image Isn't Updating Despite Changes to the Dockerfile
Table of Contents

If you use a build attribute in your docker-compose.yml file to build an image locally, you may be surprised to find that you cannot update the Docker container to the latest image using the standard method for updating a docker compose container. i.e.: docker compose pull && docker compose up -d. Here is how to fix that.

ℹ️
N.B. "docker-compose" has been replaced by "docker compose". I will use the terms interchangeably in an effort to help those who may be using one version or the other find this article in a search.

Docker Compose Build Attribute

In case you're not sure what I mean by the docker-compose build attribute, here is an example: [insert docker-compose.yml example here]

pihole:
  container_name: pihole
  build: .

In the same directory as the docker-compose.yml file, a Dockerfile exists that looks something like this:

FROM pihole/pihole:latest

RUN apt update && \
    apt install -y nano iptables

In the above example, the Dockerfile exists in the same directory as the docker-compose.yml file. When we specify the build attribute, we tell docker compose to build a new Docker image when we run docker compose pull and to look in the directory specified to find the relevant Dockerfile.

Why Doesn't Docker Compose Update the Docker Image When Running "Docker Compose Pull"?

The above example will run great the first time but, on subsequent docker compose pull commands, you will find that the associated Docker container does not update even though the underlying Dockerfile specifies to pull the image FROM the latest tag. So why is docker compose not updating the docker container?

Well, the reason is because how docker compose pull works. The first time it is run with a docker compose file that specifies to build a local image, docker compose builds that image and then tags it in the format <project>-<service>:latest. Since that image and tag exist only locally, docker compose pull sees that image as the latest (however outdated it may be, because it's literally labeled as the latest even if it isn't) and pulls it. Not particularly useful.

Incidentally, this is why we don't have this issue when we're using docker compose with an image from a repository. In the case of a repository, the image with the latest tag actually has been updated and therefore, when it is pulled, you actually get an updated Docker image.

How To Update a Docker Compose Container

How to Update a Docker Compose Container That Uses a Locally Built Image (i.e. the build attribute)

If, in your docker-compose configuration, you've specified a Dockerfile to build the image locally (i.e. you're using the configuration in the example above), you can simply use the following command:

sudo docker compose down && sudo docker compose build --no-cache && sudo docker compose up -d

How to Update a Docker Compose Container That Uses an Image from a Repository

If, however, you aren't using docker compose to build a local image and are instead using a Docker image from a repository, you can continue to use the traditional sudo docker compose up && sudo docker compose -d without issue.

Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to The Engineer's Workshop.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.