Docker — Frequently Asked Questions
Practical answers on containers in production — image size and base choice, why not to run as root, secrets in layers, data persistence, signals and shutdown, Compose versus an orchestrator, and debugging a container you cannot get into.
Images#
Which base image should we use?#
The smallest one your application genuinely runs on, from a source that publishes security updates, pinned by digest.
Slim variants remove a lot of surface for little effort. Minimal distributions go further and remove the shell, which is excellent for security and inconvenient the first time you need to debug — decide that trade-off consciously rather than discovering it during an incident.
The important part is not the choice, it is owning the update path: whoever picks the base is signing up to rebuild when it is patched.
Should we pin to a version or use latest?#
Pin, by digest, always in production. :latest means the image you tested and the image you deployed can differ with no change on your side, and the difference appears at the worst time.
Pinning alone is not the whole answer, though — a pinned image with no rebuild schedule is an image accumulating known vulnerabilities. Pin for reproducibility, rebuild on a cadence for patching.
How do we make the image smaller?#
Multi-stage builds, first and mostly. Compile or install in one stage, copy only the artefact into a clean runtime stage, and leave the compiler behind.
Then: order layers so dependencies are installed before source is copied, so a code change does not invalidate the dependency layer; add a .dockerignore so the build context does not include your .git directory and local files; and remove package manager caches in the same layer that created them.
Size matters for pull time on every deploy and every scale-up, and for the amount of software you are now responsible for patching.
Why does a deleted file still count?#
Because layers are additive. Adding a file in one instruction and deleting it in the next leaves it present in the earlier layer, retrievable by anyone with the image.
This is the mechanism behind most secrets-in-image incidents. If a credential was ever built into a published image, rotate it — removing the image from the registry does not un-publish what was pulled.
Running safely#
Why does everyone say not to run as root?#
Because the container boundary is good but not absolute, and root inside the container is the starting position for anything that escapes it. It also means a compromised process can modify its own filesystem freely.
Creating a user and switching to it costs two lines in the Dockerfile. Combine it with a read-only root filesystem and explicit writable paths, and a large class of attacks stops being useful.
How should secrets get into a container?#
At runtime, from the platform's secret mechanism, into the environment or a mounted file — never baked into the image, and never passed as a build argument, because build arguments are visible in image metadata.
Mounted files are slightly better than environment variables: environment variables tend to end up in crash dumps, child processes and log lines that print the environment for debugging.
Where does data go?#
Not in the container. The writable layer disappears when the container does, which is the point of containers and a surprise exactly once.
Use volumes for data that must survive, and prefer a managed database over a database in a container for anything you care about — the container is not the hard part of running a database; backup, failover and upgrades are.
Why did my container get killed?#
Most often the memory limit. The process exceeds it, the kernel terminates it, and the platform restarts it — with no application-level error to read, which is why it looks mysterious.
Check whether the runtime knows about the limit. Language runtimes with their own heap sizing frequently size themselves against the host's memory rather than the container's unless told otherwise, and then reliably exceed a limit they do not know exists.
Our deploys drop requests. Why?#
Almost always signal handling. On a rolling deploy the platform sends SIGTERM and waits; a process that ignores it is killed when the grace period ends, cutting in-flight requests.
Handle SIGTERM: stop accepting new work, finish or requeue what is in progress, exit. Also check that your application is PID 1 rather than a child of a shell — a shell entrypoint often does not forward signals, so a correctly-written application never receives them.
Development and operations#
Is Docker Compose fine for production?#
For a single host with modest requirements and someone who understands the trade-off, it can be — it is simple, readable, and much easier to reason about than an orchestrator.
What you do not get: rolling updates without downtime, automatic rescheduling when the host dies, and horizontal scaling. If you need those, you need an orchestrator, and it is better to move before an outage forces the decision than after.
How do we debug a container with no shell?#
Plan for it before you need it. Options: attach a debug container sharing the target's namespaces (supported natively by modern tooling), run a temporary build with a shell from the same base, or rely on good logs and metrics so you rarely need to be inside at all.
Teams that pick a minimal base and then routinely rebuild a "debug" variant during incidents have chosen the worst of both — decide which you want.
How do we keep images patched?#
Rebuild on a schedule, not only when the application changes, and rescan on rebuild. Most vulnerabilities reported in a scan come from the base image and are fixed by rebuilding rather than by anything in your code.
Then make sure someone reads the scan output and records what is accepted and why. An unread scan is a build step, not a control.
What is the most common production mistake?#
Treating a container as a small virtual machine — running several processes in it, writing data into it, connecting to it by hand to fix things, and never rebuilding it. Each of those individually is survivable; together they produce a host you cannot reproduce, which is precisely what containers were supposed to eliminate.