Skip to content
Home
Docker Logs & Debugging: Container Troubleshooting Guide

Docker Logs & Debugging: Container Troubleshooting Guide

Docker Docker 8 min read 1609 words Beginner ExcellentWiki Editorial Team

When a container misbehaves — crashes on startup, fails to connect to dependent services, consumes excessive memory, or enters a restart loop — Docker provides a comprehensive suite of debugging tools. Mastering these diagnostic techniques separates production-efficient engineers from those who restart and hope. This guide covers essential commands, common failure patterns, and systematic approaches to container troubleshooting, drawing on best practices from Docker’s official documentation and production operations experience.

Systematic Debugging Approach

Debugging containers follows a logical progression: check state, read logs, inspect configuration, execute commands inside the container, and test network connectivity. Jumping directly to docker exec without reading logs wastes time — the error message is often right there in stdout. Docker’s own troubleshooting guide recommends this progressive approach for efficient diagnosis.

Step 1: Check Container State

# List all containers including stopped ones
docker ps -a

# Filter by status
docker ps --filter status=exited
docker ps --filter status=restarting

# Check restart count (containers in a crash loop)
docker inspect --format='{{.RestartCount}}' container_name

# View resource usage of running containers
docker stats

A container that keeps restarting typically has one of three causes: the application crashes immediately, a health check fails and Docker restarts it based on restart policy, or the container runs out of memory and the OOM killer terminates it. The docker inspect command provides the definitive answer through the .State and .RestartCount fields.

Step 2: Read Container Logs

docker logs container_name          # Full log output
docker logs --tail 100 container    # Last 100 lines
docker logs --follow container      # Stream logs in real time
docker logs --since 5m container    # Last 5 minutes
docker logs --timestamps container  # Include timestamps for correlation

Common log patterns and their meanings:

  • Application error on startup — indicates missing dependencies, misconfiguration, or bugs
  • Connection refused — the container cannot reach a required service
  • Permission denied — filesystem permissions inside the container are incorrect
  • Killed — terminated by OOM killer; check memory limits

If docker logs returns no output, the application may be logging to a file inside the container instead of stdout/stderr. The 12-factor app principles recommend writing logs to stdout for containerized applications. If your application writes to files, use docker exec to read the log file directly from within the container.

Step 3: Inspect Configuration

docker inspect container_name                              # Full JSON metadata
docker inspect --format='{{.State}}' container_name        # State details
docker inspect --format='{{.NetworkSettings.IPAddress}}'   # Container IP
docker inspect --format='{{json .Mounts}}' container | jq  # Mounted volumes
docker inspect --format='{{.HostConfig.Memory}}' container # Memory limit

The docker inspect command reveals everything about the container: environment variables, mounted volumes, network configuration, resource limits, restart policy, and the exact command used to start it. The --format flag with Go templates enables targeted queries without parsing the full JSON output.

Step 4: Execute Commands Inside the Container

# Open an interactive shell
docker exec -it container_name /bin/bash
# Alpine-based images may only have sh
docker exec -it container_name /bin/sh

# Run diagnostic commands
docker exec container_name env                              # Environment variables
docker exec container_name cat /etc/hosts                   # Hostname resolution
docker exec container_name ps aux                           # Running processes
docker exec container_name df -h                            # Disk usage inside
docker exec container_name cat /etc/os-release              # OS version

The exec command works on running containers. If the container has exited, you cannot exec into it — use docker commit to create an image from the exited container and run a new container with a shell entrypoint.

Debugging Network Issues

Network problems are among the most common container issues, especially in multi-service applications. Docker’s networking documentation covers the full range of troubleshooting techniques.

Connectivity Diagnostics

# Test external connectivity from inside
docker exec container_name ping google.com
docker exec container_name curl -v http://other-service:8080
docker exec container_name nslookup service-name

# Check DNS configuration
docker exec container_name cat /etc/resolv.conf

# Verify port publishing
docker port container_name

# Use network troubleshooting container
docker run --rm --net container:problem-container nicolaka/netshoot tcpdump

The netshoot container is invaluable for network debugging — it includes tcpdump, curl, ping, dig, nslookup, netstat, and dozens of other network diagnostic tools. It is maintained by Nicolas Ehrman and is widely referenced in Docker community troubleshooting guides.

Common Network Issue Patterns

ProblemLikely CauseSolution
Connection refusedService not running or wrong portCheck service status and port mapping
Name resolution failsDNS misconfiguration or wrong networkVerify /etc/resolv.conf and network attach
TimeoutFirewall rules or network policyCheck security group and network policies
Port unreachablePort not publisheddocker ps shows PORTS column
Cross-host failureOverlay network misconfiguredVerify swarm/node network configuration

Common Failure Scenarios

Container Exits Immediately

The application crashes at startup. Run the container with a shell entrypoint to explore the filesystem:

docker run --rm -it --entrypoint /bin/sh image_name

This gives you a shell in the container’s environment where you can manually run the application and see the error output. This technique is documented in Docker’s troubleshooting guide as the definitive way to debug startup failures.

