Containers & Kubernetes18 min
Docker — Commands & Compose Cheat Sheet
Complete Docker reference — images, containers, volumes, networks, Dockerfile best practices, docker compose, and registry commands.
Images
# Pull an image
docker pull nginx:latest
docker pull ubuntu:22.04
# List images
docker images
docker image ls
# Inspect image
docker image inspect nginx:latest
# Build from Dockerfile
docker build -t myapp:v1 .
docker build -t myapp:v1 -f Dockerfile.prod .
docker build --no-cache -t myapp:v1 .
docker build --build-arg ENV=prod -t myapp:v1 .
# Tag an image
docker tag myapp:v1 myregistry.io/myapp:v1
docker tag myapp:v1 myapp:latest
# Push to registry
docker push myregistry.io/myapp:v1
# Remove images
docker rmi nginx:latest
docker image prune # Remove dangling images
docker image prune -a # Remove all unused images
# Save/load image as tar
docker save myapp:v1 -o myapp.tar
docker load -i myapp.tar
# Export/import container filesystem
docker export container-id -o container.tar
docker import container.tar myapp:imported
Containers
# Run a container
docker run nginx # Foreground, attached
docker run -d nginx # Detached (background)
docker run -d -p 8080:80 nginx # Map host:container port
docker run -d -p 8080:80 --name webserver nginx # Named container
docker run -it ubuntu:22.04 /bin/bash # Interactive shell
docker run --rm ubuntu echo "hello" # Auto-remove after exit
# Common run flags
docker run \
-d \ # detached
--name myapp \ # container name
-p 3000:3000 \ # port mapping
-e NODE_ENV=production \ # environment variable
-v /host/path:/container/path \ # bind mount
-v myvolume:/data \ # named volume
--network my-network \ # attach to network
--memory 512m \ # memory limit
--cpus 1.5 \ # CPU limit
--restart unless-stopped \ # restart policy
myapp:v1
# Manage containers
docker ps # Running containers
docker ps -a # All containers
docker stop myapp # Graceful stop (SIGTERM, then SIGKILL)
docker kill myapp # Immediate kill (SIGKILL)
docker start myapp # Start stopped container
docker restart myapp
docker pause myapp # Freeze (SIGSTOP)
docker unpause myapp
docker rm myapp # Remove stopped container
docker rm -f myapp # Force remove running container
docker container prune # Remove all stopped containers
# Logs
docker logs myapp # All logs
docker logs -f myapp # Follow live
docker logs --tail 100 myapp # Last 100 lines
docker logs --since 1h myapp # Last hour
# Exec into container
docker exec -it myapp /bin/bash
docker exec -it myapp sh
docker exec myapp cat /etc/nginx/nginx.conf # Non-interactive
# Inspect / stats
docker inspect myapp
docker stats # Live resource usage
docker stats --no-stream # One-shot stats
docker top myapp # Processes inside container
# Copy files
docker cp myapp:/etc/nginx/nginx.conf ./nginx.conf
docker cp ./config.yaml myapp:/app/config.yaml
Volumes
# Named volumes (managed by Docker)
docker volume create mydata
docker volume ls
docker volume inspect mydata
docker volume rm mydata
docker volume prune # Remove unused volumes
# Use named volume
docker run -d -v mydata:/var/lib/mysql mysql:8
# Bind mount (host directory)
docker run -d -v $(pwd)/data:/app/data myapp
# Read-only mount
docker run -d -v $(pwd)/config:/app/config:ro myapp
# tmpfs mount (in-memory, not persisted)
docker run -d --tmpfs /tmp:rw,size=256m myapp
Networks
# List networks
docker network ls
# Create network
docker network create my-net
docker network create --driver bridge my-net
docker network create --subnet 172.20.0.0/16 my-net
# Connect container to network
docker network connect my-net myapp
docker run -d --network my-net myapp
# Inspect network
docker network inspect my-net
# Disconnect
docker network disconnect my-net myapp
# Remove
docker network rm my-net
docker network prune # Remove unused networks
# Containers on the same user-defined network can reach each other by name
docker run -d --name db --network my-net postgres
docker run -d --name app --network my-net -e DB_HOST=db myapp
Dockerfile Reference
# Minimal, production-ready Node.js example
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
USER node
CMD ["node", "server.js"]
Key instructions:
FROM image[:tag] # Base image
WORKDIR /path # Set working directory
COPY src dest # Copy from build context
ADD src dest # Like COPY but also extracts tar/URL
RUN command # Execute at build time (creates layer)
ENV KEY=value # Environment variable
ARG NAME=default # Build-time argument
EXPOSE 8080 # Document port (doesn't publish!)
VOLUME ["/data"] # Declare volume mount point
USER username # Switch user for subsequent commands
ENTRYPOINT ["executable"] # Container entrypoint (not overridden by args)
CMD ["arg1", "arg2"] # Default command / args to ENTRYPOINT
HEALTHCHECK --interval=30s CMD curl -f http://localhost/ || exit 1
LABEL version="1.0" maintainer="ops@example.com"
Best practices:
- Combine
RUNcommands to reduce layers - Put rarely-changing instructions (like
COPY package.json) early for cache - Use multi-stage builds to minimize image size
- Use non-root
USER - Use
.dockerignoreto excludenode_modules,.git, secrets
Docker Compose
# docker-compose.yml
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_URL=postgres://user:pass@db:5432/mydb
depends_on:
db:
condition: service_healthy
volumes:
- ./uploads:/app/uploads
restart: unless-stopped
networks:
- app-net
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: mydb
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-net
volumes:
pgdata:
networks:
app-net:
driver: bridge
# Compose commands
docker compose up -d # Start in background
docker compose up --build -d # Rebuild then start
docker compose down # Stop + remove containers/networks
docker compose down -v # Also remove volumes
docker compose ps # Status
docker compose logs -f # Follow all logs
docker compose logs -f app # Follow specific service
docker compose exec app sh # Exec into service
docker compose pull # Pull latest images
docker compose restart app # Restart one service
docker compose scale app=3 # (v2 only: deprecated, use replicas)
Cleanup — Remove Everything Unused
docker system df # Disk usage summary
docker system prune # Remove stopped containers, dangling images, unused networks
docker system prune -a --volumes # Nuclear option: also volumes + all unused images
