Bookmark this page. Use Ctrl+F (or Cmd+F on Mac) to find what you need. This cheat sheet covers Docker CLI commands, Dockerfile instructions, Docker Compose, volumes, networking, and production tips.
Last updated: March 2026
How Docker Works
┌──────────────┐ docker build ┌──────────┐ docker run ┌────────────┐
│ Dockerfile │ ───────────────► │ Image │ ─────────────► │ Container │
│ (recipe) │ │ (template)│ │ (running) │
└──────────────┘ └──────────┘ └────────────┘
│
docker push
│
┌────▼───────┐
│ Registry │
│ (Docker Hub)│
└────────────┘
Container Commands
| Command | Description |
|---|---|
docker run <image> | Create and start a container |
docker run -d <image> | Run in background (detached) |
docker run -it <image> bash | Run interactively with shell (sh for Alpine) |
docker run -p 8080:80 <image> | Map host port 8080 to container port 80 |
docker run --name myapp <image> | Run with a custom name |
docker run --rm <image> | Automatically remove container when it stops |
docker run -e KEY=value <image> | Set environment variable |
docker run -v /host:/container <image> | Mount a volume |
docker ps | List running containers |
docker ps -a | List all containers (including stopped) |
docker stop <container> | Stop a running container |
docker start <container> | Start a stopped container |
docker restart <container> | Restart a container |
docker rm <container> | Remove a stopped container |
docker rm -f <container> | Force remove (even if running) |
docker exec -it <container> bash | Open a shell inside a running container |
docker logs <container> | View container logs |
docker logs -f <container> | Follow logs in real-time |
docker inspect <container> | Show detailed container info (JSON) |
docker stats | Live resource usage for all containers |
docker cp <container>:/path ./local | Copy file from container to host |
docker cp ./local <container>:/path | Copy file from host to container |
docker container prune | Remove all stopped containers |
docker kill <container> | Force stop a container (SIGKILL) |
Image Commands
| Command | Description |
|---|---|
docker images | List all local images |
docker pull <image> | Download an image from registry |
docker push <image> | Upload an image to registry |
docker build -t myapp . | Build image from Dockerfile in current dir |
docker build -t myapp:v1 . | Build with a tag/version |
docker tag <image> <new-tag> | Add a tag to an image |
docker rmi <image> | Remove an image |
docker image prune | Remove unused (dangling) images |
docker system prune -a | Remove all unused images, containers, networks (not volumes) |
docker system prune -a --volumes | Remove everything including volumes |
docker history <image> | Show image layers and sizes |
docker login | Log in to Docker Hub (required before push) |
docker logout | Log out from registry |
docker save -o image.tar <image> | Export image to tar file |
docker load -i image.tar | Import image from tar file |
Dockerfile Reference
# Base image
FROM node:20-alpine
# Set working directory
WORKDIR /app
# Copy dependency files first (for caching)
COPY package.json package-lock.json ./
# Install dependencies
RUN npm ci --production
# Copy application code
COPY . .
# Expose a port (documentation only)
EXPOSE 3000
# Default command when container starts
CMD ["node", "server.js"]
Dockerfile Instructions
| Instruction | Description |
|---|---|
FROM <image> | Base image (required, must be first) |
WORKDIR /app | Set working directory for subsequent commands |
COPY <src> <dest> | Copy files from host to image |
ADD <src> <dest> | Like COPY but can extract tar and fetch URLs |
RUN <command> | Execute command during build (creates a layer) |
ENV KEY=value | Set environment variable |
ARG KEY=value | Build-time variable (not available at runtime) |
EXPOSE <port> | Document which port the app listens on |
CMD ["executable", "arg"] | Default command (can be overridden) |
ENTRYPOINT ["executable"] | Fixed command (CMD becomes arguments) |
VOLUME /data | Create a mount point for persistent data |
USER <username> | Switch to non-root user |
| `HEALTHCHECK CMD curl -f http://localhost/ |
CMD vs ENTRYPOINT
# CMD — default command, can be overridden
CMD ["python", "app.py"]
# docker run myapp → runs python app.py
# docker run myapp bash → runs bash (overrides CMD)
# ENTRYPOINT — fixed command, CMD becomes arguments
ENTRYPOINT ["python"]
CMD ["app.py"]
# docker run myapp → runs python app.py
# docker run myapp test.py → runs python test.py
Multi-Stage Build
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Production (smaller image)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Multi-stage builds produce smaller images — the final image only contains the production output, not the build tools.
Docker Compose
docker-compose.yml Example
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on:
- db
volumes:
- ./src:/app/src # bind mount for development
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data # named volume
ports:
- "5432:5432"
volumes:
pgdata: # named volume persists data
Compose Commands
| Command | Description |
|---|---|
docker compose up | Start all services |
docker compose up -d | Start in background (detached) |
docker compose up --build | Rebuild images and start |
docker compose down | Stop and remove containers |
docker compose down -v | Stop and remove containers + volumes |
docker compose logs | View logs for all services |
docker compose logs -f app | Follow logs for one service |
docker compose ps | List running services |
docker compose exec app bash | Open shell in a running service |
docker compose build | Build/rebuild images |
docker compose pull | Pull latest images |
docker compose restart | Restart all services |
docker compose stop | Stop without removing |
docker compose watch | Auto-sync file changes to containers (hot reload) |
Volumes
| Type | Syntax | Use case |
|---|---|---|
| Named volume | -v mydata:/app/data | Persistent data (databases) |
| Bind mount | -v ./src:/app/src | Development (live code changes) |
| Anonymous volume | -v /app/node_modules | Temporary data |
docker volume create mydata # Create a named volume
docker volume ls # List all volumes
docker volume inspect mydata # Show volume details
docker volume rm mydata # Remove a volume
docker volume prune # Remove unused volumes
Networking
docker network create mynetwork # Create a custom network
docker network ls # List networks
docker network inspect mynetwork # Show network details
docker network rm mynetwork # Remove a network
Containers on the same network can reach each other by service name:
# In docker-compose.yml, the app can connect to the database using:
# postgres://user:pass@db:5432/mydb
# ^^
# service name = hostname
| Network Type | Description |
|---|---|
bridge | Default — containers can communicate via IP |
host | Container shares the host network (no port mapping) |
none | No networking |
.dockerignore
node_modules
.git
.env
*.md
Dockerfile
docker-compose.yml
.DS_Store
Always add .dockerignore — it speeds up builds and prevents copying sensitive files.
Production Tips
| Tip | Why |
|---|---|
Use specific image tags (node:20-alpine, not node:latest) | Reproducible builds |
Run as non-root user (USER node) | Security |
| Use multi-stage builds | Smaller images |
Use HEALTHCHECK | Automatic container recovery |
Set restart: unless-stopped in Compose | Auto-restart on failure |
Use .dockerignore | Faster builds, no secrets in image |
Use docker scout cves <image> | Scan for vulnerabilities |
| Copy dependency files first, then code | Better layer caching |
docker buildx build --platform linux/amd64,linux/arm64 | Multi-platform builds (ARM + x86) |
Useful One-Liners
# Remove all stopped containers
docker container prune
# Remove all unused images, containers, networks, volumes
docker system prune -a --volumes
# Get container IP address
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container>
# Copy file from container to host
docker cp <container>:/app/file.txt ./file.txt
# View image size
docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}"
Common Mistakes
Not using
.dockerignore— Without it,docker buildcopies everything (includingnode_modules,.git,.env) into the build context. This makes builds slow and can leak secrets into the image.Using
latesttag in production —FROM node:latestmeans your build can break when the upstream image updates. Always pin a specific version:FROM node:20-alpine.Running as root — By default, containers run as root. If an attacker escapes the container, they have root on the host. Add
USER node(or another non-root user) in your Dockerfile.
Related Resources
- Git Cheat Sheet — Git commands quick reference
- SQL Cheat Sheet (coming soon)
- Linux/Terminal Cheat Sheet (coming soon)
- All Cheat Sheets