Basic

Checking a container before you ship it

The check is a command that runs inside the box and exits non-zero on any problem. If you can run it, you can gate a release on it. If you cannot run it, the release is untestable and the version number is a guess.

What you will see

The deliberate failure is removed; the next gate run should pass.

About 1 min of reading

Try It

Write the release gate as one script

1

Create the gate file

printf '#!/bin/sh\nset -e\ndocker build -t app:v1.4.2 .\ndocker run --rm app:v1.4.2 python -m pytest -q\n' | tee release-gate.sh && chmod +x release-gate.sh

Before you run it, say out loud what it will print. Then open the answer.

What it prints
An executable script that builds and checks in order, stopping on any failure.
2

Run it

./release-gate.sh; echo "exit=$?"

Before you run it, say out loud what it will print. Then open the answer.

What it prints
exit=0 when the suite passes. Any non-zero means the release was not published.
3

Break the check on purpose

printf 'def test_x():\n assert False\n' > tests/test_gate.py && ./release-gate.sh; echo "exit=$?"

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Non-zero exit. The gate caught a failing test, which is the whole point of the gate.
4

Clean up

rm tests/test_gate.py

Before you run it, say out loud what it will print. Then open the answer.

What it prints
The deliberate failure is removed; the next gate run should pass.
Never publish in the same script that builds. Keep the publish step separate so a failed check cannot be papered over by a later line.

Data Flow

Build to published
1 Build the tagged box
↓
2 Run the check command inside it
↓
3 Read the exit code
↓
4 Publish only on zero
Why this works
The gate shape

Build, run the check, and only publish if the exit code is zero. Put that in a script so the discipline cannot be skipped by forgetting a step.

What a passing check does not prove

It does not prove the box is small, fast, or free of a leaked secret. Those are separate checks with separate exit codes; add them as separate lines in the gate.

Examples

One command, one exit code

docker run --rm app:v1.4.2 python -m pytest -q exits 0 or 1. That exit code is the release gate. No human reads the output to decide.

Check the environment, not only the code

Assert the base image version and the dependency versions inside the box. A check that passes on 3.12 and silently runs on 3.13 is a check that does not test what it claims.

Check the boundary, not the internals

Test the public entry point with a known input and a known output. Internal unit tests are good but do not prove the box's contract.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Pinning a dependency floor
Previous Lesson
Pinning a dependency floor
Next Lesson
Migrating data alongside the box
Migrating data alongside the box →