Tiny bytes 001: docker asserts

Using asserts in docker to simplify the build

Intro

I’m trying something new on this blog: Tiny Bytes. Instead of waiting until I have enough material for a long post, these are short write-ups about small ideas that I found useful.

Today’s bite is inspired by TigerBeetle: asserting your Docker builds.

Normally, we build an image, push it somewhere, deploy it, and only then find out something is wrong. Maybe a symlink points to the wrong Python, a dependency is missing, or the application doesn’t even start. Those aren’t really runtime bugs—they’re packaging bugs that escaped the build.

The nice thing is that many of these assumptions are easy to verify. Instead of hoping the image is correct, assert that it is while you’re building it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
FROM python:3.12-slim-trixie AS builder

# i lied i give you two bites, the here doc syntax is much cleaner
RUN <<EOF
    set -e
    --mount=type=cache,target=/root/.cache/uv
    --mount=type=bind,source=uv.lock,target=uv.lock
    --mount=type=bind,source=pyproject.toml,target=pyproject.toml
    
    # installing the dependencies
    uv sync --locked --no-install-project --no-editable
    
    # verifying that the symlink is set correctly by uv
    VENV_PYTHON="$(readlink -f .venv/bin/python)"
    if [ "$VENV_PYTHON" != "/usr/local/bin/python3.12" ]; then
     echo "CRASH: Symlink is pointing to uv or an incorrect Python binary! $VENV_PYTHON" 
     exit 1
    fi
EOF
# the last line asserts that we actually have the right symlink installed by uv, lets says someone updated the .python-version in the project this would fail.

FROM python:3.12-slim-trixie AS server
COPY --from=builder /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH" \
    PYTHONUNBUFFERED=1 \
    WORKER_COUNT=1

# check if the app is on the path and can start and has all its needed imports
RUN app --verify
CMD ["app"]

I like this pattern because it turns the Dockerfile into more than just a recipe. It also documents the assumptions the image depends on and fails fast whenever one of them no longer holds. The earlier a packaging mistake is caught, the less likely it is to become a deployment problem.

I probably wouldn’t need this if I were writing Go. Unfortunately, the job market had other plans.

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy