Caching and multistage
Goal
This project is about the cache and multistage builds. You will:
- use cache-busting to your advantage
- create and build a multistage build
Tools
- Try to complete the tasks below with the help of the slides and the cheatsheet.
- If you have any problems, you will find a fold-out block for each task describing the solution.
Preparation
Make sure that you are still in the folder my-first-image
from the previous hands-on.
Task 1 - Layers and caching
1.1: Building with cache
- Build the image again and observe the output.
- The cache is used for all layers. Nothing is rebuilt.
Solution (click on the arrow if you get stuck)
- Execute again
docker build -t demo01 .
- The output contains
CACHED
for each layer, e.g:=> CACHED [5/7] COPY requirements.txt .
1.2: Cache-busting in app.py
- Change the string "Web App with Python Flask!" in
app.py
. - Build the image again.
- Look at the output. The cache could no longer be used in every step.
Solution (click on the arrow if you get stuck)
- Change the return value in line 7 in
app.py
to:return 'Hello World from Docker demo'
- Execute
docker build -t demo01 .
again. - The output now no longer contains
CACHED
in step 7, e.g:=> [7/7] COPY app.py .
- The layer had to be rebuilt.
1.3: Cache-busting through new system dependencies
- In addition to the existing system dependencies
python3
andpython3-pip
, add another packagenano
. - Build the image again.
- The build will now take longer again, as the system dependencies have to be reinstalled and the cache could no longer be used.
Solution (click on the arrow if you get stuck)
- Change the Dockerfile to:
[...] RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ nano \ && rm -rf /var/lib/apt/lists/* [...]
- Run again
docker build -t demo01 .
- The layers had to be built again.
Task 2 - Multistage build
2.1: Create requirements.dev.txt
Create a file requirements.dev.txt
in the folder my-first-image
with the following content:
pylint
pytest
2.2: Extend Dockerfile to multistage build
Based on the previous, minimal image, we now want to install further install further development dependencies. These could be used in a CI/CD pipeline to unit/integration tests and code linting. However, the dependencies should not be included in the previous, minimal image.
- Give the previous stage the name
runtime
.
Solution (click on the arrow if you get stuck)
- Change the Dockerfile to:
FROM ubuntu:20.04 as runtime RUN apt-get update && apt-get install -y \ [...]
- Create a second stage
dev_environment
which, based on the first stage, adds further dependencies from therequirement.dev.txt
. Please note here, that the user must first be set toroot
and then toapp-runner-user
again, as only the root user has the rights for the installations.
Solution (click on the arrow if you get stuck)
- Change the Dockerfile to:
[...] CMD ["python3", "app.py"] ## Second stage FROM runtime as dev_environment USER root COPY requirements.dev.txt . RUN python3 -m pip install -r requirements.dev.txt USER app-runner-user
2.3: Building a multistage build
Now build both stages.
Solution (click on the arrow if you get stuck)
- If you want to build all stages, you can do this as before with the following command:
docker build -t demo01_dev .
Now build only the first stage.
Solution (click on the arrow if you get stuck)
- Build the first stage with the name
runtime
, as follows:docker build -t demo01 --target runtime .
You have now successfully worked with the cache and multistage builds. By the inclusion of the cache in the creation process of a Dockerfile, the build time can be minimized considerably. Multistage builds are ideal to minimize the image size.