← All Articles

Common Docker Errors and Fixes: The Practical Field Guide

At a Glance
container exits immediatelybind: address already in useCOPY failed: no such file or directory

Read the exit code first: 137 = killed (OOM), 1 = app error, 127 = command not found. Then read the logs — the container itself almost never lies.

Container Exits Immediately

docker logs <container>       # the app's own message
docker inspect <container> --format='{{.State.ExitCode}}'
Exit codeMeaningTypical fix
0Command finished (fine for batch, broken for servers)The entrypoint process ended — a server must stay in foreground
1Application errorRead the logs; often missing env vars or config
126Permission denied executing the commandchmod +x the entrypoint script
127Command not foundWrong path, or binary not installed in the image
137Killed — SIGKILL: OOM or docker stopRaise memory limit, or find the leak
143SIGTERM — graceful stopNormal shutdown, usually not an error

The classic 0-exit server case: a CMD/entrypoint that daemonizes (nginx without -g "daemon off;", or a shell script ending in &) — the container's main process exits and the container follows, even though the daemon inside is (briefly) running.

"bind: address already in use"

docker run -p 3000:3000 myapp
# Error: bind: address already in use

The host port is taken — by another container, or a local process:

lsof -i :3000          # macOS/Linux: who holds it
docker ps -a           # any old container publishing 3000?

Fixes: stop the old container (docker stop); or map a different host port (-p 3001:3000 — container port unchanged); or find the local process and stop it. On macOS, note that Docker Desktop and a local dev server can fight over the same port.

COPY Failed: No Such File or Directory

COPY package.json ./
# ERROR: failed to compute cache key: "/package.json": not found

Three causes, in order of frequency: (1) the path is outside the build context — the build context is the directory you pass to docker build (usually .), and COPY can only read from within it. Building from the wrong directory produces this instantly. (2) .dockerignore excludes the file — check with docker build --no-cache after reading the ignore file; a pattern like *.md or a miswritten node_modules line can shadow real files. (3) Case sensitivity: COPY Package.json works on macOS, fails on Linux builders — match the case exactly.

Permission Denied on Volumes (Linux)

docker run -v $(pwd)/data:/app/data myapp
# app: permission denied: /app/data

Why: the container runs as a non-root user (or root), and the host directory's ownership doesn't match the UID inside. Fixes, best to worst: (1) set the runtime user to match the host owner: --user $(id -u):$(id -g); (2) build the image with a known user and chown the directory: chown -R 1000:1000 ./data; (3) last resort, run as root — works, hides the mismatch, keeps root-owned files on your host.

On macOS/Windows with Docker Desktop, bind mounts go through a VM and masking usually prevents this; the Linux-server environment is where it bites.

Image Pull Failures

ErrorCauseFix
manifest unknown / not foundTag doesn't exist (typo, or tag was deleted)Check the registry tags page; use a digest for pinning
unauthorized / deniedNot logged in, or missing repo permissiondocker login registry; verify the token scope
net/http: TLS handshake timeoutNetwork/proxy/DNS in the daemon contextConfigure daemon proxy; retry — large pulls also just time out sometimes
no space left on deviceDisk full from layers/cachedocker system prune -a (frees images+cache), docker volume prune (careful: volumes hold data)
toomanyrequests (rate limit)Docker Hub anonymous pull limitLog in (higher limit), or mirror the image to your own registry

The Build Cache Trap

"It works locally, fails in CI" is usually layer ordering: put dependency installation (COPY package.json + install) before copying source, so code changes don't invalidate the dependency layer. And when a build behaves impossibly, docker build --no-cache establishes ground truth before you debug the cache itself.

A Debugging Habit That Saves the Most Time

When a container fails at startup, override the entrypoint and stand inside it: docker run -it --entrypoint sh myimage — then run the startup commands manually, one at a time. Every "works in shell, fails in Docker" mystery becomes a step-by-step comparison: the environment, the working directory, the user, the PATH. That comparison IS the diagnosis.

Related Errors

Permission denied (EACCES) · EADDRINUSE