
Docker Syntax Cli Containers
- 8 installs
- 9 repo stars
- Updated July 8, 2026
- openaec-foundation/docker-claude-skill-package
Helps with devops & ci/cd tasks.
About
docker-syntax-cli-containers is a Claude Code skill for devops & ci/cd. It helps solo builders move faster with AI-assisted development.
- docker-syntax-cli-containers
- DevOps & CI/CD
- AI-coding skill
Docker Syntax Cli Containers by the numbers
- 8 all-time installs (skills.sh)
- Ranked #1,044 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/docker-claude-skill-package --skill docker-syntax-cli-containersAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 8 |
|---|---|
| repo stars | ★ 9 |
| Last updated | July 8, 2026 |
| Repository | openaec-foundation/docker-claude-skill-package ↗ |
What it does
Helps with devops & ci/cd tasks.
Files
docker-syntax-cli-containers
Quick Reference
Container Lifecycle Overview
| Command | Purpose | Key Flags |
|---|---|---|
docker run | Create and start container | -d, -it, --rm, --name, -p, -v |
docker create | Create without starting | Same as run |
docker start | Start stopped container | -a (attach), -i (interactive) |
docker stop | Graceful stop (SIGTERM) | -t (grace period, default 10s) |
docker restart | Stop then start | -t (grace period) |
docker kill | Immediate signal | -s (signal, default SIGKILL) |
docker rm | Remove container | -f (force), -v (volumes) |
docker container prune | Remove all stopped | --filter |
docker exec | Run command in container | -it, -u, -w, -e |
docker logs | Read container output | -f, --tail, --since |
docker inspect | Container metadata | --format (Go templates) |
docker ps | List containers | -a, --filter, --format |
docker stats | Live resource usage | --no-stream, --format |
docker top | Container processes | Accepts ps options |
docker events | Real-time daemon events | --filter, --since |
docker cp | Copy files in/out | -a (archive mode) |
docker diff | Filesystem changes | A=Added, C=Changed, D=Deleted |
docker rename | Rename container | — |
docker update | Change resource limits | --memory, --cpus, --restart |
docker pause | Freeze container | — |
docker unpause | Resume container | — |
docker wait | Block until exit | Returns exit code |
docker port | Show port mappings | — |
docker attach | Attach to STDIN/STDOUT | --detach-keys |
docker run Flag Categories
| Category | Key Flags | Details |
|---|---|---|
| Execution | -d, -it, --rm, --name, --init | references/commands.md#execution |
| Ports & Network | -p, --network, --hostname, --dns | references/commands.md#ports--network |
| Storage | -v, --mount, --read-only, --tmpfs | references/commands.md#storage |
| Environment | -e, --env-file, -w, --entrypoint, -u | references/commands.md#environment |
| Resources | -m, --cpus, --pids-limit, --ulimit | references/commands.md#resources |
| Security | --cap-add, --cap-drop, --security-opt, --read-only | references/commands.md#security |
| Health | --health-cmd, --health-interval, --health-retries | references/commands.md#health |
| Restart | `--restart no\ | always\ |
| Logging | --log-driver, --log-opt | references/commands.md#logging |
| Pull & Platform | --pull, --platform | references/commands.md#pull--platform |
Critical Warnings
NEVER use --privileged in production -- it grants the container full host access. ALWAYS use specific --cap-add flags for the exact capabilities needed.
NEVER run containers as root unless technically required. ALWAYS use -u 1000:1000 or define USER in the Dockerfile.
NEVER use --link for container communication -- it is legacy. ALWAYS use user-defined bridge networks with --network.
NEVER use docker exec with chained commands directly -- the shell interprets && on the host. ALWAYS wrap in sh -c "cmd1 && cmd2".
NEVER run docker rm -f on production databases without confirming backups. ALWAYS stop gracefully with docker stop first.
ALWAYS use --rm for one-off containers (tests, migrations, debug shells) to prevent stopped container accumulation.
ALWAYS set --init when running applications that do not handle signals or reap zombie processes (e.g., shell scripts, Node.js without signal handlers).
---
docker ps -- Filter Cheat Sheet
Filter Options
| Filter | Match Type | Example |
|---|---|---|
name | Substring | --filter name=web |
status | Exact | --filter status=running |
ancestor | Image name/tag/ID | --filter ancestor=nginx:latest |
label | Key or key=value | --filter label=app=web |
exited | Exit code (with -a) | --filter exited=0 |
health | Health status | --filter health=healthy |
network | Network name/ID | --filter network=mynet |
volume | Volume name/mount | --filter volume=mydata |
publish | Published port | --filter publish=80/tcp |
before/since | Relative to container | --filter before=myapp |
Status Values
created | restarting | running | removing | paused | exited | dead
Format Placeholders
| Placeholder | Output |
|---|---|
{{.ID}} | Container ID |
{{.Names}} | Container name |
{{.Image}} | Image name |
{{.Status}} | Detailed status with health |
{{.State}} | State (running/exited) |
{{.Ports}} | Port mappings |
{{.RunningFor}} | Uptime |
{{.Size}} | Disk usage (with -s) |
{{.Label "key"}} | Specific label value |
{{.Networks}} | Network names |
{{.Mounts}} | Volume names |
# Useful one-liners
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
docker ps -a --filter status=exited --format "{{.Names}}: exited {{.Status}}"
docker ps -q --filter status=exited | xargs docker rm
docker ps --format json---
docker inspect -- Common Format Strings
Container State
docker inspect --format='{{.State.Status}}' CONTAINER
docker inspect --format='{{.State.Running}}' CONTAINER
docker inspect --format='{{.State.ExitCode}}' CONTAINER
docker inspect --format='{{.State.Pid}}' CONTAINER
docker inspect --format='{{.State.StartedAt}}' CONTAINERNetwork Information
# IP address
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' CONTAINER
# Port bindings
docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{$p}} -> {{(index $conf 0).HostPort}}{{end}}' CONTAINER
# Network name
docker inspect --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}}{{end}}' CONTAINERConfiguration
docker inspect --format='{{.Config.Image}}' CONTAINER
docker inspect --format='{{json .Config.Cmd}}' CONTAINER
docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' CONTAINER
docker inspect --format='{{json .Config.Labels}}' CONTAINER
docker inspect --format='{{index .Config.Labels "com.example.version"}}' CONTAINERMounts
docker inspect --format='{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}' CONTAINER
docker inspect --format='{{json .Mounts}}' CONTAINERSize
docker inspect --size -f '{{.SizeRootFs}}' CONTAINER
docker inspect --size -f '{{.SizeRw}}' CONTAINERHealth Check
docker inspect --format='{{.State.Health.Status}}' CONTAINER
docker inspect --format='{{json .State.Health}}' CONTAINER---
Decision Trees
Which Run Mode?
Need interactive shell?
├── YES → docker run -it --rm IMAGE bash
└── NO → Need background daemon?
├── YES → docker run -d --name NAME IMAGE
└── NO → One-off command?
├── YES → docker run --rm IMAGE COMMAND
└── NO → docker create + docker startWhich Stop Method?
Need graceful shutdown?
├── YES → docker stop [-t SECONDS] CONTAINER
│ (sends SIGTERM, waits grace period, then SIGKILL)
└── NO → Need immediate termination?
├── YES → docker kill CONTAINER
└── NO → Need to send specific signal?
└── YES → docker kill -s SIGNAL CONTAINERExec or Attach?
Need to run a NEW command in running container?
├── YES → docker exec -it CONTAINER COMMAND
└── NO → Need to connect to the MAIN process?
├── YES → docker attach CONTAINER
│ (Ctrl+P, Ctrl+Q to detach without stopping)
└── NO → Just need logs?
└── YES → docker logs -f CONTAINER---
Common Patterns
Production Container Launch
docker run -d \
--name myapp \
--restart unless-stopped \
--init \
-u 1000:1000 \
--read-only \
--tmpfs /tmp \
--cap-drop ALL \
--security-opt no-new-privileges=true \
-m 512m --cpus 1.5 --pids-limit 200 \
-p 127.0.0.1:8080:8080 \
--network mynet \
--mount source=appdata,target=/data \
-e NODE_ENV=production \
--log-opt max-size=10m --log-opt max-file=3 \
--health-cmd='curl -f http://localhost:8080/health || exit 1' \
--health-interval=30s \
myapp:v1.2.3Debug a Running Container
# Shell into container
docker exec -it myapp sh
# Check processes
docker top myapp
# Stream logs
docker logs -f --tail 100 myapp
# Resource usage
docker stats myapp --no-stream
# Filesystem changes
docker diff myapp
# Full metadata
docker inspect myapp | jq '.[0].State'Container Cleanup
# Remove specific stopped container and its anonymous volumes
docker rm -v myapp
# Remove ALL stopped containers
docker container prune -f
# Remove containers older than 24 hours
docker container prune -f --filter "until=24h"
# Force remove running container (emergency only)
docker rm -f myappCopy Files
# Extract logs from container
docker cp myapp:/var/log/app.log ./app.log
# Inject config into running container
docker cp ./config.yml myapp:/app/config.yml
# Archive mode (preserves UID/GID)
docker cp -a myapp:/app/data ./backup/Update Running Container Resources
docker update --memory 1g --cpus 2 myapp
docker update --restart always myapp
docker update --pids-limit 300 myapp---
Reference Links
- references/commands.md -- Complete flag reference for all container commands
- references/examples.md -- Common container management workflows
- references/anti-patterns.md -- CLI misuse patterns and corrections
Official Sources
- https://docs.docker.com/reference/cli/docker/container/
- https://docs.docker.com/reference/cli/docker/container/run/
- https://docs.docker.com/reference/cli/docker/container/exec/
- https://docs.docker.com/reference/cli/docker/container/logs/
- https://docs.docker.com/reference/cli/docker/container/ls/
- https://docs.docker.com/reference/cli/docker/inspect/
Container CLI Anti-Patterns
Common Docker container CLI misuse patterns with corrections. Docker Engine 24+.
---
1. Execution Anti-Patterns
AP-001: Using --privileged Instead of Specific Capabilities
# WRONG -- grants full host access
docker run --privileged myapp
# CORRECT -- grant only what is needed
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE --cap-add SYS_PTRACE myappWhy: --privileged disables ALL security isolation. The container can access ALL host devices, bypass AppArmor/SELinux, load kernel modules, and mount the host filesystem. ALWAYS drop all capabilities and add back only the specific ones required.
AP-002: Running as Root by Default
# WRONG -- runs as root inside container
docker run nginx
# CORRECT -- specify non-root user
docker run -u 1000:1000 nginx
# BEST -- define USER in Dockerfile
# USER 1001:1001Why: Root inside a container maps to root on the host (unless user namespaces are configured). A container escape vulnerability with root gives full host access. ALWAYS run as non-root.
AP-003: Not Using --rm for Throwaway Containers
# WRONG -- leaves stopped container behind
docker run ubuntu echo "hello"
docker run node:20 npm test
# CORRECT -- auto-cleanup
docker run --rm ubuntu echo "hello"
docker run --rm node:20 npm testWhy: Every docker run without --rm creates a stopped container that consumes disk space. Over time, hundreds of stopped containers accumulate. ALWAYS use --rm for one-off commands, tests, and debug sessions.
AP-004: Not Using --init for Signal Handling
# WRONG -- shell scripts and Node.js do not forward SIGTERM
docker run -d --name app node:20 node server.js
# CORRECT -- tini init process handles signals and reaps zombies
docker run -d --name app --init node:20 node server.jsWhy: Without --init, the application runs as PID 1 and must handle signals itself. Most applications (Node.js, Python, shell scripts) do NOT handle SIGTERM by default, causing docker stop to always wait the full grace period and then SIGKILL. --init adds tini as PID 1 which properly forwards signals and reaps zombie processes.
---
2. Networking Anti-Patterns
AP-005: Using --link for Container Communication
# WRONG -- legacy, deprecated
docker run --link redis:db myapp
# CORRECT -- use user-defined bridge network
docker network create mynet
docker run -d --name redis --network mynet redis
docker run -d --name myapp --network mynet myapp
# myapp can reach redis at hostname "redis"Why: --link is legacy and only works on the default bridge network. It does NOT support automatic DNS resolution, cannot be changed without recreating containers, and provides no network isolation. User-defined networks provide DNS, isolation, and live connect/disconnect.
AP-006: Using Default Bridge Network
# WRONG -- default bridge lacks DNS resolution
docker run -d --name redis redis
docker run -d --name myapp myapp
# myapp CANNOT reach redis by name
# CORRECT -- user-defined network with automatic DNS
docker network create mynet
docker run -d --name redis --network mynet redis
docker run -d --name myapp --network mynet myapp
# myapp reaches redis at hostname "redis"Why: The default bridge network does NOT provide DNS resolution between containers. Containers can only communicate by IP address, which changes on restart. ALWAYS create and use user-defined bridge networks.
AP-007: Exposing Ports on All Interfaces
# WRONG -- accessible from any network interface
docker run -p 8080:80 nginx
# CORRECT -- bind to localhost only (use reverse proxy for external access)
docker run -p 127.0.0.1:8080:80 nginxWhy: -p 8080:80 binds to 0.0.0.0, making the service accessible from any network interface, including the public internet. For services that should only be accessed via a reverse proxy or locally, ALWAYS bind to 127.0.0.1.
---
3. Exec Anti-Patterns
AP-008: Chained Commands Without Shell Wrapper
# WRONG -- && is interpreted by the HOST shell
docker exec myapp echo "step 1" && echo "step 2"
# "step 2" runs on the HOST, not in the container
# CORRECT -- wrap in shell
docker exec myapp sh -c 'echo "step 1" && echo "step 2"'Why: The host shell interprets &&, ||, |, ;, and redirections before Docker sees them. The second command runs on the host. ALWAYS wrap compound commands in sh -c "...".
AP-009: Exec Into Paused Container
# WRONG -- fails silently or with error
docker pause myapp
docker exec -it myapp bash # Will fail
# CORRECT -- unpause first
docker unpause myapp
docker exec -it myapp bashWhy: A paused container's processes are frozen by the cgroup freezer. Docker cannot execute new processes in a frozen cgroup. ALWAYS unpause before exec.
AP-010: Using Exec for Persistent Changes
# WRONG -- changes are lost when container is recreated
docker exec myapp apt-get update && apt-get install -y curl
docker exec myapp pip install requests
# CORRECT -- add to Dockerfile
# RUN apt-get update && apt-get install -y --no-install-recommends curl
# RUN pip install requestsWhy: docker exec changes exist only in the container's writable layer. When the container is removed and recreated (deployment, scaling, restart), all changes are lost. ALWAYS put required packages and configuration in the Dockerfile.
---
4. Lifecycle Anti-Patterns
AP-011: Using docker kill Instead of docker stop
# WRONG -- no graceful shutdown, data corruption risk
docker kill myapp
# CORRECT -- graceful shutdown with SIGTERM
docker stop myapp
# CORRECT -- with custom grace period for slow shutdown
docker stop -t 30 myappWhy: docker kill sends SIGKILL by default, which immediately terminates the process. Applications cannot flush buffers, close database connections, or finish in-flight requests. ALWAYS use docker stop for graceful shutdown. Use docker kill only for hung or unresponsive containers.
AP-012: Not Setting Restart Policy for Services
# WRONG -- container stays stopped after crash or host reboot
docker run -d --name api myapp
# CORRECT -- auto-restart on failure
docker run -d --name api --restart unless-stopped myapp
# CORRECT -- with retry limit for debugging
docker run -d --name api --restart on-failure:5 myappWhy: Without a restart policy, crashed containers stay stopped until manually restarted. After a host reboot, all containers remain stopped. ALWAYS set --restart unless-stopped or --restart on-failure:N for production services.
AP-013: Force-Removing Running Containers in Production
# WRONG -- immediate kill, no graceful shutdown
docker rm -f production-db
# CORRECT -- stop gracefully, then remove
docker stop -t 30 production-db
docker rm -v production-dbWhy: docker rm -f sends SIGKILL immediately, identical to docker kill followed by docker rm. For databases and stateful services, this risks data corruption. ALWAYS docker stop first with an appropriate grace period.
---
5. Resource Anti-Patterns
AP-014: Running Without Memory Limits
# WRONG -- container can consume all host memory
docker run -d myapp
# CORRECT -- set memory limit
docker run -d -m 512m myapp
# CORRECT -- with swap limit
docker run -d -m 512m --memory-swap 1g myappWhy: Without memory limits, a single container with a memory leak can consume all host memory, causing the OOM killer to terminate random processes including other containers. ALWAYS set -m for production containers.
AP-015: Running Without CPU Limits
# WRONG -- container can use 100% of all CPU cores
docker run -d myapp
# CORRECT -- limit CPU usage
docker run -d --cpus 1.5 myapp
# CORRECT -- with PID limit for fork bomb prevention
docker run -d --cpus 1.5 --pids-limit 200 myappWhy: Without CPU limits, a runaway process in one container can starve all other containers of CPU time. ALWAYS set --cpus and --pids-limit for production workloads.
AP-016: Disabling OOM Killer Without Memory Limit
# WRONG -- can hang the entire host
docker run --oom-kill-disable myapp
# CORRECT -- disable OOM kill only WITH a memory limit
docker run -m 512m --oom-kill-disable myappWhy: --oom-kill-disable without a memory limit means a container can consume unlimited memory. When the host runs out, the kernel has no container to OOM-kill, potentially freezing the entire system. NEVER use --oom-kill-disable without -m.
---
6. Storage Anti-Patterns
AP-017: Using -v Instead of --mount for Production
# WRONG -- -v silently creates host directories if they do not exist
docker run -v /nonexistent/path:/app/config myapp
# Creates /nonexistent/path as root-owned empty directory
# CORRECT -- --mount fails explicitly if source does not exist
docker run --mount type=bind,src=/etc/myapp/config,dst=/app/config myapp
# Error: source path does not existWhy: -v auto-creates missing host directories as root-owned empty directories, masking configuration errors. --mount fails immediately if the source does not exist, catching misconfiguration before the container starts. ALWAYS use --mount for production bind mounts.
AP-018: Not Using Named Volumes for Database Data
# WRONG -- anonymous volume, hard to manage
docker run -d postgres:16
# Volume gets random ID, lost if container is removed with --rm
# CORRECT -- named volume, persistent and manageable
docker run -d --mount source=pgdata,target=/var/lib/postgresql/data postgres:16Why: Anonymous volumes get random IDs that are difficult to identify and manage. They are automatically removed when the container is removed with --rm. Named volumes persist independently of container lifecycle and are easy to backup, restore, and share.
---
7. Logging Anti-Patterns
AP-019: Not Setting Log Rotation
# WRONG -- logs grow unbounded
docker run -d --name api myapp
# CORRECT -- set max log size and file count
docker run -d --name api \
--log-opt max-size=10m \
--log-opt max-file=3 \
myappWhy: The default json-file log driver has no size limit. A busy container can fill the entire disk with logs. ALWAYS set max-size and max-file log options, or configure defaults in /etc/docker/daemon.json.
AP-020: Searching Logs Without --since or --tail
# WRONG -- reads ALL logs (can be gigabytes)
docker logs myapp | grep error
# CORRECT -- limit the log window
docker logs --since 1h myapp 2>&1 | grep error
docker logs --tail 1000 myapp 2>&1 | grep errorWhy: docker logs without --since or --tail reads the entire log history. For long-running containers, this can be gigabytes of data, causing high memory usage and slow results. ALWAYS limit the scope.
---
8. Security Anti-Patterns
AP-021: Mounting Docker Socket Into Containers
# WRONG -- container gets full Docker API access (effectively root on host)
docker run -v /var/run/docker.sock:/var/run/docker.sock myapp
# CORRECT -- use Docker-in-Docker with limited permissions, or
# use a Docker API proxy that restricts operationsWhy: Mounting the Docker socket gives the container full control over the Docker daemon, which is equivalent to root access on the host. The container can create privileged containers, mount host filesystems, and escape completely. NEVER mount the Docker socket unless absolutely necessary (CI/CD runners), and ALWAYS pair with additional restrictions.
AP-022: Hardcoding Secrets in Environment Variables
# WRONG -- visible in docker inspect, docker history, process list
docker run -e DB_PASSWORD=mysecretpass myapp
# CORRECT -- use Docker secrets or file-based secrets
docker run --mount type=bind,src=/etc/secrets/db_pass,dst=/run/secrets/db_pass,readonly myapp
# Application reads /run/secrets/db_passWhy: Environment variables set via -e are visible in docker inspect, docker exec env, /proc/1/environ, and process listing. ALWAYS use file-based secrets or Docker Swarm secrets for sensitive data.
AP-023: Using latest Tag in Production
# WRONG -- unpredictable, different version on each pull
docker run -d myapp:latest
# CORRECT -- pin to specific version
docker run -d myapp:v2.1.0
# BEST -- pin to digest for supply chain security
docker run -d myapp@sha256:abc123...Why: The latest tag is mutable and can point to a different image at any time. Deployments become non-reproducible. ALWAYS pin to a specific version tag, and use digest pinning for critical production workloads.
---
Summary Table
| # | Anti-Pattern | Severity | Correction |
|---|---|---|---|
| AP-001 | --privileged in production | Critical | --cap-drop ALL --cap-add <specific> |
| AP-002 | Running as root | High | -u 1000:1000 or USER in Dockerfile |
| AP-003 | No --rm for throwaway containers | Low | ALWAYS --rm for one-off commands |
| AP-004 | No --init for signal handling | Medium | ALWAYS --init for non-signal-aware apps |
| AP-005 | Using --link | Medium | User-defined bridge network |
| AP-006 | Using default bridge | Medium | docker network create + --network |
| AP-007 | Ports on all interfaces | High | -p 127.0.0.1:port:port |
| AP-008 | Chained commands without shell | Medium | sh -c "cmd1 && cmd2" |
| AP-009 | Exec into paused container | Low | docker unpause first |
| AP-010 | Exec for persistent changes | Medium | Put in Dockerfile |
| AP-011 | docker kill for normal shutdown | High | docker stop with grace period |
| AP-012 | No restart policy | Medium | --restart unless-stopped |
| AP-013 | docker rm -f on production | High | docker stop then docker rm |
| AP-014 | No memory limit | High | -m 512m |
| AP-015 | No CPU limit | Medium | --cpus 1.5 --pids-limit 200 |
| AP-016 | OOM kill disabled without -m | Critical | ALWAYS pair with -m |
| AP-017 | -v for production bind mounts | Medium | --mount for explicit errors |
| AP-018 | Anonymous volumes for databases | High | Named volumes |
| AP-019 | No log rotation | High | --log-opt max-size=10m |
| AP-020 | Unbounded log reads | Low | --since or --tail |
| AP-021 | Mounting Docker socket | Critical | Avoid or use API proxy |
| AP-022 | Secrets in env vars | High | File-based secrets |
| AP-023 | latest tag in production | High | Pin specific version or digest |
Container Command Reference
Complete flag reference for all Docker container CLI commands. Docker Engine 24+.
---
docker run
Syntax: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Creates and starts a container in one step.
Execution
| Flag | Description | Default | Example |
|---|---|---|---|
-d, --detach | Run in background, print container ID | foreground | docker run -d nginx |
-i, --interactive | Keep STDIN open | closed | docker run -i ubuntu cat |
-t, --tty | Allocate pseudo-TTY | none | docker run -it ubuntu bash |
--rm | Auto-remove container on exit | persist | docker run --rm ubuntu echo hello |
--name | Assign container name | auto-generated | docker run --name web nginx |
--init | Run init process (forwards signals, reaps zombies) | disabled | docker run --init node app.js |
Ports & Network
| Flag | Description | Example |
|---|---|---|
-p, --publish | Publish port [host-ip:]host-port:container-port[/proto] | -p 8080:80 |
-P, --publish-all | Publish all EXPOSE ports to random host ports | -P |
--network | Connect to network (bridge, host, none, custom) | --network mynet |
--network-alias | Add DNS alias on the network | --network-alias web |
--ip | Static IPv4 address (user-defined networks only) | --ip 172.20.0.5 |
--ip6 | Static IPv6 address | --ip6 2001:db8::33 |
--dns | Custom DNS server | --dns 8.8.8.8 |
--dns-search | Custom DNS search domain | --dns-search example.com |
-h, --hostname | Set container hostname | -h myhost |
--add-host | Add host-to-IP mapping to /etc/hosts | --add-host myhost=8.8.8.8 |
--mac-address | Set MAC address | --mac-address 92:d0:c6:0a:29:33 |
--expose | Expose port (documentation only, no host binding) | --expose 80 |
--link | LEGACY -- NEVER use. Use --network instead | — |
Storage
| Flag | Description | Example |
|---|---|---|
-v, --volume | Bind mount or named volume (name:path[:opts]) | -v mydata:/data |
--mount | Declarative mount (preferred for production) | --mount type=volume,src=mydata,dst=/data |
--volumes-from | Mount volumes from another container | --volumes-from web:ro |
--read-only | Read-only root filesystem | --read-only |
--tmpfs | Mount tmpfs (in-memory filesystem) | --tmpfs /run:size=64k |
Environment
| Flag | Description | Example |
|---|---|---|
-e, --env | Set environment variable | -e DB_HOST=db |
--env-file | Read env vars from file | --env-file .env |
-w, --workdir | Set working directory inside container | -w /app |
--entrypoint | Override image ENTRYPOINT | --entrypoint /bin/sh |
-u, --user | Run as user (name or UID[:GID]) | -u 1000:1000 |
-l, --label | Set metadata label | -l app=web |
--label-file | Read labels from file | --label-file labels.txt |
Resources
| Flag | Description | Example |
|---|---|---|
-m, --memory | Memory limit (bytes, k, m, g) | -m 512m |
--memory-reservation | Memory soft limit | --memory-reservation 256m |
--memory-swap | Total memory + swap limit (-1 = unlimited) | --memory-swap 1g |
--cpus | Number of CPUs (decimal) | --cpus 1.5 |
-c, --cpu-shares | CPU shares (relative weight, default 1024) | -c 2048 |
--cpuset-cpus | Pin to specific CPUs | --cpuset-cpus 0-3 |
--pids-limit | Max PIDs in container (fork bomb prevention) | --pids-limit 200 |
--ulimit | Set ulimit values | --ulimit nofile=1024:2048 |
--shm-size | /dev/shm size | --shm-size 1g |
--blkio-weight | Block I/O weight (10-1000) | --blkio-weight 300 |
--device-read-bps | Limit device read rate | --device-read-bps /dev/sda:1mb |
--device-write-bps | Limit device write rate | --device-write-bps /dev/sda:1mb |
--oom-kill-disable | Disable OOM killer (use with -m) | --oom-kill-disable |
Security
| Flag | Description | Example |
|---|---|---|
--privileged | Full host privileges (NEVER use in production) | --privileged |
--cap-add | Add Linux capability | --cap-add SYS_PTRACE |
--cap-drop | Drop Linux capability | --cap-drop ALL |
--security-opt | Security options (AppArmor, SELinux, seccomp) | --security-opt no-new-privileges=true |
--device | Add host device to container | --device /dev/sda:/dev/xvdc |
--gpus | Add GPU devices | --gpus all |
--pid | PID namespace (host or container:NAME) | --pid=host |
--ipc | IPC namespace mode | --ipc host |
--userns | User namespace mode | --userns host |
--cgroupns | Cgroup namespace (host or private) | --cgroupns private |
Health
| Flag | Description | Default | Example |
|---|---|---|---|
--health-cmd | Health check command | none | --health-cmd='curl -f http://localhost/' |
--health-interval | Time between checks | 30s | --health-interval 30s |
--health-timeout | Max time for single check | 30s | --health-timeout 10s |
--health-retries | Consecutive failures for unhealthy | 3 | --health-retries 3 |
--health-start-period | Grace period during init | 0s | --health-start-period 40s |
--health-start-interval | Check interval during start period | 5s | --health-start-interval 5s |
--no-healthcheck | Disable health check from image | — | --no-healthcheck |
Restart
| Policy | Behavior | Example |
|---|---|---|
no | Never restart (default) | --restart no |
always | Always restart, including on daemon startup | --restart always |
unless-stopped | Like always but NOT after manual docker stop | --restart unless-stopped |
on-failure[:N] | Restart on non-zero exit, optional max retries | --restart on-failure:5 |
Logging
| Flag | Description | Example |
|---|---|---|
--log-driver | Logging driver (json-file, syslog, journald, etc.) | --log-driver json-file |
--log-opt | Log driver options (repeatable) | --log-opt max-size=10m --log-opt max-file=3 |
Pull & Platform
| Flag | Description | Example |
|---|---|---|
--pull | Pull policy: missing (default), always, never | --pull always |
--platform | Target platform | --platform linux/amd64 |
Signals
| Flag | Description | Default | Example |
|---|---|---|---|
--stop-signal | Signal to stop container | SIGTERM | --stop-signal SIGKILL |
--stop-timeout | Seconds before force kill after stop signal | 10 | --stop-timeout 30 |
--sig-proxy | Proxy signals to the process | true | --sig-proxy=false |
---
docker create
Syntax: docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
Accepts ALL the same flags as docker run. Creates the container without starting it. Use docker start afterward.
docker create --name myapp -p 8080:80 nginx
# Returns container ID
docker start myapp---
docker start
Syntax: docker start [OPTIONS] CONTAINER [CONTAINER...]
| Flag | Description |
|---|---|
-a, --attach | Attach STDOUT/STDERR and forward signals |
-i, --interactive | Attach container's STDIN |
--detach-keys | Override detach key sequence |
---
docker stop
Syntax: docker stop [OPTIONS] CONTAINER [CONTAINER...]
Sends SIGTERM, waits for grace period, then sends SIGKILL.
| Flag | Description | Default |
|---|---|---|
-t, --time | Grace period in seconds before SIGKILL | 10 |
-s, --signal | Signal to send instead of SIGTERM | SIGTERM |
---
docker restart
Syntax: docker restart [OPTIONS] CONTAINER [CONTAINER...]
Equivalent to docker stop followed by docker start.
| Flag | Description | Default |
|---|---|---|
-t, --time | Grace period in seconds | 10 |
-s, --signal | Signal to send | SIGTERM |
---
docker kill
Syntax: docker kill [OPTIONS] CONTAINER [CONTAINER...]
Sends a signal immediately (no grace period).
| Flag | Description | Default |
|---|---|---|
-s, --signal | Signal to send | SIGKILL |
---
docker rm
Syntax: docker rm [OPTIONS] CONTAINER [CONTAINER...]
| Flag | Description |
|---|---|
-f, --force | Force remove running container (sends SIGKILL first) |
-v, --volumes | Remove anonymous volumes attached to the container |
-l, --link | Remove the specified link only |
---
docker container prune
Syntax: docker container prune [OPTIONS]
Removes ALL stopped containers.
| Flag | Description |
|---|---|
-f, --force | No confirmation prompt |
--filter | Filter (e.g., until=24h, label=temp) |
---
docker exec
Syntax: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
| Flag | Description |
|---|---|
-d, --detach | Run in background |
-e, --env | Set environment variables |
--env-file | Load env vars from file |
-i, --interactive | Keep STDIN open |
-t, --tty | Allocate pseudo-TTY |
-u, --user | Run as username or UID |
-w, --workdir | Working directory inside container |
--privileged | Extended privileges |
ALWAYS wrap chained commands in a shell:
# CORRECT
docker exec myapp sh -c "echo a && echo b"
# WRONG -- && is interpreted by host shell
docker exec myapp echo a && echo bCannot exec into a paused container -- unpause first.
---
docker attach
Syntax: docker attach [OPTIONS] CONTAINER
Connects to the container's MAIN process (PID 1) STDIN/STDOUT/STDERR.
| Flag | Description | Default |
|---|---|---|
--detach-keys | Override detach key sequence | Ctrl+P, Ctrl+Q |
--no-stdin | Do not attach STDIN | false |
--sig-proxy | Proxy all signals to the process | true |
---
docker logs
Syntax: docker logs [OPTIONS] CONTAINER
| Flag | Description | Default |
|---|---|---|
-f, --follow | Stream live output | — |
-n, --tail | Number of lines from end | all |
-t, --timestamps | Show RFC3339Nano timestamps | — |
--since | Logs after timestamp or duration | — |
--until | Logs before timestamp or duration | — |
--details | Show extra metadata | — |
Timestamp formats: RFC 3339 (2024-01-01T00:00:00Z), Unix timestamps, Go duration strings (30m, 3h).
---
docker inspect
Syntax: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
| Flag | Description |
|---|---|
--format, -f | Go template format string |
--type | Restrict to type: container, image, network, volume |
-s, --size | Include size information |
---
docker stats
Syntax: docker stats [OPTIONS] [CONTAINER...]
| Flag | Description |
|---|---|
--all, -a | Show all containers (not just running) |
--no-stream | Single snapshot instead of live stream |
--no-trunc | Full container IDs |
--format | Go template format |
Format placeholders: {{.Name}}, {{.CPUPerc}}, {{.MemUsage}}, {{.MemPerc}}, {{.NetIO}}, {{.BlockIO}}, {{.PIDs}}.
---
docker top
Syntax: docker top CONTAINER [ps OPTIONS]
Displays running processes. Accepts standard ps options after the container name.
docker top myapp
docker top myapp aux
docker top myapp -o pid,user,%cpu,%mem,cmd---
docker events
Syntax: docker events [OPTIONS]
Real-time stream of Docker daemon events.
| Flag | Description |
|---|---|
--filter | Filter by: type, event, container, image, label, network, volume |
--since | Events after timestamp or duration |
--until | Events before timestamp or duration |
--format | Go template or json |
Event types: container, image, volume, network, daemon, plugin, node, service, secret, config.
---
docker wait
Syntax: docker wait CONTAINER [CONTAINER...]
Blocks until the container stops, then prints the exit code.
EXIT_CODE=$(docker wait myapp)---
docker cp
Syntax: docker cp [OPTIONS] SRC DEST
Either SRC or DEST must be CONTAINER:PATH.
| Flag | Description |
|---|---|
-a, --archive | Archive mode (preserves UID/GID) |
-L, --follow-link | Follow symlinks in SRC |
# Container to host
docker cp myapp:/app/log.txt ./log.txt
# Host to container
docker cp ./config.yml myapp:/app/config.yml
# Archive mode
docker cp -a myapp:/app/data ./backup/---
docker diff
Syntax: docker diff CONTAINER
Shows filesystem changes relative to the image.
| Symbol | Meaning |
|---|---|
A | File or directory added |
C | File or directory changed |
D | File or directory deleted |
---
docker rename
Syntax: docker rename CONTAINER NEW_NAME
Works on running or stopped containers.
---
docker update
Syntax: docker update [OPTIONS] CONTAINER [CONTAINER...]
Updates resource limits and restart policy on a running or stopped container.
| Flag | Description |
|---|---|
--memory, -m | Memory limit |
--memory-reservation | Memory soft limit |
--memory-swap | Memory + swap limit |
--cpus | Number of CPUs |
--cpu-shares, -c | CPU shares |
--cpuset-cpus | CPUs to pin to |
--pids-limit | Max PIDs |
--restart | Restart policy |
--blkio-weight | Block I/O weight |
---
docker pause / unpause
docker pause CONTAINER [CONTAINER...]
docker unpause CONTAINER [CONTAINER...]Pauses all processes in a container using cgroup freezer. ALWAYS unpause before attempting docker exec.
---
docker port
Syntax: docker port CONTAINER [PRIVATE_PORT[/PROTO]]
docker port myapp # All mappings
docker port myapp 80/tcp # Specific port---
docker ps / container ls
Syntax: docker ps [OPTIONS]
| Flag | Description |
|---|---|
-a, --all | Show all containers (not just running) |
-f, --filter | Filter output |
--format | Go template format or json |
-n, --last | Show n last created containers |
-l, --latest | Show the latest created container |
--no-trunc | Full output (no truncation) |
-q, --quiet | Container IDs only |
-s, --size | Display file sizes |
See SKILL.md for complete filter and format reference.
Container Management Workflows
Practical workflows for common Docker container operations. Docker Engine 24+.
---
1. Development Workflows
Start Interactive Development Container
# Node.js development with live code mount
docker run -it --rm \
--name dev \
-v "$(pwd)":/app \
-w /app \
-p 3000:3000 \
node:20-alpine \
sh
# Python development with pip cache
docker run -it --rm \
--name pydev \
-v "$(pwd)":/app \
-v pipcache:/root/.cache/pip \
-w /app \
-p 8000:8000 \
python:3.12-slim \
bashRun One-Off Commands
# Run tests
docker run --rm -v "$(pwd)":/app -w /app node:20-alpine npm test
# Run database migration
docker run --rm \
--network mynet \
-e DATABASE_URL=postgres://user:pass@db:5432/mydb \
myapp:latest \
python manage.py migrate
# Generate build artifact
docker run --rm -v "$(pwd)":/app -w /app golang:1.22 go build -o /app/serverDebug a Failing Container
# 1. Check why it exited
docker ps -a --filter name=myapp
docker logs --tail 50 myapp
# 2. Inspect the state
docker inspect --format='{{.State.ExitCode}}' myapp
docker inspect --format='{{.State.Error}}' myapp
# 3. Check filesystem changes
docker diff myapp
# 4. Start a shell in the stopped container's image
docker run -it --rm --entrypoint sh myapp:latest
# 5. Copy logs out before removing
docker cp myapp:/var/log/app.log ./debug-log.txt
docker rm myapp---
2. Production Workflows
Launch Production Service
docker run -d \
--name api \
--restart unless-stopped \
--init \
-u 1000:1000 \
--read-only \
--tmpfs /tmp \
--cap-drop ALL \
--security-opt no-new-privileges=true \
-m 512m --cpus 1.5 --pids-limit 200 \
-p 127.0.0.1:8080:8080 \
--network production \
--mount source=api-data,target=/data \
-e NODE_ENV=production \
--env-file /etc/myapp/env \
--log-opt max-size=10m --log-opt max-file=5 \
--health-cmd='curl -sf http://localhost:8080/health || exit 1' \
--health-interval=30s \
--health-timeout=5s \
--health-retries=3 \
--health-start-period=60s \
myapp:v2.1.0Launch Database with Persistent Storage
# PostgreSQL
docker run -d \
--name postgres \
--restart unless-stopped \
-u 999:999 \
--network production \
--mount source=pgdata,target=/var/lib/postgresql/data \
-e POSTGRES_PASSWORD_FILE=/run/secrets/pg_password \
--mount type=bind,src=/etc/secrets/pg_password,dst=/run/secrets/pg_password,readonly \
-m 1g --cpus 2 \
--shm-size 256m \
--log-opt max-size=10m --log-opt max-file=3 \
postgres:16-alpine
# Redis with memory limit
docker run -d \
--name redis \
--restart unless-stopped \
--network production \
--mount source=redisdata,target=/data \
-m 256m \
redis:7-alpine \
redis-server --maxmemory 200mb --maxmemory-policy allkeys-lruGraceful Deployment (Blue-Green)
# 1. Start new version alongside old
docker run -d --name api-v2 --network production \
-p 127.0.0.1:8081:8080 myapp:v2.0.0
# 2. Wait for health check
until docker inspect --format='{{.State.Health.Status}}' api-v2 | grep -q healthy; do
sleep 2
done
# 3. Switch traffic (update reverse proxy, then)
docker stop api-v1
docker rm api-v1
# 4. Rename new container
docker rename api-v2 api---
3. Monitoring Workflows
Live Resource Monitoring
# All running containers
docker stats
# Specific containers with custom format
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.PIDs}}" \
api postgres redis
# Single snapshot for scripts
docker stats --no-stream --format "{{.Name}}: CPU={{.CPUPerc}} MEM={{.MemUsage}}"Log Analysis
# Last 100 lines with timestamps
docker logs -t --tail 100 myapp
# Logs from the last hour
docker logs --since 1h myapp
# Follow live logs
docker logs -f --tail 0 myapp
# Logs between two timestamps
docker logs --since 2024-06-01T10:00:00 --until 2024-06-01T11:00:00 myapp
# Search logs (pipe to grep)
docker logs myapp 2>&1 | grep -i errorHealth Check Monitoring
# Current health status
docker inspect --format='{{.State.Health.Status}}' myapp
# Health check log (last 5 results)
docker inspect --format='{{range .State.Health.Log}}{{.ExitCode}} {{.Output}}{{end}}' myapp
# Full health JSON
docker inspect --format='{{json .State.Health}}' myapp | jq .
# List all unhealthy containers
docker ps --filter health=unhealthy --format "{{.Names}}: {{.Status}}"Event Monitoring
# Watch container start/stop/die events
docker events --filter type=container --filter event=start --filter event=stop --filter event=die
# Watch with structured output
docker events --format '{{.Time}} {{.Action}} {{.Actor.Attributes.name}}'
# Events from the last 10 minutes
docker events --since 10m --until 0s---
4. Maintenance Workflows
Batch Container Management
# Stop all running containers
docker stop $(docker ps -q)
# Remove all stopped containers
docker container prune -f
# Remove containers by label
docker rm $(docker ps -aq --filter label=environment=staging)
# Remove containers older than 24h
docker container prune -f --filter "until=24h"
# Restart all containers on a specific network
docker ps -q --filter network=production | xargs -r docker restartResource Limit Adjustment
# Increase memory for a running container
docker update --memory 1g --memory-swap 2g myapp
# Add CPU resources
docker update --cpus 4 myapp
# Change restart policy
docker update --restart unless-stopped myapp
# Apply limits to multiple containers
docker update --memory 256m --cpus 0.5 worker1 worker2 worker3Backup and Restore
# Backup: copy data from volume via helper container
docker run --rm \
--mount source=pgdata,target=/data,readonly \
-v "$(pwd)/backups":/backup \
alpine \
tar czf /backup/pgdata-$(date +%Y%m%d).tar.gz -C /data .
# Restore: extract backup into volume
docker run --rm \
--mount source=pgdata,target=/data \
-v "$(pwd)/backups":/backup \
alpine \
sh -c "rm -rf /data/* && tar xzf /backup/pgdata-20240601.tar.gz -C /data"
# Copy specific files from container
docker cp myapp:/app/uploads ./uploads-backup
# Copy config into running container
docker cp ./nginx.conf proxy:/etc/nginx/nginx.conf
docker exec proxy nginx -s reload---
5. Troubleshooting Workflows
Container Keeps Restarting
# 1. Check restart count and status
docker inspect --format='{{.RestartCount}} restarts, last exit: {{.State.ExitCode}}' myapp
# 2. Read recent logs
docker logs --tail 50 myapp
# 3. Check OOM kill
docker inspect --format='{{.State.OOMKilled}}' myapp
# 4. Check resource usage
docker stats --no-stream myapp
# 5. Temporarily disable restart to investigate
docker update --restart no myapp
docker stop myapp
docker logs --tail 200 myappContainer Cannot Reach Another Container
# 1. Verify both are on the same network
docker inspect --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}' container1
docker inspect --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}' container2
# 2. Check DNS resolution
docker exec container1 nslookup container2
# 3. Check connectivity
docker exec container1 ping -c 2 container2
# 4. Check container2 is actually listening
docker exec container2 netstat -tlnp
# 5. Check /etc/resolv.conf
docker exec container1 cat /etc/resolv.confPort Already In Use
# Find what is using the port
# Linux:
lsof -i :8080
# or
ss -tlnp | grep 8080
# Find which Docker container holds the port
docker ps --filter publish=8080
# Use a different host port
docker run -p 8081:8080 myappHigh Memory Usage Investigation
# 1. Check current memory usage
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}"
# 2. Check memory limit
docker inspect --format='{{.HostConfig.Memory}}' myapp
# 3. Check if OOM killed
docker inspect --format='{{.State.OOMKilled}}' myapp
# 4. Check processes inside container
docker top myapp -o pid,rss,cmd
# 5. Increase memory limit if needed
docker update --memory 1g myapp---
6. Scripting Patterns
Wait for Container Health
#!/bin/bash
CONTAINER=$1
TIMEOUT=60
ELAPSED=0
until [ "$(docker inspect --format='{{.State.Health.Status}}' "$CONTAINER" 2>/dev/null)" = "healthy" ]; do
if [ $ELAPSED -ge $TIMEOUT ]; then
echo "ERROR: $CONTAINER did not become healthy within ${TIMEOUT}s"
docker logs --tail 20 "$CONTAINER"
exit 1
fi
sleep 2
ELAPSED=$((ELAPSED + 2))
done
echo "$CONTAINER is healthy"Get Container IP on Specific Network
docker inspect --format='{{(index .NetworkSettings.Networks "mynet").IPAddress}}' myappList All Container Port Mappings
docker ps --format '{{.Names}}: {{.Ports}}' | grep -v "^$"Bulk Inspect with jq
# All container IPs
docker inspect $(docker ps -q) | jq -r '.[].NetworkSettings.Networks | to_entries[] | "\(.key): \(.value.IPAddress)"'
# All containers with their restart policy
docker inspect $(docker ps -aq) | jq -r '.[] | "\(.Name): \(.HostConfig.RestartPolicy.Name)"'Clean Exit with Wait
# Start container and wait for completion
docker run -d --name job myapp:latest process-data
EXIT_CODE=$(docker wait job)
docker logs job > job-output.log
docker rm job
exit $EXIT_CODE