Skip to content

Docker Workflows

Common Docker operations for development.

Container Debugging

Shell Access

# Running container
docker exec -it container_name bash
docker exec -it container_name sh  # If no bash

# Run new container with shell
docker run -it --rm image_name bash

# As root (when container runs as non-root)
docker exec -it -u root container_name bash

Inspecting Containers

# Container details
docker inspect container_name

# Specific fields
docker inspect -f '{{.State.Status}}' container_name
docker inspect -f '{{.NetworkSettings.IPAddress}}' container_name
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name

# Environment variables
docker exec container_name env

# Running processes
docker exec container_name ps aux
docker top container_name

Logs

# View logs
docker logs container_name

# Follow logs
docker logs -f container_name

# Tail last N lines
docker logs --tail 100 container_name

# With timestamps
docker logs -t container_name

# Since specific time
docker logs --since 2024-01-15T10:00:00 container_name
docker logs --since 1h container_name

# Compose logs
docker compose logs
docker compose logs -f api db
docker compose logs --tail 50 api

File Operations

# Copy from container
docker cp container_name:/app/data.json ./data.json

# Copy to container
docker cp ./config.yaml container_name:/app/config.yaml

# View file in container
docker exec container_name cat /app/config.yaml

Resource Usage

# Live stats
docker stats
docker stats container_name

# One-time stats
docker stats --no-stream

# Disk usage
docker system df
docker system df -v  # Verbose

Docker Compose

Basic Operations

# Start all services
docker compose up

# Start in background
docker compose up -d

# Start specific services
docker compose up -d api db

# Rebuild and start
docker compose up -d --build

# Force recreate
docker compose up -d --force-recreate

# Stop services
docker compose stop

# Stop and remove
docker compose down
docker compose down -v  # Include volumes
docker compose down --rmi local  # Include local images

Service Management

# Restart service
docker compose restart api

# Scale service
docker compose up -d --scale worker=3

# Rebuild single service
docker compose build api
docker compose up -d api

# Pull latest images
docker compose pull
docker compose up -d

Executing Commands

# Run command in running container
docker compose exec api python manage.py shell
docker compose exec db psql -U postgres

# Run one-off command (new container)
docker compose run --rm api python manage.py migrate
docker compose run --rm api pytest

# Run with environment override
docker compose run -e DEBUG=1 --rm api python script.py

Profiles

# docker-compose.yml
services:
  api:
    build: .
    profiles: ["app"]

  db:
    image: postgres:15

  worker:
    build: .
    profiles: ["app", "worker"]

  debug:
    image: busybox
    profiles: ["debug"]
# Start specific profiles
docker compose --profile app up -d
docker compose --profile debug up -d debug

# Start all
docker compose --profile app --profile worker up -d

Networking

Network Inspection

# List networks
docker network ls

# Inspect network
docker network inspect bridge
docker network inspect compose_default

# Find container IP
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container

# Container connectivity
docker exec container_name ping other_container
docker exec container_name curl http://api:8000/health

Custom Networks

# Create network
docker network create mynetwork

# Run container on network
docker run -d --network mynetwork --name api myimage

# Connect existing container
docker network connect mynetwork container_name

# Disconnect
docker network disconnect mynetwork container_name

Port Mapping

# View port mappings
docker port container_name

# Map specific port
docker run -p 8080:80 nginx
docker run -p 127.0.0.1:8080:80 nginx  # Bind to localhost only

# Expose all ports
docker run -P nginx  # Random host ports

Volume Management

Volume Operations

# List volumes
docker volume ls

# Create volume
docker volume create mydata

# Inspect volume
docker volume inspect mydata

# Remove volume
docker volume rm mydata

# Remove unused volumes
docker volume prune

Bind Mounts

# Mount directory
docker run -v $(pwd):/app image_name
docker run -v /host/path:/container/path image_name

# Read-only mount
docker run -v $(pwd):/app:ro image_name

# Named volume
docker run -v mydata:/app/data image_name

Volume Backup

# Backup volume to tarball
docker run --rm -v mydata:/data -v $(pwd):/backup alpine \
    tar czf /backup/mydata.tar.gz -C /data .

# Restore volume from tarball
docker run --rm -v mydata:/data -v $(pwd):/backup alpine \
    tar xzf /backup/mydata.tar.gz -C /data

Building Images

Build Commands

# Basic build
docker build -t myapp .

# With tag
docker build -t myapp:v1.0 .
docker build -t registry.example.com/myapp:latest .

# No cache
docker build --no-cache -t myapp .

# Build arg
docker build --build-arg VERSION=1.0 -t myapp .

# Target stage
docker build --target builder -t myapp:builder .

# From different file
docker build -f Dockerfile.prod -t myapp:prod .

Multi-Stage Build Example

# Dockerfile
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt

FROM python:3.12-slim AS runtime
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "main.py"]
# Build final stage
docker build -t myapp .

# Build builder stage only
docker build --target builder -t myapp:builder .

Build Cache

# Use BuildKit (better caching)
DOCKER_BUILDKIT=1 docker build -t myapp .

# Cache from previous build
docker build --cache-from myapp:latest -t myapp:new .

# Export cache
docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t myapp .

Debugging Techniques

Container Won't Start

# Check logs
docker logs container_name

# Check exit code
docker inspect -f '{{.State.ExitCode}}' container_name

# Run with entrypoint override
docker run -it --entrypoint bash image_name

# Run with command override
docker run -it image_name bash

Networking Issues

# Check DNS resolution
docker exec container_name nslookup api

# Check connectivity
docker exec container_name curl -v http://api:8000

# Check iptables (host)
sudo iptables -L -n

# Check docker networks
docker network inspect bridge

Permission Issues

# Run as root
docker exec -u root container_name ls -la /app

# Check file ownership
docker exec container_name ls -la /app

# Fix permissions
docker exec -u root container_name chown -R app:app /app

Resource Issues

# Check memory usage
docker stats container_name

# Check disk usage in container
docker exec container_name df -h

# Check available disk
docker system df

Cleanup

Selective Cleanup

# Remove stopped containers
docker container prune

# Remove unused images
docker image prune        # Dangling only
docker image prune -a     # All unused

# Remove unused volumes
docker volume prune

# Remove unused networks
docker network prune

Full Cleanup

# Remove everything unused
docker system prune

# Include volumes
docker system prune --volumes

# Include all images
docker system prune -a --volumes

# Force (no confirmation)
docker system prune -af --volumes

Compose Cleanup

# Stop and remove containers, networks
docker compose down

# Include volumes
docker compose down -v

# Include images
docker compose down --rmi all
docker compose down --rmi local  # Only locally built

Development Patterns

Hot Reload with Volumes

# docker-compose.yml
services:
  api:
    build: .
    volumes:
      - .:/app
      - /app/node_modules  # Exclude node_modules
    command: bun run dev

Database Persistence

services:
  db:
    image: postgres:15
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: postgres

volumes:
  pgdata:

Override for Development

# docker-compose.override.yml (auto-loaded)
services:
  api:
    build:
      context: .
      target: development
    volumes:
      - .:/app
    environment:
      DEBUG: 1
# Production (ignores override)
docker compose -f docker-compose.yml up -d

Useful Aliases

# Add to .zshrc or .bashrc
alias d="docker"
alias dc="docker compose"
alias dps="docker ps"
alias dlog="docker logs -f"
alias dex="docker exec -it"
alias dcu="docker compose up -d"
alias dcd="docker compose down"
alias dcl="docker compose logs -f"
alias dprune="docker system prune -af --volumes"