๐Ÿ”ง Docker Troubleshooting

Find your exact problem and fix it โ€” each section follows Problem โ†’ Symptoms โ†’ Diagnose โ†’ Fix.

๐Ÿฉบ Run These First โ€” Every Time

These 5 commands give you the full picture within 60 seconds and resolve most issues without deeper investigation.

1
What state is the container in?
docker ps -a

Check STATUS โ€” Exited (1) = crash ยท Exited (0) = ran and finished ยท Restarting = crash-loop.

2
What did it say before dying?
docker logs <container> --tail 100

The error is almost always in the last 10 lines. Pipe to grep -i error if output is large.

3
Was it killed by the kernel (OOM)?
docker inspect --format '{{.State.OOMKilled}}' <container>

If true โ†’ increase memory limit. OOM kills leave no app-level log.

4
What resources is it consuming?
docker stats --no-stream

CPU pegged at 100 % = throttled. MEM near limit = impending OOM. BLOCK I/O high = disk bottleneck.

5
What events happened on the host?
docker events --since 30m

Shows OOM kills, restarts, and daemon signals invisible in container logs.

๐Ÿ“Š Exit Code โ€” What Happened?

Exit CodeMeaningGo To
0Clean finish โ€” process ran and exited normallyContainer Won't Stay Up tab
1App crash / unhandled exceptiondocker logs for stack trace
127Binary not found in imageBuild Errors tab
137OOM kill (SIGKILL)Crashes & OOM tab
139Segfault (SIGSEGV)App bug โ€” check binary
143Graceful shutdown (SIGTERM)Check restart policy
๐Ÿšซ

Problem: Container status is Exited (127) โ€” command not found

Symptoms
You see: exec: "mybin": executable file not found in $PATH or exit code 127.
Diagnose
docker logs <container> --tail 20
# Verify binary exists in image
docker run --rm --entrypoint sh myimage -c "which mybin && mybin --version"
Fix

Binary not installed

Add the package to your Dockerfile.

RUN apt-get update && apt-get install -y mypackage

Wrong CMD path

Use the absolute path or verify the binary name.

CMD ["/usr/local/bin/mybin", "--flag"]
๐Ÿ”‘

Problem: Container exits with error โ€” missing environment variable

Symptoms
You see: KeyError: 'DB_URL' / undefined environment variable / connection refused on startup.
Diagnose
docker inspect <container> | grep -A30 '"Env"'
docker logs <container> --tail 30
Fix

Pass the missing variable

docker run -e DB_URL=postgres://host:5432/db myimage
# or via env file
docker run --env-file .env myimage

Use a default in-app

Make the app fall back to a sane default so startup isn't fatal.

๐Ÿ”Œ

Problem: Container fails โ€” host port already bound

Symptoms
You see: Bind for 0.0.0.0:8080 failed: port is already allocated
Diagnose
ss -tlnp | grep :8080
docker ps --filter publish=8080
Fix

Use a different host port

docker run -p 8081:8080 myimage

Stop the conflicting container

docker stop $(docker ps -q --filter publish=8080)

Kill host process owning the port

lsof -ti:8080 | xargs kill -9
๐Ÿ“ฆ

Problem: Container exits because image / tag doesn't exist

Symptoms
You see: Unable to find image 'myimage:tag' locally or manifest unknown
Diagnose
docker images | grep myimage
docker pull myimage:tag          # try pulling explicitly
Fix

Build the image first

docker build -t myimage:tag .

Check the correct tag

docker search myimage
docker pull myimage:latest
๐Ÿ’€

Problem: Container exits immediately with code 0 โ€” "it just stops"

Symptoms
Confusing behaviour: Container starts, nothing seems wrong, but it's gone after a second. Exit code 0 = clean exit. Docker containers stop when their PID 1 exits.
Diagnose
docker logs <container>           # any output at all?
docker inspect --format '{{.Config.Cmd}}' <container>
Fix

Service must run in foreground

