I came across this example . Here they made a 3 stage build. Is it necessary to have a 2nd stage (build-venv) ?
Is it mentioned that having it can have an advantage of "Build the virtualenv as a separate step: Only re-execute this step when requirements.txt changes". But I was under assumption that docker is intelligent enough to not build the image layer if it is not changed.
Is there any difference between
original Dockerimage
# Build a virtualenv using the appropriate Debian release
# * Install python3-venv for the built-in Python3 venv module (not installed by default)
# * Install gcc libpython3-dev to compile C Python modules
# * In the virtualenv: Update pip setuputils and wheel to support building new packages
FROM debian:11-slim AS build
RUN apt-get update && \
apt-get install --no-install-suggests --no-install-recommends --yes python3-venv gcc libpython3-dev && \
python3 -m venv /venv && \
/venv/bin/pip install --upgrade pip setuptools wheel
# Build the virtualenv as a separate step: Only re-execute this step when requirements.txt changes
FROM build AS build-venv
COPY requirements.txt /requirements.txt
RUN /venv/bin/pip install --disable-pip-version-check -r /requirements.txt
# Copy the virtualenv into a distroless image
FROM gcr.io/distroless/python3-debian11
COPY --from=build-venv /venv /venv
COPY . /app
WORKDIR /app
ENTRYPOINT ["/venv/bin/python3", "psutil_example.py"]
And (2nd stage removed)
# Build a virtualenv using the appropriate Debian release
# * Install python3-venv for the built-in Python3 venv module (not installed by default)
# * Install gcc libpython3-dev to compile C Python modules
# * In the virtualenv: Update pip setuputils and wheel to support building new packages
FROM debian:11-slim AS build
RUN apt-get update && \
apt-get install --no-install-suggests --no-install-recommends --yes python3-venv gcc libpython3-dev && \
python3 -m venv /venv && \
/venv/bin/pip install --upgrade pip setuptools wheel
COPY requirements.txt /requirements.txt
RUN /venv/bin/pip install --disable-pip-version-check -r /requirements.txt
# Copy the virtualenv into a distroless image
FROM gcr.io/distroless/python3-debian11
COPY --from=build-venv /venv /venv
COPY . /app
WORKDIR /app
ENTRYPOINT ["/venv/bin/python3", "psutil_example.py"]
Any build time advantage of one over the other ?
Thanks
I'd expect both paths to be identical. Arguably the first path would let you docker build --target
do get an image that contained the C toolchain and an empty virtual environment, but I wouldn't expect this to be a frequent use case.
More generally, there's not really a benefit to splitting a build into multiple stages but having the second stage start FROM
the first one. If your Dockerfile has
FROM ... AS a
COPY ...
RUN ...
FROM a
RUN ...
then you will get the same image out at the end whether there are two build stages or just one (deleting the second FROM
line). Build-time layer caching will work the same way, and the final image will contain all of the layers from the first stage.