Docker Cheat Sheet & Workflows¶
1. Command Reference¶
1.1. Project Management (Docker Compose)¶
Primary method for managing stacks.
| Command | Description |
|---|---|
docker compose up -d |
Create/Start services in detached mode. |
docker compose up -d --force-recreate |
Force container recreation (useful if config changed but image didn't). |
docker compose restart |
Stop then restart containers. Does not rebuild/pull updated images. |
docker compose down |
Stop and remove containers/networks. |
docker compose down -v |
DANGER: Removes containers AND standard volumes. |
docker compose down --volumes --rmi all --remove-orphans |
DANGER: Removes containers, all volumes, all images used by the stack, and orphaned containers not defined in the current compose file. |
docker compose stop |
Stops services without removing containers. |
docker compose pull |
Pulls the image tags written in the YAML (with pinned tags, nothing changes until you edit the tag). |
docker compose logs -f |
Stream logs for all services in the stack. |
docker compose config -q |
Validate only: exit code 0 or the error. Run before every deploy. |
docker compose config |
Print the resolved configuration (shows .env secrets in clear text). |
docker compose ps |
Stack status, including (healthy) / (unhealthy). |
docker compose exec <svc> <cmd> |
Run command inside service (e.g., docker compose exec pihole bash). |
1.2. Container & Resource Monitoring¶
Debugging individual containers or checking resource load.
| Command | Description |
|---|---|
docker ps |
List running containers. |
docker ps -a |
List all containers (including stopped/exited). |
docker stats |
Live stream of CPU, RAM, and Net I/O usage per container. |
docker logs -f <container> |
Follow log output for a specific container (e.g., omada-controller). |
docker inspect <container> |
JSON dump of container config (IP address, mounts, env vars). |
docker inspect --format '{{json .State.Health}}' <container> |
Healthcheck status and the last few probe outputs. |
docker ps --filter health=unhealthy |
Everything currently unhealthy. |
docker top <container> |
Display the running processes of a container. |
1.3. Storage & Volumes¶
Managing persistence. Critical for the "External Volume" workflow.
| Command | Description |
|---|---|
docker volume ls |
List all volumes. |
docker volume create <name> |
Manually create a volume (required for external: true). |
docker volume inspect <name> |
Show volume mount point (usually /var/lib/docker/volumes/...). |
docker volume rm <name> |
Delete a volume. Data loss permanent. |
docker volume prune |
Remove unused anonymous local volumes. Add -a (docker volume prune -a) to also remove unused named volumes. |
docker run --rm -v <vol>:/data busybox ls /data |
Quickly list files inside a volume without attaching to the main app. |
1.4. Networking¶
Essential for debugging communication issues.
| Command | Description |
|---|---|
docker network ls |
List all created networks. |
docker network inspect <net_name> |
Show containers and IP addresses assigned to a specific network. |
docker network create <name> |
Create a manual bridge network. |
docker network prune |
Remove all unused networks. |
1.5. System Maintenance (Housekeeping)¶
Periodic cleanup.
| Command | Description |
|---|---|
docker image prune -a |
Remove all unused images (frees disk space). |
docker system df |
Show docker disk usage summary. |
docker system prune |
Cleanup: Removes stopped containers, unused networks, and dangling images. |
docker system prune -a --volumes |
Nuclear: Wipes everything not currently running. |
2. Workflows¶
2.1. Deploying New Stack (External Volume Method)¶
Standard procedure for stateful services (Omada, Databases).
-
Pre-create Volumes:
-
Deploy:
-
Verify Persistence:
2.2. Updating a Stack¶
Images are pinned, so an update is a tag change, not a pull of :latest.
With GitOps (how my stacks run), Renovate opens a PR that bumps the tag; merging it redeploys the stack. See GitOps and Compose Conventions.
By hand:
cd /opt/docker/project_name
# 1. Edit the image tag in compose.yaml (read the release notes first)
# 2. Validate, pull, recreate only changed containers
docker compose config -q && docker compose pull && docker compose up -d
# 3. Check health, then clean up old images
docker compose ps
docker image prune -f
2.3. "Hot" Backup of a Volume¶
Backup data without stopping the container (using tar).
# Syntax: docker run --rm -v <volume_name>:/data -v <host_backup_dir>:/backup alpine tar czf /backup/<filename>.tar.gz -C /data .
docker run --rm \
-v omada_data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/omada_data_backup_$(date +%F).tar.gz -C /data .
2.4. Debugging Connectivity¶
If services (e.g., Pi-hole, Unbound) are not responding.
# 1. Check if container is healthy
docker ps
# 2. Check internal IP assignment
docker network inspect bridge_network_name
# 3. Test resolution from INSIDE the container
docker exec -it pihole nslookup google.com 127.0.0.1
3. Environment Variables (.env)¶
Separates configuration (passwords, versions, ports) from the code (compose.yaml).
3.1. Directory Location¶
The .env file must be located in the same directory as the compose.yaml file for Docker Compose to automatically read it.
File Structure:
/opt/docker/
├── homepage/ # Project Stack (dashboard)
│ ├── .env # <--- GOES HERE (Specific to Homepage)
│ └── compose.yaml
├── omada/ # Project Stack (Network)
│ ├── .env # <--- GOES HERE (Specific to Omada)
│ └── compose.yaml
└── couchdb/ # Project Stack (Obsidian Sync)
├── .env # <--- GOES HERE (Specific to CouchDB)
└── compose.yaml
Keep .env files mode 600 (chmod 600 .env). In a GitOps setup the deploy tool writes .env from its secret
store, so it never exists in the repo.
3.2. Syntax Rules¶
- Format:
KEY=VALUE - No Spaces:
PASSWORD = 123is invalid. UsePASSWORD=123. - Comments: Use
#for comments. - Special Characters: If a password contains
#,$, or spaces, wrap the value in quotes:DB_PASS="Secure#Pass$123".
3.3. Workflow Example (CouchDB)¶
-
Create the file:
-
Define Variables:
-
Implement in
compose.yaml: Use the${VARIABLE_NAME}syntax.
3.4. Verification¶
To verify that Docker is reading the variables correctly without actually starting the container:
docker compose config -q # just validate: silent on success
docker compose config # print the resolved YAML
The second form prints the "resolved" YAML to the terminal, showing the actual values instead of the ${VAR} placeholders, secrets included.
3.5. Security (Git)¶
NEVER commit .env files to GitHub. They contain secrets.
Ensure the global .gitignore includes:
Sources & further reading¶
- Docker Compose CLI reference
- Variable interpolation and
.env - Lessons learned: Docker & systemd