Skip to content

Docker and containers, 8 of 26

A container is a list
of things it cannot do.

The PDF reader fetches whatever address a stranger types in. That is the job, and it is also the reason it runs with nothing: no package manager, no writable disk, no Linux capability, and a hard ceiling on memory, processor and processes.

Everything below was read off the running container after the last deploy, not copied from the command that started it.

pdf-reader:latest, read 7 Sept, 15:41

healthhealthy
runs as10001:10001
read-only roottrue
capabilities dropped["ALL"]
capabilities addednone
security options["no-new-privileges"]
memory512 MB
swap512 MB
cpu1
process limit128
restart policyunless-stopped
restarts since deploy0
image222 MB
layers9
pip in the final imagefalse
could write to /appfalse

What each flag forbids

--read-only

the filesystem cannot be written to, so nothing survives a restart

--tmpfs /tmp noexec

except scratch space, and nothing there can be executed

--cap-drop ALL

no Linux capability at all. It binds 8080, so it needs none

--security-opt no-new-privileges

a setuid binary cannot raise privileges

--pids-limit 128

a fork bomb inside stays inside

--memory 512m --memory-swap 512m

half a gigabyte, with no swap to escape into

--cpus 1

one core, so a pathological PDF cannot take the box down

USER 10001

not root, and a fixed uid so a mount agrees with it

Four decisions

01

The flags are read back, not quoted

Docker takes a flag whose spelling changed two releases ago and says nothing at all. So the deploy asks the running container what is actually in force and publishes the answer. A limit that silently failed to apply then shows up here as missing, in red, instead of living on as a confident sentence in a README that nobody rechecks.

02

Two of the claims are questions, not assertions

After every build the deploy runs `command -v pip` inside the finished image, and tries to write a file into the application directory. Both are meant to fail, and both answers are published. The first version of this image said the package manager had been left behind while pip sat there, because the base image puts it back.

03

The deploy waits on the health check the container defines

It used to curl the port and call that healthy. That let the deploy and Docker hold different opinions, while the restart policy acted on the one nobody saw. One answer now.

04

Memory and swap are set to the same number

A memory limit on its own is a limit on how much a process can hold before it starts swapping, which is not a limit at all. Setting swap equal to memory is what makes the number mean what people assume it means.

What this is not

One container on one machine. No orchestrator, no rolling deploy, no second copy. Replacing it takes a few seconds, and for those seconds the service is down.

For a service this size that is the right trade, and it stops being the right trade the moment somebody is paying for uptime. Naming that is more useful than a diagram of a cluster nobody is running.

The endpoint returns the last five reports. The service itself is what runs inside it, and the address guard is why it is allowed to fetch anything at all. The whole list is 41 requirements from 114 job posts.