Skip to content
intermediate Phase 7 · Docker in Development

Debugging Containers

Debug running containers with exec, logs, and multi-stage debugging.

45m
0 problems
Topic Progress 0%

Interactive Debugging with exec

Interactive Debugging with exec

Shell Access

# Open shell in running container
docker exec -it web bash

# If no bash, use sh
docker exec -it web sh

# Run as root
docker exec -u root -it web bash

# Set environment variables
docker exec -e DEBUG=true -it web bash

# Change working directory
docker exec -w /app/src -it web bash

Inspect Container State

# Check if container is running
docker ps | grep web

# View recent logs
docker logs --tail 100 web

# Follow live logs
docker logs -f web

# Check resource usage
docker stats web --no-stream

# Check environment variables
docker exec web env

# Check running processes
docker exec web ps aux

# Check open ports
docker exec web ss -tlnp
# or
docker exec web netstat -tlnp

# Check filesystem changes
docker diff web

Debug Inside Container

# Install debugging tools (if needed)
docker exec -u root web apt-get update && apt-get install -y curl net-tools

# Test HTTP endpoints
docker exec web curl -s http://localhost:3000/health

# Test database connectivity
docker exec web pg_isready -h db -p 5432

# Check DNS resolution
docker exec web nslookup api

# Check network connectivity
docker exec web ping -c 3 api

# Check environment variables
docker exec web env | grep -i db

# Check mounted volumes
docker exec web df -h

Debug Stopped Containers

# Start a stopped container
docker start web

# Execute into it
docker exec -it web bash

# Or create new container from same image with shell
docker run -it --rm --entrypoint bash myapp:latest

# Inspect why container stopped
docker inspect web | jq '.[0].State'
# {
#   "Status": "exited",
#   "ExitCode": 1,
#   "Error": "",
#   "StartedAt": "2024-01-15T10:00:00Z",
#   "FinishedAt": "2024-01-15T10:05:00Z"
# }

Debug Init Containers

# For containers that keep crashing
docker run -it --rm --entrypoint bash myapp:latest

# Run without CMD to inspect
docker run -it --rm --entrypoint sh myapp:latest

# Override CMD with sleep
docker run -it --rm myapp:latest sleep 3600
# In another terminal:
docker exec -it <container_id> bash

Log Analysis and Debugging

Log Analysis and Debugging

Basic Log Commands

# View all logs
docker logs web

# Follow logs (real-time)
docker logs -f web

# Show timestamps
docker logs -t web

# Last 50 lines
docker logs --tail 50 web

# Logs since a specific time
docker logs --since 2h web        # Last 2 hours
docker logs --since 2024-01-15T10:00:00 web

# Logs until a specific time
docker logs --until 2024-01-15T11:00:00 web

Multi-Container Log Analysis

# Logs for all compose services
docker compose logs

# Follow all services
docker compose logs -f

# Specific service
docker compose logs -f api

# Multiple services
docker compose logs -f api db

# With timestamps
docker compose logs -f --timestamps

# Last 100 lines per service
docker compose logs --tail 100

Structured Logging

# Parse JSON logs
docker logs web 2>&1 | jq '.'

# Filter by log level
docker logs web 2>&1 | jq 'select(.level == "error")'

# Extract specific fields
docker logs web 2>&1 | jq '{timestamp: .time, message: .msg, error: .err}'

# Count errors
docker logs web 2>&1 | jq -s 'map(select(.level == "error")) | length'

Common Log Patterns

Application crashes:

docker logs web 2>&1 | grep -i -E "error|exception|fatal|crash"

Database connection issues:

docker logs api 2>&1 | grep -i "connect\|ECONNREFUSED\|timeout"

OOM kills:

docker logs web 2>&1 | grep -i "killed\|oom"
docker inspect web | jq '.[0].State.OOMKilled'

Port conflicts:

docker logs web 2>&1 | grep -i "address already in use\|bind"

Docker Events

# Real-time container events
docker events --filter container=web

# Filter by event type
docker events --filter event=start --filter event=die

# Specific time range
docker events --since 1h --until now

Export Logs for Analysis

# Export to file
docker logs web > web.log 2>&1

# Export all compose logs
docker compose logs > compose-logs.txt 2>&1

# Export with timestamps
docker logs -t web > web-timestamped.log 2>&1

Network Debugging

Network Debugging

Debug Container Networking

# Check container's IP address
docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web

# Check which network container is on
docker inspect --format '{{json .NetworkSettings.Networks}}' web | jq

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

# Test DNS resolution
docker exec web nslookup api

# Test connectivity
docker exec web ping -c 3 api

# Test port connectivity
docker exec web nc -zv api 80
# or
docker exec web curl -v http://api:80

Network Inspect

# Inspect network
docker network inspect bridge

# List containers on network
docker network inspect bridge --format '{{range .Containers}}{{.Name}}: {{.IPv4Address}}{{println}}{{end}}'

# Check port mappings
docker port web

# Check iptables rules
sudo iptables -t nat -L DOCKER -n

Debug Docker DNS

# Test from container
docker exec web nslookup google.com

# Test local resolution
docker exec web nslookup api

# Check DNS server
docker exec web cat /etc/resolv.conf

# If DNS fails, try using IP directly
docker exec web ping -c 3 172.18.0.3

# Add DNS manually
docker exec web echo "nameserver 8.8.8.8" > /etc/resolv.conf

Debug Docker Compose Networking

# Check compose network
docker network ls | grep myproject

# Inspect compose network
docker network inspect myproject_default

# Verify service names resolve
docker compose exec api nslookup db

# Check container connectivity
docker compose exec api ping -c 3 db

Network Debugging Container

# Run a debugging container on the same network
docker run -it --rm --network mynet nicolaka/netshoot

# Inside netshoot you have:
# - ping, traceroute, dig, nslookup
# - tcpdump, ss, netstat
# - curl, wget
# - ip, ifconfig

# Example: capture traffic
tcpdump -i eth0 port 80 -w /tmp/capture.pcap