Debugging a Container
Combine logs, exec, inspect and stats to figure out why a container is crashing, misbehaving, or eating resources.
When a container misbehaves, you have a well-worn toolkit. Knowing which tool answers which question is what makes debugging fast.
The four workhorses
docker logs— what did the app say? Add-f --tailto follow. First stop for a crash loop.docker exec -it— get a shell inside a running container to poke at files, config and processes.docker inspect— the full JSON truth: mounts, env, networks, and crucially the exit code andOOMKilledflag underState.docker stats— live CPU, memory and I/O. Perfect for spotting a memory leak or a container hitting its limit.
When there's no shell
Distroless and scratch images have nothing to exec into. Modern Docker gives you docker debug, or you can attach a debugging toolbox to the same namespaces with --pid=container:… --network=container:… from a separate nicolaka/netshoot container.
Read the exit code
A container that keeps dying? Check State.ExitCode and State.OOMKilled in inspect. Exit 137 with OOMKilled true means it blew past its memory limit — raise the limit or fix the leak.
Example
# Why did it die? Logs first
docker logs -f --tail 100 api
# Exit code + OOM status straight from inspect
docker inspect --format '{{.State.ExitCode}} OOMKilled={{.State.OOMKilled}}' api
# Live resource usage (spot leaks / limit pressure)
docker stats api
# Get a shell in a running container
docker exec -it api sh
# No shell in the image? Attach a debug toolbox to its namespaces
docker run -it --rm \
--pid=container:api --network=container:api \
nicolaka/netshootWhen to use it
- A developer diagnoses a container that keeps crashing at startup by checking docker logs --tail 50 for the error message before it exits.
- An ops engineer identifies memory pressure by running docker stats and sees a container hitting its memory limit and being OOM-killed.
- A developer copies a config file out of a stopped container with docker cp to inspect it locally when the container exits too fast to exec into.
More examples
Debug a crashing container
Combines inspect, logs, and entrypoint override to investigate a container that crashes before it can be exec'd into.
# See why it exited
docker inspect myapp --format '{{.State.ExitCode}} {{.State.Error}}'
# Show last 100 lines of output
docker logs --tail 100 myapp
# Override entrypoint to keep it running for inspection
docker run -it --entrypoint sh myapp:latestInspect resource usage live
Shows real-time and snapshot resource metrics to identify which container is consuming excessive CPU or memory.
# Live CPU, memory, and network stats for all containers
docker stats
# One-shot snapshot in parseable format
docker stats --no-stream --format \
'table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}'Copy files from a stopped container
Extracts files from a stopped container to the host for offline inspection when exec is not possible.
# Copy a log file out of a stopped container
docker cp myapp:/var/log/app/error.log ./error.log
# Copy a config file for inspection
docker cp myapp:/etc/nginx/nginx.conf ./nginx-inspect.conf
Discussion