E-NO Logo
EN FR
Docker troubleshooting 9 Min Read

Docker troubleshooting with practical examples: practical implementation guide

calendar_today Published: 2026-07-09
update Last Updated: 2026-07-09
analytics SEO Efficiency: 100%
Technical guide illustration for Docker troubleshooting with practical examples: practical implementation guide.

This guide shows how to troubleshoot Docker with concrete commands, short checklists, and small recovery workflows. It targets developers, DevOps consultants, and startup teams who need fast, safe fixes. You will learn a repeatable flow, see common failure patterns, and apply practical examples that work on Linux and macOS hosts, and inside Docker Compose and Kubernetes. The goal: make issues easy to reproduce, measure, and resolve locally before wider rollout.

Workflow Overview

Use this repeatable flow for most Docker issues:

  1. Verify the basics
  • Check Docker is running:
  • Linux: systemctl status docker
  • All: docker info
  • Confirm disk and memory are not exhausted: df -h, free -m (Linux), docker system df
  1. Reproduce and capture context
  • Record the exact command, compose file, image tag, and error message.
  • Keep a small repro case if possible.
  1. Inspect container and image state
  • docker ps -a
  • docker inspect <container-or-image>
  1. Read logs first
  • docker logs <container> --since=10m -n 200
  • docker events --since 10m
  • Daemon logs (Linux): journalctl -u docker --since "10 min ago"
  1. Check networking
  • docker network ls
  • docker network inspect <net>
  • Test from host: curl -v http://localhost: PORT
  • Test from container: docker exec -it <ctr> sh -c 'curl -v http://service: port'
  1. Check volumes and permissions
  • docker inspect -f '{{.Mounts}}' <ctr>
  • ls -l on host paths; identify UID/GID mismatches
  1. Check build and cache
  • docker build . --no-cache (to validate a true rebuild)
  • docker history <image>
  1. Check resource pressure
  • docker stats (live view)
  • ulimit -a; check OOM kills in logs
  1. Fix, retest, and document briefly
  • Apply the smallest viable fix.
  • Rebuild/recreate only affected services.
  1. Cleanup safely (optional)
  • List before prune: docker system df
  • Targeted prune: docker image prune -f, docker builder prune -f
  • Avoid destructive global prunes on shared hosts.

Logs and Diagnostics

Start with logs and a quick snapshot of state.

Commands you will use frequently:

  • Container logs:
  docker logs <ctr>
  docker logs -f --since=15m <ctr>
  • Daemon logs (Linux):
  journalctl -u docker -n 200 --no-pager
  • Live events timeline:
  docker events --since 30m
  • State and health:
  docker inspect -f '{{.State.Status}} {{.State.Health.Status}}' <ctr>
  • Networking:
  docker network ls
  docker network inspect <net>
  • Compose:
  docker compose ps
  docker compose logs -f --since=10m

Tip: capture command outputs into text files for later diffing, for example docker inspect > inspect.json.

Containers Exit Immediately

Symptom: docker run exits with code 0 or a nonzero code, and the service never stays up.

Checklist:

  1. Inspect exit code and reason:
docker inspect -f '{{.State.ExitCode}} {{.State.Error}}' <ctr>
  1. Show last logs:
docker logs --tail=100 <ctr>
  1. Run the image interactively to see the process lifecycle:
docker run --rm -it <image> sh
  1. Confirm CMD/ENTRYPOINT:
docker inspect -f '{{.Config.Entrypoint}} {{.Config.Cmd}}' <image>

Common causes and fixes:

  • The process ended normally (exit 0). Add a foreground process or use a proper server command. For quick debugging use:
docker run -it --entrypoint sh <image>
# or keep it alive temporarily
docker run -d --name debug <image> sh -c 'tail -f /dev/null'
  • Wrong ENTRYPOINT. Prefer an entrypoint script that execs the final process so signals work:
#!/bin/sh
set -e
exec "$@"
  • Missing dependencies at runtime. Validate inside the container:
ldd /path/to/binary || true
which node || which python || which nginx

Networking and Ports

Symptom: service does not respond on the expected port, or bind fails with "address already in use".

Checklist:

  1. Verify port mappings:
docker ps --format 'table {{.Names}}\t{{.Ports}}'
  1. Check host port conflicts:
# Linux/macOS
sudo lsof -i :8080 || sudo ss -lntp | grep ':8080'
  1. Confirm the service is listening inside the container:
docker exec -it <ctr> sh -c 'ss -lntp || netstat -lntp'
  1. Test reachability:
# From host
curl -v http://localhost:8080
# From another container on same network
docker run --rm --network <net> curlimages/curl:8.7.1 curl -sv http://<service>:<port>

Fixes:

  • Change the host port mapping: -p 8081:8080 when 8080 is in use.
  • Bind to 0.0.0.0 inside the container if the app binds to 127.0.0.1 by default.
  • Validate container network: docker network inspect <net> and ensure both services share the same network.

DNS and Proxy Issues

Symptom: containers cannot resolve names or cannot reach the internet behind a proxy.

Checklist:

  1. Check resolver inside the container:
cat /etc/resolv.conf
  1. Test DNS:
docker run --rm busybox:1.36 getent hosts example.com || nslookup example.com
  1. Corporate proxy case:
  • Pass HTTP_PROXY, HTTPS_PROXY, and NO_PROXY to builds and runs.
  • For builds:
docker build --build-arg HTTP_PROXY=$HTTP_PROXY --build-arg HTTPS_PROXY=$HTTPS_PROXY .
  1. Override DNS if needed:
docker run --dns 8.8.8.8 --dns 1.1.1.1 <image>

