Docker for testers
Updated 2026-11-13 · 3 min read
Build a disposable Docker test runner, inspect its logs and exit status, and prove a failed assertion reaches the host shell.
A useful containerised test does two things: runs in a known environment and returns a failure status when an assertion fails. This lab builds a tiny shell test runner; it needs no application server, registry account or published port.
Verified on Linux with Docker client and Engine 29.1.3, using the official alpine:3.22 image. The tag can move; the local build pins its selected base by digest in the generated Dockerfile. You need Bash, an accessible Docker daemon and network access to pull the public base image.
1. Check the daemon and create a workspace
docker version
lab=$(mktemp -d /tmp/qa-docker-XXXXXX)
cd "$lab"
image="qa-batch8-$(basename "$lab" | tr '[:upper:]' '[:lower:]'):local"
docker pull alpine:3.22
base=$(docker image inspect alpine:3.22 --format '{{index .RepoDigests 0}}')
docker version must show both Client and Server. A socket permission or daemon connection error means this prerequisite is missing; stop here and fix access with your machine administrator. Do not weaken socket permissions to make a tutorial work.
2. Write the test and build the image
This single block creates both files. The test calculates a fake two-item order total in paise. It accepts the expected total as its first argument so we can demonstrate both outcomes.
cat > check.sh <<'SH'
#!/bin/sh
set -eu
actual=$((14900 * 2))
expected=${1:-29800}
if [ "$actual" -ne "$expected" ]; then
echo "FAIL: expected $expected paise, got $actual"
exit 1
fi
echo "PASS: total is $actual paise"
SH
cat > Dockerfile <<EOF
FROM $base
WORKDIR /lab
COPY check.sh /lab/check.sh
ENTRYPOINT ["sh", "/lab/check.sh"]
EOF
docker build -t "$image" .
FROM selects the base. COPY includes the test. ENTRYPOINT makes the test the container's main command. No executable-bit change is needed because sh reads the script. This arithmetic example checks failure propagation, not an actual checkout service.
3. Inspect a successful run
cid=$(docker create --network none "$image")
docker start -a "$cid"
docker logs "$cid"
docker inspect --format '{{.State.ExitCode}}' "$cid"
docker rm "$cid"
The test prints PASS: total is 29800 paise; logs repeat that line, and inspection prints 0. The container has stopped but remains inspectable until removed. --network none is sufficient because this test has no network dependency.
4. Prove a failure reaches the caller
if docker run --rm --network none "$image" 1; then
echo 'Unexpected success'
exit 1
else
result=$?
test "$result" -eq 1
echo "Verified assertion failure: exit $result"
fi
Expect FAIL: expected 1 paise, got 29800 followed by Verified assertion failure: exit 1. An infrastructure error with a different exit code will fail the check. This is an intentional negative control: a runner that always returns zero would be unsafe as a pipeline gate.
5. Clean up only this lab's image
docker image rm "$image"
The first container was removed explicitly and the second uses --rm. The shared base image and Docker's build cache remain. The temporary directory may be deleted after inspection. Avoid broad cleanup commands on a shared daemon.
Explain it in an interview
“I package the test dependencies in an image, run a container, collect its output and use the exit status as the gate. I verify both a passing and a deliberately failing assertion. I also distinguish an assertion failure from failure to start the runner.”
Follow-up: will this prove production behaves identically? No. Databases, networks, permissions and configuration still need representative integration tests. This lab uses no volumes or host mounts, so it does not demonstrate persistence or report export.
Quick answers
Is an image the same as a container?
An image supplies the filesystem and defaults. A container is a created instance with its own execution state.
Does removing this container remove the image?
No. The lab removes its tagged image separately after removing its containers.
Sources
- Docker create (official; accessed 2026-11-13)
- Docker start (official; accessed 2026-11-13)
- Docker logs (official; accessed 2026-11-13)
- Docker inspect (official; accessed 2026-11-13)
- Docker image inspect (official; accessed 2026-11-13)
- Docker build (official; accessed 2026-11-13)
- Docker remove container (official; accessed 2026-11-13)
- Docker remove image (official; accessed 2026-11-13)
- Docker run (official; accessed 2026-11-13)
- Dockerfile reference (official; accessed 2026-11-13)
Want a project you can show in interviews?
The portfolio project kit walks you through testing a deliberately buggy app with Selenium or Playwright and API tests, then explaining it. The app itself is free.
