Docker Troubleshooting

Docker

Diagnose failing Docker builds and misbehaving containers. Use when a build fails, a container exits, or compose services will not start or reach each other.

dockercomposecontainersbuildkit

Save this file as .agents/skills/docker-troubleshooting/SKILL.md in your repository.

Compatible with: Claude Code, GitHub Copilot, Cursor, Windsurf — any agent that reads SKILL.md-style instruction files.

---
name: docker-troubleshooting
description: Diagnose failing Docker builds and misbehaving containers. Use when a build fails, a container exits, or compose services will not start or reach each other.
---

# Docker Troubleshooting

Containers fail for boring reasons. Check them in order before touching the Dockerfile.

## Container will not start / exits immediately

1. `docker ps -a` → get the exit code. 0 = the process finished (missing long-running command), 1 = app error, 127 = command not found, 137 = OOM-killed, 139 = segfault.
2. `docker logs <container>` — the last lines usually name the problem.
3. Entrypoint/CMD issues: `docker inspect <container> --format '{{json .Config}}'`. Shell-form vs exec-form, missing interpreter, CRLF line endings in scripts (fix with `sed -i 's/\r$//'` or .gitattributes).
4. Get inside: `docker run --rm -it --entrypoint sh <image>` and poke around.

## Build failures

1. Read the failing step's full output — BuildKit truncates; rerun with `--progress=plain`.
2. Cache confusion: rebuild the suspicious stage with `--no-cache` before assuming the Dockerfile is wrong.
3. .dockerignore missing → giant context, or worse, files copied that should not be (node_modules, .env).
4. Network flakes during package install: retry; do not bake in workarounds for a transient failure.

## Compose networking

- Services reach each other by service name on the compose network, not localhost. `localhost` inside a container is the container itself.
- `depends_on` waits for start, not readiness — a DB that takes 10s to accept connections needs a healthcheck + `condition: service_healthy`.
- Port conflicts: `docker compose ps` and check the host port mapping; another project may hold 5432.
- Verify from inside: `docker compose exec app sh` then `wget -qO- http://db:5432` or equivalent.

## Image hygiene (when relevant)

- Multi-stage builds to keep runtime images small.
- Pin base image versions (`node:20-alpine`, not `node:latest`).
- Never store secrets via ENV or COPY — they persist in layers. Use build secrets or runtime env.

## Output

Root cause, the minimal fix, and the command that proves the fix (`docker compose up` healthy, endpoint reachable).

Related skills: systematic-debugging, incident-response

Related commands: docker logs, docker inspect, docker compose ps

Related workflows: Debug a failing Docker build