Debugging Docker Containers: A Practical Toolkit
When a container doesn't behave, work from the outside in: what does it log, how did it exit, what does its configuration look like, and what is happening inside?
1. Logs
docker logs api # everything written to stdout/stderr
docker logs -f --tail 100 api # follow the last 100 lines
docker logs --since 10m api
Apps in containers should log to stdout/stderr, not files, so these commands (and your log platform) can see them.
2. Exit codes
docker ps -a --filter name=api
docker inspect --format '{{.State.ExitCode}} {{.State.OOMKilled}}' api
0- the process finished. Did your command run once and exit instead of starting a server?1- application error; check the logs.137- killed with SIGKILL, often out of memory (OOMKilled: true).139- segmentation fault, often a native module built for the wrong platform.143- received SIGTERM (a normal stop).
3. Look inside
docker exec -it api sh # or bash, if the image has it
env | sort # did the environment variables arrive?
ls -la /app # are the files where you expect?
wget -qO- localhost:3000/healthz
4. Start it differently
# Override the command to explore an image that crashes immediately
docker run --rm -it --entrypoint sh my-api:latest
5. Resources and events
docker stats # live CPU, memory, network per container
docker events --since 30m # starts, stops, OOM kills, health changes
docker inspect api | less # full config: mounts, networks, env, command
6. Images without a shell
Distroless and scratch images have no shell to exec into. Attach a debugging container that shares the target's process and network namespaces:
docker run --rm -it --pid=container:api --network=container:api nicolaka/netshoot
Docker Desktop also includes docker debug, which opens a toolbox shell into any container, even minimal ones.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.