# BAD โ€” daemon exits after forking
CMD ["nginx"]
# GOOD โ€” blocks the process
CMD ["nginx", "-g", "daemon off;"]

One-shot script? That's fine

If CMD runs a script that exits, the container stops. Use --restart=on-failure for retry, or run interactively for debugging.

docker run -it --entrypoint /bin/sh myimage
๐Ÿ”„

Problem: Container keeps restarting in a loop

Symptoms
You see: docker ps shows Restarting (1) X seconds ago. Restart count keeps climbing.
Diagnose
docker logs --tail 40 <container>
docker inspect --format '{{.RestartCount}}' <container>
docker inspect --format '{{.State.ExitCode}}' <container>
Fix

Disable restart to read logs

docker update --restart=no <container>
docker stop <container>
docker logs <container>

Limit retries in production

docker run --restart=on-failure:3 myimage
# stops retrying after 3 crashes

Run interactively to reproduce

docker run --restart=no -it myimage
๐Ÿ’ฅ

Problem: Container killed with exit 137 โ€” Out of Memory

Symptoms
You see: Exit code 137. No error in app logs. Container suddenly disappears.
Diagnose
docker inspect --format '{{.State.OOMKilled}}' <container>
# โ†’ true confirms OOM

dmesg | grep -i "oom\|killed"     # host kernel log
docker stats --no-stream <container>
Fix

Increase memory limit

docker run -m 2g --memory-swap 2g myimage
# compose.yml:
mem_limit: 2g

Profile memory first

docker exec -it <container> sh -c "free -m"
docker stats <container>    # watch MEM USAGE live

Fix memory leak in app

If usage grows unbounded, the app is leaking. Profile in staging before increasing limits blindly.

๐ŸŒ

Problem: Container is extremely slow / high CPU

Symptoms
You see: Requests time out. docker stats shows CPU near 100 %. App responds but sluggishly.
Diagnose
docker stats --no-stream <container>
docker exec -it <container> sh -c "top -bn1 | head -20"
docker exec -it <container> sh -c "ps aux --sort=-%cpu | head"
Fix

CPU quota too tight โ€” increase it

docker run --cpus="2.0" myimage   # was 0.5?
docker update --cpus="2.0" <running-container>

Disk I/O bottleneck

Heavy writes to the overlay2 layer are slow. Move I/O-heavy paths to a volume.

docker run -v mydata:/app/data myimage

Clean up disk โ€” system full causes stalls

docker system df
docker system prune -af
๐ŸŒ

Problem: Container can't reach the internet

Symptoms
You see: curl: (6) Could not resolve host or connect: network is unreachable inside container.
Diagnose
docker exec -it <container> ping -c3 8.8.8.8   # IP reachable?
docker exec -it <container> nslookup google.com # DNS working?
docker exec -it <container> curl -v https://example.com
Fix

iptables MASQUERADE missing

# Missing nat rule โ€” restart Docker to restore
sudo systemctl restart docker
# Verify rule exists
sudo iptables -t nat -L POSTROUTING -n | grep MASQUERADE

Custom DNS servers

# One-off
docker run --dns 8.8.8.8 myimage
# Permanent โ€” /etc/docker/daemon.json
{"dns": ["8.8.8.8", "1.1.1.1"]}
sudo systemctl reload docker

Behind a corporate proxy

docker run \
  -e HTTP_PROXY=http://proxy:3128 \
  -e HTTPS_PROXY=http://proxy:3128 \
  -e NO_PROXY=localhost,127.0.0.1 \
  myimage
๐Ÿ”—

Problem: Container A can't connect to Container B by name

Symptoms
You see: Could not resolve host: db or connection refused when using container name as hostname.
Diagnose
docker inspect <container-a> | grep -A10 '"Networks"'
# Are both containers on the same user-defined network?
docker network ls
docker network inspect <network>   # who's attached?
Fix

Use a user-defined network (required for DNS)

docker network create mynet
docker run -d --name db --network mynet postgres:15
docker run -d --name app --network mynet myapp
# Now: app โ†’ ping db  โœ“

Connect a running container