Exec Fails: “not found”

Distroless and scratch images have no shell. Use the image’s entrypoint directly:

docker run --rm --entrypoint /app/server image_name --help

Or use docker inspect to find the entrypoint and run it with verbose flags. For distroless images, the container contains only the application binary and its runtime dependencies — no shell, no package manager.

Out of Memory

The kernel OOM killer terminates the container. Check docker inspect --format='{{.State.OOMKilled}}' container_name. Increase memory limit or investigate memory leaks:

# Run with increased memory
docker run --memory="512m" myimage

# Monitor memory usage
docker stats --no-stream

Disk Full from Log Growth

Container logs can grow unbounded. Configure log rotation:

docker run --log-opt max-size=10m --log-opt max-file=3 myimage

For existing containers, truncate logs carefully:

truncate -s 0 $(docker inspect --format='{{.LogPath}}' container_name)

Using Health Checks

Health checks give Docker a way to monitor application health from the container engine level:

docker run --health-cmd="curl -f http://localhost/ || exit 1" \
           --health-interval=30s \
           --health-timeout=10s \
           --health-retries=3 \
           --health-start-period=40s \
           nginx

# Check health status
docker inspect --format='{{.State.Health.Status}}' container_name

The status is one of: starting, healthy, unhealthy. Integration with restart policies means Docker automatically restarts unhealthy containers using docker run --restart=unless-stopped. The start_period field is particularly important — it gives the application time to initialize before health check failures count toward retries.

Debugging Image Build Failures

Build failures often result from missing dependencies, incorrect Dockerfile instructions, or environment differences between local and CI builds. Always ensure your Dockerfile uses pinned base image versions to eliminate variability. For failures related to package installation, use BuildKit’s interactive debugging mode by passing --progress=plain to see full build output, which Docker hides by default in the formatted output mode.

Debugging with BuildKit Cache Mounts

BuildKit’s --mount=type=cache can help debug build failures by persisting intermediate artifacts:

# syntax=docker/dockerfile:1
FROM python:3.11-slim
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt

FAQ

How do I see logs from a container that exited immediately?

Use docker logs container_name to retrieve logs from exited containers. If there is no output, the application may be logging to a file instead of stdout. In that case, commit the container and run it with --entrypoint /bin/sh to inspect files.

Why does my container keep restarting?

Check docker inspect --format='{{.RestartCount}}' container_name. Common causes: the application crashes on startup (check logs), runs out of memory (check State.OOMKilled), or fails health checks (check State.Health.Status). Run with --restart=no temporarily to prevent restart loops while debugging.

Can I attach a debugger to a running container?

Yes. Use docker exec -it container_name /bin/bash to get a shell. For language-specific debugging (pdb, gdb, Node inspector), ensure the debugger is installed in the image or use a sidecar container with host networking.

How do I debug network latency between containers?

Run docker exec container_name ping other_container for basic latency measurement. For detailed analysis, use the nicolaka/netshoot container with tcpdump and mtr utilities. Container network performance depends on the network driver (bridge, overlay, macvlan) and host network configuration.

What is the best way to view logs from multiple containers?

Use docker compose logs -f for Compose projects, which streams logs from all services with color-coded prefixes. For production monitoring, route Docker logs to a centralized logging platform (Loki, ELK, Datadog).

Conclusion

Effective container debugging follows a systematic progression: check state, read logs, inspect configuration, exec commands, and validate networking. Docker’s built-in tools handle most scenarios, while specialized images like netshoot cover network debugging. Understanding common failure patterns — crash loops, OOM kills, log growth, network misconfiguration — speeds diagnosis. Combine these techniques with proper health checks and log management for reliable production containers. Master more Docker fundamentals with our Docker beginner’s guide and learn about Docker networking.

Centralized Logging with Docker

Docker’s logging drivers send container logs to various destinations. The json-file driver (default) writes logs as JSON to the host filesystem but rotates poorly at scale. The local driver stores logs in a custom, efficient format. Production deployments should use syslog, gelf, fluentd, or splunk drivers to forward logs to a central aggregator. ELK stack integration: docker run --log-driver=gelf --log-opt gelf-address=udp://logstash:12201. Log rotation prevents disk exhaustion: --log-opt max-size=10m --log-opt max-file=3. For debugging, docker logs --tail 50 --follow --timestamps <container> shows recent lines with timestamps. The docker events command streams real-time Docker daemon events: container start/stop, image pulls, volume mounts. Use docker inspect <container> | jq ’.[].State’ to view detailed container state.

Debugging Common Issues

Container exit code analysis: 0 = clean exit, 1 = application error, 137 = SIGKILL (OOM), 139 = SIGSEGV (segfault), 143 = SIGTERM (graceful shutdown). Resource constraints: docker stats <container> shows real-time CPU and memory. Network debugging: docker network inspect bridge shows connected containers. Exec into a container: docker exec -it <container> /bin/sh. For images without a shell, use docker export <container> | tar t to inspect files.

Section: Docker 1609 words 8 min read Beginner 756 articles in section Report inaccuracy Back to top