Dockerfile ONBUILD for customisable images
Over the past couple of weeks, I’ve been working on building new base images for teams to use for their services. I designed these images to be small, yet include commonly used tools, and to ensure they remain patched and up-to-date.
One of those tools is Poetry, which recently had a major version of release as I was working on the images. At first I included multiple versions of Poetry in the matrix, but as I added more things to the matrix, the number of images grew quickly.
parallel:
matrix:
- python: ["3.13", "3.12", "3.11", "3.10", "3.9"]
- poetry: ["1", "2"]
I was trying to figure out if we could drop the multiple versions of Poetry to reduce the overall complexity and decrease the number of CI jobs. After speaking to our DevEx team, it turned out that it would actually be the opposite and that we would more than likely need to support multiple minor versions of Poetry because of breaking changes.
This is when I remembered reading about the ONBUILD instruction and wondered if we could use it to control the version of Poetry installed.
The ONBUILD instruction adds to the image a trigger instruction to be executed at a later time, when the image is used as the base for another build. The trigger will be executed in the context of the downstream build, as if it had been inserted immediately after the FROM instruction in the downstream Dockerfile. - docs
Base Image
FROM python:3.13-slim-bookworm
ENV POETRY_HOME=/opt/poetry \
PIPX_HOME=/usr/local/pipx \
PIPX_BIN_DIR=/usr/local/bin
RUN python -m pip install --no-cache-dir pipx \
&& python -m pipx ensurepath \
&& python --version \
&& rm -rf /root/.cache/pip /tmp/* /var/tmp/*
ARG LATEST_POETRY_VERSION=2.0.1 # pypi/poetry&versioning=semver
RUN pipx install poetry==${LATEST_POETRY_VERSION}
ONBUILD ARG POETRY_VERSION
ONBUILD RUN if [ -n "${POETRY_VERSION}" ]; then \
pipx uninstall poetry && \
pipx install poetry==${POETRY_VERSION}; \
fi \
&& poetry --version
Few things to call out in this Dockerfile:
# pypi/poetry&versioning=semver~> this comment is for a Renovate custom manager to keep the Poetry version up to date.ONBUILD ARG POETRY_VERSION~> this declares thePOETRY_VERSIONas an empty build argument in the downstream build.ONBUILD RUN if [ -n "${POETRY_VERSION}" ];~> ifPOETRY_VERSIONhas been set, it will uninstall Poetry and install the version specified in theARGinstruction.
Default Image
FROM python-base:latest
CMD ["poetry", "--version"]
Running the image returns the Poetry version installed in the base image.
➜ docker run default
Poetry (version 2.0.1)
Custom Image
ARG POETRY_VERSION=1.8.4
FROM python-base:latest
CMD ["poetry", "--version"]
Running the image returns the Poetry version we specified in the ARG instruction.
➜ docker run custom
Poetry (version 1.8.4)