A living quick-reference for the Docker commands I actually use. Each section pairs commands with the moment you’d reach for them. For the model behind any of this, see Docker Foundations.
Getting Help
# Top-level help
docker --help
# Help for a subcommand
docker run --help
# Version of client and daemon
docker version
# Daemon info: storage driver, root dir, runtime
docker info
Running Containers
# Run in foreground, remove when it exits
docker run --rm -it ubuntu bash
# Run detached, name it, publish a port
docker run -d --name web -p 8080:80 nginx
# Set an environment variable
docker run -e POSTGRES_PASSWORD=secret postgres
# Mount a named volume
docker run -v pgdata:/var/lib/postgresql/data postgres
# Mount the current directory as a bind mount
docker run -v "$(pwd)":/app node
# Limit CPU and memory
docker run --cpus="1.5" --memory="512m" myapp
# Auto-restart on failure or reboot
docker run -d --restart=unless-stopped --name api myapp
Note:
-itis two flags glued together.-ikeeps STDIN open,-tallocates a pseudo-TTY. You almost always want both for an interactive shell.
Listing and Inspecting
# Running containers
docker ps
# All containers, including stopped
docker ps -a
# Just IDs (useful for piping)
docker ps -q
# Full details (JSON)
docker inspect web
# Pull one field out with a Go template
docker inspect -f '{{.NetworkSettings.IPAddress}}' web
# Live CPU, memory, network, I/O
docker stats
# Snapshot of stats (one read, no streaming)
docker stats --no-stream
Logs
# Dump all logs
docker logs web
# Follow (like tail -f)
docker logs -f web
# Last 100 lines, with timestamps
docker logs --tail 100 -t web
# Since a relative time
docker logs --since 10m web
Exec and Shell Access
# Open an interactive shell in a running container
docker exec -it web bash
docker exec -it web sh # for alpine / distroless-ish images
# Run a one-off command without a shell
docker exec web ls /etc/nginx
# Run as a specific user
docker exec -u root -it web bash
Gotcha:
docker execrequires the container to be running. To poke inside a stopped one, start it first ordocker runa fresh shell against the same image.
Lifecycle
# Start, stop, restart by name or ID
docker start web
docker stop web
docker restart web
# Pause / unpause (freezes processes via cgroups freezer)
docker pause web
docker unpause web
# Remove a stopped container
docker rm web
# Force-remove a running container
docker rm -f web
# Rename
docker rename old-name new-name
Building Images
# Build from current directory, tag the result
docker build -t myapp:1.0 .
# Use a non-default Dockerfile
docker build -f Dockerfile.dev -t myapp:dev .
# Build without using the cache
docker build --no-cache -t myapp:1.0 .
# Pass a build argument
docker build --build-arg VERSION=1.2.3 -t myapp:1.2.3 .
# Target a specific stage in a multi-stage build
docker build --target build -t myapp:build .
# Build for a different platform (needs buildx)
docker buildx build --platform linux/amd64,linux/arm64 -t me/app:1.0 --push .
Images
# List local images
docker images
# Pull a specific tag
docker pull postgres:16.3
# Tag an existing image
docker tag myapp:1.0 ghcr.io/me/myapp:1.0
# Remove an image
docker rmi myapp:old
# Show the layer history of an image
docker history nginx
# Save an image to a tarball (for air-gapped transfer)
docker save -o nginx.tar nginx:latest
# Load an image from a tarball
docker load -i nginx.tar
Registry
# Log in (Docker Hub by default)
docker login
# Log in to a specific registry
docker login ghcr.io
docker login -u USERNAME ghcr.io # prompts for password / token
# Push an image
docker push ghcr.io/me/myapp:1.0
# Log out
docker logout ghcr.io
Networking
# List networks
docker network ls
# Create a user-defined bridge network
docker network create appnet
# Run a container on a specific network
docker run -d --name db --network appnet postgres
# Attach an existing container to another network
docker network connect appnet web
# Detach
docker network disconnect appnet web
# Inspect (shows connected containers and their IPs)
docker network inspect appnet
# Remove
docker network rm appnet
Note: On a user-defined network, containers resolve each other by name. From
webyou can reachdbasdb:5432, no IP juggling.
Volumes
# List volumes
docker volume ls
# Create a named volume
docker volume create pgdata
# Inspect (shows the mountpoint on the host)
docker volume inspect pgdata
# Remove
docker volume rm pgdata
# Remove all unused volumes
docker volume prune
Copying Files
# Copy from container to host
docker cp web:/etc/nginx/nginx.conf ./nginx.conf
# Copy from host to container
docker cp ./nginx.conf web:/etc/nginx/nginx.conf
Docker Compose
# Bring the stack up in the background
docker compose up -d
# Bring it up and rebuild changed images
docker compose up -d --build
# Tail logs from all services
docker compose logs -f
# Tail logs from one service
docker compose logs -f api
# List services in this project
docker compose ps
# Run a one-off command in a service container
docker compose run --rm api python manage.py migrate
# Exec into a running service
docker compose exec api bash
# Restart a single service
docker compose restart api
# Tear it all down (containers + networks)
docker compose down
# Tear it down and delete named volumes too
docker compose down -v
Danger:
docker compose down -vremoves named volumes for the project. Postgres data, Redis snapshots, anything you put in a volume, all gone. Use plaindownif you want to keep state across restarts.
Cleanup
# Remove stopped containers, dangling images, unused networks, and build cache
docker system prune
# Same, but also remove unused images (not just dangling)
docker system prune -a
# Add unused volumes to the sweep
docker system prune -a --volumes
# Disk usage breakdown
docker system df
# Targeted prunes
docker container prune
docker image prune
docker network prune
docker volume prune
Danger:
docker system prune -a --volumesdeletes any volume that isn’t currently attached to a container. Stop a Postgres container to upgrade it, run this, lose your data.
Quick Debug Recipes
# What's eating disk?
docker system df -v
# Why did this container exit?
docker inspect -f '{{.State.ExitCode}} {{.State.Error}}' CONTAINER
# Get a shell in a broken image without running its entrypoint
docker run --rm -it --entrypoint sh myapp:broken
# See what ports a container actually published
docker port web
# Diff: what files has the container changed vs the image?
docker diff web