docker network connect mynet <container>
โš ๏ธ Common mistake: Using localhost to reach another container. Each container has its own network namespace โ€” use the container name instead.
๐Ÿšช

Problem: Port is mapped but not reachable from the host

Symptoms
You see: curl localhost:8080 hangs or returns Connection refused even though the container is running.
Diagnose
docker port <container>               # what's actually mapped?
docker exec -it <container> ss -tlnp  # what is the app binding to?
Fix

App binds to 127.0.0.1 โ€” not 0.0.0.0

Port mapping only works if the app listens on all interfaces inside the container.

# BAD in your app config:
listen("127.0.0.1", 3000)
# GOOD:
listen("0.0.0.0", 3000)

Missing -p flag โ€” port not published

docker run -p 8080:80 myimage    # host:container
# Check mapping:
docker port <container>
๐Ÿ—๏ธ

Problem: apt-get install fails โ€” package not found

Symptoms
You see: E: Unable to locate package xyz during docker build.
Diagnose
docker build --progress=plain .    # show full output
docker build --no-cache .          # stale cache?
Fix

Always update before install โ€” in the same RUN

RUN apt-get update && apt-get install -y \
    curl git vim \
  && rm -rf /var/lib/apt/lists/*

Stale layer cache โ€” rebuild without cache

docker build --no-cache -t myimage .
๐Ÿ“‚

Problem: COPY fails โ€” file not found in build context

Symptoms
You see: COPY failed: file not found in build context: "src/app.py"
Diagnose
ls -la src/app.py                   # does it exist?
cat .dockerignore                    # could it be excluded?
docker build --progress=plain . 2>&1 | head -20
Fix

Paths are relative to build context, not Dockerfile

# Run from the project root, not a subdirectory docker build -t myimage . # or specify context explicitly docker build -f docker/Dockerfile -t myimage .

.dockerignore is excluding the file

Open .dockerignore and remove or narrow the pattern that's blocking the file.

๐Ÿ˜

Problem: Image is huge โ€” build takes forever or push fails

Symptoms
You see: docker images shows image size > 1 GB. docker push is extremely slow.
Diagnose
docker history myimage             # which layer is bloated?
docker system df                   # overall disk usage
Fix

Switch to a slim base image

FROM python:3.11-slim    # not python:3.11
FROM node:20-alpine      # not node:20

Use multi-stage build

FROM golang:1.22 AS builder
COPY . . && RUN go build -o app

FROM scratch
COPY --from=builder /app/app /app
ENTRYPOINT ["/app"]

Clean up inside the same RUN

RUN apt-get install -y build-essential \
  && make install \
  && apt-get purge -y build-essential \
  && rm -rf /var/lib/apt/lists/*
โšก

Problem: Cache busted every build โ€” rebuilds are slow

Symptoms
You see: Every code change triggers a full npm install / pip install even though dependencies didn't change.
Fix

โŒ Anti-pattern

COPY . .           # all files first
RUN npm install    # cache busted on any code change

โœ… Cache-friendly

COPY package*.json ./   # deps manifest first
RUN npm ci              # cached until deps change
COPY . .                # code copied last
๐Ÿ’พ

Problem: Data disappears when the container is removed

Symptoms
You see: Database is empty after docker rm and docker run. Files written inside the container are gone.
Diagnose
docker inspect <container> | grep -A20 '"Mounts"'
# Empty Mounts = no volume โ€” data is in the ephemeral layer
Fix

Attach a named volume

docker run -v pg_data:/var/lib/postgresql/data postgres:15
# Data survives docker rm; lost only on docker volume rm

Use a bind mount (dev)

docker run -v /host/uploads:/app/uploads myimage
# Data lives in /host/uploads on the host
๐Ÿ”’

Problem: Permission denied writing to a mounted volume

Symptoms
You see: Permission denied when app tries to write to /data or any bind-mounted directory.
Diagnose
docker exec -it <container> ls -lan /data     # note UID:GID
docker inspect --format '{{.Config.User}}' <container>
Fix

Match UID on the host directory

# Container runs as UID 1000:
sudo chown -R 1000:1000 /host/data
docker run -v /host/data:/data myimage

Set ownership in Dockerfile

RUN mkdir -p /data && \
    chown -R appuser:appuser /data
USER appuser

SELinux (RHEL / Fedora) โ€” add :z flag

docker run -v /host/data:/data:z myimage
๐Ÿ“‚

Problem: Bind mount shows an empty directory inside container

Symptoms
You see: Files exist on the host but the container sees an empty directory at the mount path.
Diagnose
docker inspect <container> | grep -A5 '"Source"'
# Verify the host path is correct and populated
ls -la /host/path
Fix

Always use absolute paths in -v

# BAD โ€” relative path silently creates wrong dir
docker run -v data:/app/data myimage         # โ† named volume, not ./data!
# GOOD
docker run -v /absolute/host/path:/app/data myimage

Host dir was auto-created empty

Docker creates the host directory if it doesn't exist โ€” but empty. Pre-create and populate it before running.

๐Ÿ›‘

Problem: Docker daemon fails to start โ€” systemctl start docker fails

Symptoms
You see: Job for docker.service failed or all docker commands return Cannot connect to the Docker daemon.
Diagnose
sudo systemctl status docker
sudo journalctl -u docker -n 80 --no-pager   # last 80 lines of daemon log
Fix

Invalid daemon.json (most common)

python3 -m json.tool /etc/docker/daemon.json
# Fix syntax errors, then:
sudo systemctl restart docker

Stale PID / socket file

sudo rm -f /var/run/docker.pid
sudo rm -f /var/run/docker.sock
sudo systemctl start docker

Storage driver conflict

sudo journalctl -u docker | grep "storage-driver"
# daemon.json โ€” explicitly set overlay2
{"storage-driver": "overlay2"}
๐Ÿ”‘

Problem: permission denied connecting to Docker socket

Symptoms
You see: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
Diagnose
ls -la /var/run/docker.sock     # check ownership
id                               # are you in the docker group?
groups $USER
Fix

Add user to docker group (permanent)

sudo usermod -aG docker $USER
newgrp docker                    # apply now, without logout

Temporary โ€” only until reboot

sudo chmod 666 /var/run/docker.sock
โš ๏ธ Security: The docker group grants root-equivalent access. Only add trusted users in production.
๐Ÿ“‹

Problem: Container logs are missing / docker logs returns nothing

Symptoms
You see: docker logs <container> returns empty output even though the container is running and the app is logging.
Diagnose
docker inspect --format='{{.HostConfig.LogConfig.Type}}' <container>
# If not "json-file" โ†’ docker logs won't work
Fix

Non-default log driver active

If using journald, awslogs, etc., use the driver's native tool.

journalctl CONTAINER_NAME=<name> -n 100

App writes to file, not stdout

Docker only captures stdout/stderr. Configure your app to log to stdout, or tail the log file inside the container.

docker exec -it <container> tail -f /var/log/app.log

Log size limits โ€” oldest lines rotated

# daemon.json โ€” set retention { "log-driver": "json-file", "log-opts": {"max-size": "100m", "max-file": "3"} }
๐Ÿ’ฟ

Problem: no space left on device โ€” Docker disk is full

Symptoms
You see: no space left on device on build, pull, or container write operations.
Diagnose
docker system df # breakdown by type docker system df -v # per-image / per-volume detail df -h /var/lib/docker # host disk usage
Fix โ€” start safe, go aggressive only if needed
BASH
docker container prune              # step 1 โ€” stopped containers
docker image prune                  # step 2 โ€” dangling images
docker image prune -a               # step 3 โ€” ALL unused images
docker volume prune                 # step 4 โ€” unused volumes
docker builder prune                # step 5 โ€” build cache
docker system prune -af --volumes   # โ˜ข๏ธ  nuclear โ€” everything unused
โš ๏ธ docker system prune -af --volumes permanently deletes all unused images and volumes. Run docker system df first to understand impact.