Mystery of changes not reflected on Docker container
I was recently working on a project where I needed to adjust an existing Dockerfile configuration to add a new database schema.
For a (then) mysterious reason, I couldn’t see the new database schema created in the database container as I had expected. It took me a while to figure this out. I am sharing this hoping this will save time for other developers facing a similar situation.
So what was happening? Why were the Dockerfile changes not reflected on the database container?
To explain this and see it in action, let’s use a small example: https://github.com/taomoh/docker-gotcha1
In this example, we are using a Dockerfile to “dockerise” a basic “Hello World” Python application, exposed on port 8000.
The Docker image built from this Dockerfile will contain all the dependencies the application requires.
1. Clone the github project docker-gotcha1: https://github.com/taomoh/docker-gotcha1
2. Start up the application by running docker compose
command from the root folder of the project:
$ docker-compose up -d web
Check the container started as expected:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
97f84f04df98 tip-1_web "flask run" 6 seconds ago Up 3 seconds 0.0.0.0:8000->5000/tcp, :::8000->5000/tcp tip-1_web_1
The first time you run this command, it will build the application Docker image, based on the instructions provided in Dockerfile:
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
tip-1_web latest 268f207b4ba4 19 seconds ago 179MB
python 3.7-alpine caace8ae014d 11 days ago 45.5MB
3. Hit http://localhost:8000/ on the browser: you’ll see the message “Hello World!” as expected.
4. Now let’s change something in the application code:
For example, in app.py, replace: return `Hello World`
with return `Hola Mundo!`
and restart the Docker container:
$ docker-compose stop
$ docker-compose up -d web
6. Hit http://localhost:8000/ on the browser: you still see the message “Hello World!” and not “Hola Mundo!” as expected. What’s going on?
Well, the docker compose
command have re-used the image created from the first run, which still has the old version of the code:
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
tip-1_web latest 268f207b4ba4 17 minutes ago 179MB
python 3.7-alpine caace8ae014d 11 days ago 45.5M
You need to rebuild a fresh Docker image to reflect the code change. To do this you need to pass the --build switch:
$ docker-compose stop
$ docker-compose up -d --build web
List Docker images and you will see that a fresh Docker image of the web application has just been created:
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
tip-1_web latest 5e6982bdd0f1 About a minute ago 179MB
<none> <none> 268f207b4ba4 23 minutes ago 179M
This time, if you hit http://localhost:8000/ on the browser, you will see the new message “Hola Mundo!” as expected.
P.S. The same principle applies if you had to change Dockerfile: you’ll have to rebuild your application image, by providing the --build switch to the docker compose up
command.
About the author:
Taoufik Mohdit is a Senior Java Developer here at Version 1.