Fixes:

  • Ensure the daemon-level DNS is configured only if necessary; prefer per-container flags.
  • Set NO_PROXY for internal hostnames and service names on user-defined networks.

Volumes and Permissions

Symptom: Permission denied when writing to a bind mount or volume.

Checklist:

  1. Inspect mounts:
docker inspect -f '{{json .Mounts}}' <ctr> | jq .
  1. Check host path ownership:
ls -l /host/path
stat -c '%u:%g %n' /host/path  # Linux
  1. Find the container process UID/GID:
docker exec -it <ctr> id

Fixes:

  • Align UIDs: chown -R 1000:1000 /host/path to match the app user, or run with -u 1000:1000.
  • Use a named volume to avoid host permission quirks for app data:
docker volume create appdata && docker run -v appdata:/var/lib/app ...
  • SELinux hosts: add :Z or :z to bind mounts to relabel context when appropriate.
  • Validate Nginx and static content permissions in web stacks:
docker exec -it <ctr> sh -c 'nginx -t && ls -l /usr/share/nginx/html'

Build and Image Issues

Common build failures and slow builds.

Symptoms and fixes:

  • Stale cache or bad layer ordering:
  • Use .dockerignore to reduce context.
  • Move apt-get install and package.json steps earlier for better caching.
  • Validate a clean rebuild: docker build --no-cache -t app: test .
  • Network failures during RUN:
  • Retry with a base image that includes curl to debug network.
  • Respect HTTP(S)_PROXY and NO_PROXY in Dockerfile with ARG/ENV.
  • No space left on device:
  • Inspect: docker system df, docker builder du
  • Prune safely:
docker image prune -f
docker builder prune -f
  • Remove only unneeded dangling images; avoid global prune on shared hosts.
  • Large images:
  • Use multi-stage builds to copy only final artifacts.
  • Prefer alpine or distro-specific minimal images when compatible.

Docker Compose Tips

Debugging multi-service apps.

Useful commands:

docker compose ps
docker compose logs -f service
docker compose config

Service readiness:

  • Add healthchecks and make dependents wait for readiness instead of startup order.

Example healthcheck and simple wait loop:

services:
  db:
    image: postgres:16
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U postgres']
      interval: 5s
      timeout: 3s
      retries: 10
  api:
    build: ./api
    depends_on:
      - db
    environment:
      DATABASE_URL: postgres://postgres@db:5432/app
    command: sh -lc 'until pg_isready -h db -U postgres; do sleep 1; done; exec ./api'

Networking:

  • Ensure services share the same user-defined network (default for Compose).

Kubernetes Edge Cases

When containers run in Kubernetes, map cluster symptoms back to container behavior.

Checklist:

  • Find pod and events:
kubectl get pods -n <ns>
kubectl describe pod/<name> -n <ns>
  • Logs:
kubectl logs <pod> -n <ns> --previous

Check image tag, registry auth, and pull policy.

Ensure readiness and liveness probes match the container's real startup time and port.

  • Image pull issues:
  • Health probes:

Local reproduction:

  • Pull the same image locally and run with similar env and command to debug faster:
docker run --rm -e VAR=val <image>:<tag>
  • If CrashLoopBackOff, focus on container logs and entrypoint arguments first.

GitLab CI/CD Notes

Common Docker runner patterns.

Docker-in-Docker (dind) for building images:

image: docker:27
services:
  - name: docker:27-dind
    command: ['--mtu=1460']
variables:
  DOCKER_HOST: tcp://docker:2375
  DOCKER_TLS_CERTDIR: ''
stages: [build]
build:
  stage: build
  script:
    - docker info
    - docker build -t registry.example.com/app:$CI_COMMIT_SHORT_SHA .
    - docker push registry.example.com/app:$CI_COMMIT_SHORT_SHA

Tips:

  • Set DOCKER_TLS_CERTDIR='' when you intentionally use plain TCP with dind in trusted runners.
  • If name resolution fails in jobs, pass HTTP(S)_PROXY and NO_PROXY and verify with docker run busybox getent hosts.
  • For bind mounts in the runner, align UID/GID or use a volume to avoid permission errors.

Local Pilot Plan

Start with a small, measurable pilot you can inspect locally.

Pilot goal: stand up a simple Nginx service via Docker Compose, add healthchecks, rehearse 3 failure scenarios, and document fixes.

Scope (keep it small):

  • One compose file with nginx: alpine serving a static index.html.
  • Healthcheck: GET http://localhost:8080/ returns 200.

Steps:

  1. Baseline run:
docker compose up -d
curl -v http://localhost:8080/
  1. Add a deliberate port conflict:
  • Start a process on 8080, then observe compose error and switch to 8081.
  1. Add a bad mount permission:
  • Bind mount a read-only dir and confirm 403 or write errors; fix ownership or use a volume.
  1. Add a DNS failure in a sidecar curl job:
  • Run a curl container on the same network to test external DNS; add --dns override if needed.
  1. Capture and store commands and outputs in a troubleshooting.md file under the repo.

Success criteria:

  • All three failures reproduced and resolved locally.
  • Healthcheck passes consistently.
  • Clear list of commands and expected outputs for each scenario.

Conclusion

You now have a practical flow to triage Docker issues, read the right logs, and apply safe, minimal fixes. Start with service state and logs, confirm networking, and check volumes, permissions, and build layers. For Compose, rely on healthchecks and simple waits rather than startup order. In Kubernetes and CI, map symptoms back to the same container fundamentals. Begin with a small local pilot, measure outcomes, and extend the approach service by service.

Article Quality Score

Reader usefulness 100%
  • check_circle Reader-ready guide
  • check_circle Practical examples included
  • check_circle Clean SEO article URL