Docker Cheat Sheet¶
Container Lifecycle¶
docker run -d --name app -p 8080:80 nginx:1.25
docker run -it --rm ubuntu bash # Interactive, auto-remove
docker stop app # Graceful stop (SIGTERM)
docker kill app # Force stop (SIGKILL)
docker rm app # Remove container
docker rm -f $(docker ps -aq) # Remove all containers
Common Run Flags¶
| Flag | Purpose |
|---|---|
-d |
Detached (background) |
-it |
Interactive terminal |
--rm |
Auto-remove on exit |
-p 8080:80 |
Port mapping host:container |
-v /host:/cont |
Bind mount |
-v vol:/cont |
Named volume |
-e KEY=VAL |
Environment variable |
--env-file .env |
Env file |
--network net |
Attach to network |
--restart unless-stopped |
Restart policy |
--memory 512m |
Memory limit |
--cpus 0.5 |
CPU limit |
Images¶
docker build -t myapp:v1 . # Build from Dockerfile
docker build -t myapp:v1 -f Dockerfile.prod .
docker tag myapp:v1 registry.io/myapp:v1
docker push registry.io/myapp:v1
docker pull nginx:1.25
docker images # List images
docker image prune -a # Remove unused images
docker history myapp:v1 # Show layers
Dockerfile Best Practices¶
# Use specific base image (pin digest for prod)
FROM golang:1.22-alpine AS builder
WORKDIR /app
# Cache dependencies (copy go.mod first)
COPY go.mod go.sum ./
RUN go mod download
# Copy source and build
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server .
# Minimal runtime image
FROM gcr.io/distroless/static:nonroot
COPY --from=builder /app/server /server
USER nonroot:nonroot
EXPOSE 8080
CMD ["/server"]
DO:
✓ Use multi-stage builds
✓ Order layers by change frequency (deps before code)
✓ Use .dockerignore
✓ Run as non-root
✓ Use COPY not ADD (unless extracting tar)
✓ Pin base image versions
DON'T:
✗ Use :latest in production
✗ Store secrets in image layers
✗ Install unnecessary packages
✗ Run as root
✗ Use ADD for remote URLs
Under the hood: Each Dockerfile instruction creates a new image layer. Layers are cached and reused across builds. This is why ordering matters: put
COPY go.mod go.sum ./andRUN go mod downloadbeforeCOPY . .— dependencies change rarely, so the download layer stays cached across code changes. Changing layer order can turn a 10-second build into a 5-minute rebuild.Gotcha:
docker stopsends SIGTERM and waits 10 seconds (default--stop-timeout), then sends SIGKILL. If your app does not handle SIGTERM, it always takes the full 10 seconds to stop. The same PID 1 problem exists here as in Kubernetes — useexecform in ENTRYPOINT or a lightweight init liketini.
Debugging¶
docker logs app --tail=50 -f # Tail logs
docker exec -it app bash # Shell into container
docker exec app env # Check env vars
docker inspect app # Full metadata
docker inspect -f '{{.State.Status}}' app
docker stats # Live resource usage
docker top app # Processes in container
docker diff app # Changed files
docker cp app:/path/file ./local # Copy file out
Networking¶
docker network ls
docker network create mynet
docker network inspect mynet
docker run --network mynet --name api myapp
docker run --network mynet --name db postgres
# api can reach db at hostname "db"
# Expose specific IP
docker run -p 127.0.0.1:8080:80 nginx
| Network | Use Case |
|---|---|
| bridge (default) | Container-to-container on same host |
| host | Container uses host networking directly |
| none | No networking |
| custom bridge | Containers communicate by name |
Volumes¶
docker volume create data
docker volume ls
docker volume inspect data
docker volume rm data
docker volume prune # Remove unused
# Mount types:
docker run -v mydata:/data app # Named volume
docker run -v /host/path:/data app # Bind mount
docker run --tmpfs /tmp app # tmpfs (in-memory)
Docker Compose¶
services:
api:
build: .
ports: ["8080:8080"]
environment:
DB_HOST: db
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: secret
healthcheck:
test: pg_isready -U postgres
interval: 5s
retries: 5
volumes:
pgdata:
docker compose up -d # Start all
docker compose down # Stop + remove
docker compose logs -f api # Follow logs
docker compose ps # Service status
docker compose exec api bash # Shell into service
docker compose build # Rebuild images
Cleanup¶
docker system prune # Remove stopped + unused
docker system prune -a --volumes # Remove everything unused
docker system df # Show disk usage