← Cheatsheets
Tags: docker, dockerfile, docker-compose, docker-desktop, volumes, networking, containers, windows, linux, devops
Last updated: 2026-07-02
Docker Cheatsheet
What Is Docker?
Docker packages applications into containers — lightweight, portable units that include everything needed to run (code, runtime, libraries, config). Containers share the host OS kernel, so they're far more efficient than VMs.
| Concept | What It Means |
| Image | A read-only template with instructions for creating a container |
| Container | A runnable instance of an image |
| Dockerfile | A recipe that defines how to build an image |
| Volume | Persistent storage that survives container restarts |
| Registry | A repo of images (Docker Hub, GitHub Container Registry) |
| Docker Compose | Define and run multi-container apps with a YAML file |
Installation
Docker Desktop (GUI — Windows & macOS)
Docker Desktop includes the Docker Engine, CLI, Docker Compose, a GUI dashboard, and Kubernetes support — all in one installer.
| OS | Download & Install |
| Windows | Download from docker.com — requires WSL 2 backend (auto-installed) |
| macOS | Same URL — Intel and Apple Silicon (ARM) builds available |
| Linux | Docker Desktop available, but most prefer CLI-only engine |
Docker Desktop GUI features: Dashboard (containers, logs, stats, exec), Images tab (browse, pull, inspect layers), Volumes tab (create/remove, see mounts), Settings (CPU, RAM, disk, registry credentials), Extensions (VS Code integration, etc.).
Docker Engine (CLI — Linux)
# Ubuntu/Debian
sudo apt update && sudo apt install docker.io
sudo systemctl enable --now docker
sudo usermod -aG docker $USER # Run docker without sudo (log out & back in)
# Official script (for most distros)
curl -fsSL https://get.docker.com | sh
Docker Engine (Windows — WSL 2)
# In PowerShell as admin:
wsl --install -d Ubuntu
# Then inside WSL Ubuntu:
sudo apt update && sudo apt install docker.io
sudo service docker start
Post-Install Verification
docker --version
docker compose version
docker run hello-world
Docker Desktop GUI Walkthrough
| Section | What You Can Do |
| Containers | Start, stop, restart, delete. Click one to see logs, inspect, exec a shell. |
| Images | Browse local images, pull from registry, delete, see layer history. |
| Volumes | List, create, delete, see mount paths and which container uses them. |
| Builds | View Docker build history and output. |
- Run a container: Images tab → click "Run" → set name, ports, volumes, env vars → "Run"
- View logs: Containers tab → click container → Logs tab (real-time)
- Exec into container: Containers tab → click container → Exec tab → type
sh
- Pull an image: Images tab → "Pull" → type image name (e.g.
nginx:latest)
- Resource limits: Settings → Resources → Set CPU, RAM, swap, disk image size
Docker Desktop vs CLI-Only
| Factor | Docker Desktop | CLI-Only Engine |
| Platform | Windows, macOS, Linux | Linux (or via WSL 2) |
| GUI | Yes — dashboard, settings, extensions | No — CLI only |
| Kubernetes | Bundled (toggle on/off) | Manual install |
| Resource overhead | Moderate (VM on macOS/Windows) | Minimal (native Linux) |
| Licensing | Free for personal/edu/small business | Free (community edition) |
CLI Quick Reference
# Container lifecycle
docker run nginx # Run foreground
docker run -d nginx # Run detached
docker run -d -p 8080:80 nginx # Port mapping
docker run --name my-nginx nginx # Named container
docker run --rm nginx # Auto-delete when stopped
docker run -it ubuntu bash # Interactive terminal
docker ps # Running containers
docker ps -a # All containers
docker stop # Graceful stop (SIGTERM)
docker kill # Immediate stop (SIGKILL)
docker start # Start stopped container
docker restart # Stop + start
docker rm # Remove stopped container
docker rm -f # Force remove (even running)
docker container prune # Remove all stopped
docker logs # View logs
docker logs -f # Follow (streaming)
docker exec -it sh # Shell into container
docker inspect # Full JSON metadata
docker stats # Live resource usage
# Images
docker images # List images
docker pull nginx # Download image
docker build -t myapp . # Build from Dockerfile
docker tag myapp user/myapp:v1 # Tag
docker push user/myapp:v1 # Push to registry
docker rmi # Delete image
docker system prune -a # Clean everything
docker system df # Disk usage
Windows-Specific (PowerShell)
# Same commands work in PowerShell
docker run -d -p 8080:80 --name web nginx
# Mount a Windows path
docker run -v C:/Users/me/data:/data myapp
# Switch to Windows containers:
& "C:\Program Files\Docker\Docker\DockerCli.exe" -SwitchDaemon
Dockerfile Reference
# 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
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
USER node
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/server.js"]
Dockerfile Instructions
| Instruction | Purpose |
FROM | Base image |
WORKDIR | Set working directory |
COPY | Copy files into image |
RUN | Execute build command |
ENV | Set environment variable |
ARG | Build-time variable |
EXPOSE | Document port |
CMD | Default command |
ENTRYPOINT | Executable (CMD becomes args) |
HEALTHCHECK | Container health probe |
USER | Switch user (security) |
LABEL | Metadata |
VOLUME | Declare mount point |
Layer Caching Best Practices
# ❌ BAD — reinstalls all deps on every code change
COPY . .
RUN npm install
# ✅ GOOD — deps cached until package.json changes
COPY package*.json ./
RUN npm install
COPY . .
- Order from least to most frequently changed.
- Combine
RUN commands with && to reduce layers.
- Use
.dockerignore to exclude node_modules, .git, .env.
- Use multi-stage builds to keep final images small.
Docker Compose
services:
app:
build: .
ports: ["3000:3000"]
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on:
db:
condition: service_healthy
volumes:
- .:/app
- /app/node_modules
restart: unless-stopped
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
interval: 10s
retries: 5
volumes:
pgdata:
Compose Commands
docker compose up -d # Start (detached)
docker compose up -d --build # Rebuild + start
docker compose down # Stop + remove
docker compose down -v # + remove volumes (⚠)
docker compose ps # Status
docker compose logs -f app # Follow logs
docker compose exec app sh # Shell into service
docker compose restart app # Restart service
docker compose build # Build images
docker compose pull # Pull latest
Volumes
docker volume create mydata
docker run -v mydata:/data myapp # Named volume
docker run -v /host/path:/app myapp # Bind mount
docker run --tmpfs /tmp myapp # In-memory (ephemeral)
docker volume ls
docker volume inspect mydata
docker volume prune
docker volume rm mydata
| Type | Use Case | Persists? |
| Named volume | Databases, persistent state | ✅ Yes |
| Bind mount | Dev (hot reload), config files | ✅ Yes |
| tmpfs | Cache, temp files, secrets | ❌ No |
Networking
docker network create mynet
docker run --network mynet --name db postgres
docker run --network mynet --name app myapp
# app can reach db at hostname "db"
docker network ls
docker network inspect mynet
docker network connect mynet mycontainer
docker network disconnect mynet mycontainer
# Port mapping
docker run -p 8080:80 nginx # Host:Container
docker run -P nginx # Random port for exposed ports
docker run -p 127.0.0.1:8080:80 nginx # Localhost only
Container Management
# Lifecycle
docker create nginx # Create (don't start)
docker pause # Freeze processes
docker unpause # Resume
# Copy files
docker cp myfile.txt :/app/
docker cp :/app/logs.txt ./
# Resource limits
docker run --memory=512m --cpus=1.5 nginx
docker run --memory-reservation=256m nginx
docker run --memory-swap=1g nginx
# Inspect
docker inspect --format '{{.State.Status}}'
docker port
docker top
Pushing & Pulling
docker login # Docker Hub
docker login ghcr.io # GitHub Container Registry
docker tag myapp user/myapp:v1.0.0
docker push user/myapp:v1.0.0
docker pull nginx:latest
# Multi-architecture build
docker buildx build --platform linux/amd64,linux/arm64 \
-t user/myapp:latest --push .
Troubleshooting
| Problem | Likely Cause | Fix |
| Cannot connect to Docker daemon | Service not running | Linux: systemctl start docker. Desktop: start the app. |
| Permission denied | User not in docker group | usermod -aG docker $USER + log out |
| Port already in use | Another container or process | docker ps → docker stop or lsof -i :8080 |
| No space left on device | Docker disk full | docker system prune -a + docker builder prune |
| Container exits immediately | App crashed | docker logs to see the error |
| Slow on macOS/Windows | VM resource limits | Increase RAM/CPU in Docker Desktop Settings |
| WSL 2 not working (Windows) | WSL 2 not set up | wsl --set-default-version 2. Enable in Desktop Settings. |
docker compose not found | Missing plugin | apt install docker-compose-plugin |
Tips & Advice
- Never run containers as root — use the
USER instruction.
- Use
.dockerignore to keep builds fast and small.
- Multi-stage builds are the best thing for image size.
- Use
docker compose down -v sparingly — it destroys volumes.
- Healthchecks matter — orchestrators use them to restart unhealthy containers.
- Tag images with versions — never use
:latest in production.
- Set memory & CPU limits to prevent one container starving others.
- Docker Desktop on Windows/macOS for GUI. CLI-only on Linux for servers.
- Clean up regularly —
docker system prune -a reclaims disk space.
- Pin base image versions —
node:20-alpine not node:latest.