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 --tail to 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 and OOMKilled flag under State.
  • 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

Example · bash
# 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/netshoot

When 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.

Example · bash
# 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:latest

Inspect resource usage live

Shows real-time and snapshot resource metrics to identify which container is consuming excessive CPU or memory.

Example · bash
# 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.

Example · bash
# 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

  • Be the first to comment on this lesson.