Cheatsheet

Docker Commands Cheatsheet

This cheatsheet lists the Docker CLI commands and flags for running, inspecting, building and cleaning up containers, plus the Compose equivalents. It is for developers who know the idea of a container and want the exact command. The Docker glossary page explains what Docker is. The common confusion here is an image (a template) versus a container (a running or stopped instance of it). Every command below was run against Docker 29.6.2.

Quick reference

Run a container

Flag Meaning Example
`-d` Run in the background (detached) `docker run -d nginx:alpine`
`--name` Give the container a fixed name `--name web1`
`-p HOST:CONTAINER` Publish a container port on the host `-p 8080:80`
`-p 127.0.0.1:HOST:CONTAINER` Publish on the host loopback only `-p 127.0.0.1:8080:80`
`-e KEY=value` Set an environment variable `-e GREETING=hi`
`--env-file` Read variables from a file `--env-file .env`
`-v SRC:DEST[:ro]` Bind mount a path or named volume `-v $PWD:/data:ro`
`--rm` Delete the container when it exits `docker run --rm alpine:3.20 date`
`-it` Keep stdin open and allocate a terminal `docker run -it alpine:3.20 sh`
`--network` Attach to a named network `--network net1`
`-w` / `-u` Working directory / user inside the container `-w /app -u 1000`
`-m` / `--cpus` Memory and CPU limits `-m 512m --cpus 1.5`
`--entrypoint` Replace the image entrypoint `--entrypoint sh`
`--read-only` Mount the root filesystem read only `--read-only`

Restart policies

Policy Behavior
`no` Never restart. This is the default
`on-failure[:max-retries]` Restart only on a non-zero exit code, optionally up to a limit
`always` Restart whenever it stops. A manually stopped container comes back when the daemon restarts
`unless-stopped` Like `always`, but a manually stopped container stays stopped after a daemon restart

Inspect and operate

Command What it does
`docker ps` List running containers. Add `-a` for stopped ones
`docker logs -f --tail 100 NAME` Follow the last 100 log lines (`-t` adds timestamps)
`docker exec -it NAME sh` Open a shell in a running container
`docker inspect -f '{{.State.Status}}' NAME` Read one field from the JSON detail
`docker port NAME` Show published port mappings
`docker cp NAME:/path ./path` Copy a file out of (or into) a container
`docker stats --no-stream` One snapshot of CPU and memory use
`docker stop` / `kill` / `restart` Stop gracefully, kill, or restart
`docker rm -f NAME` Remove a container, even a running one

Images, volumes, networks

Command What it does
`docker build -t name:tag .` Build an image from the Dockerfile in the current directory
`docker images` List local images
`docker pull` / `push` Download or upload an image
`docker tag SRC NEW` Add another name to an image
`docker rmi name:tag` Remove an image tag
`docker volume create` / `ls` / `rm` Manage named volumes
`docker network create` / `ls` / `rm` Manage networks

Compose and cleanup

Command What it does
`docker compose up -d` Create and start every service in `compose.yaml`
`docker compose ps` List the project's containers
`docker compose logs --tail 50 web` Show logs for one service
`docker compose config` Print the merged, validated configuration
`docker compose down` Stop and remove containers and the default network
`docker container prune -f` Remove all stopped containers
`docker image prune -a` Remove all images not used by a container
`docker system prune` Remove stopped containers, unused networks, dangling images and unused build cache

Common patterns

Run a throwaway command and see its exit code

docker run --rm alpine:3.20 echo hello
docker run --rm alpine:3.20 sh -c 'exit 3'; echo "exit=$?"
hello
exit=3

--rm keeps stopped containers from piling up. The shell sees the exit code of the command inside the container, which makes docker run usable in scripts and CI steps. Without --rm, a finished container stays in docker ps -a until you remove it.

Start a long-running container with env, a read-only mount and a restart policy

docker run -d --name web1 -e GREETING=hi -v /tmp/dc:/data:ro --restart unless-stopped alpine:3.20 sh -c 'echo $GREETING; ls /data; sleep 300'
docker logs web1
docker inspect -f '{{.HostConfig.RestartPolicy.Name}} {{.State.Status}}' web1
hi
compose.yaml
unless-stopped running

Logs show what the main process wrote to stdout and stderr, so log to the console rather than to files inside the container. The inspect template pulls just the two fields you care about.

Publish a port to the host only

docker run -d --name n1 -p 127.0.0.1:8081:80 nginx:alpine
curl -s -o /dev/null -w "%{http_code}\n" localhost:8081/
docker port n1
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
200
80/tcp -> 127.0.0.1:8081
NAMES     IMAGE          STATUS
n1        nginx:alpine   Up 1 second

Binding to 127.0.0.1 keeps the port off the network. Without that prefix, the port is reachable from other machines. The --format 'table ...' template lets you choose the columns docker ps prints.

Build an image and run it

printf 'FROM alpine:3.20\nRUN echo built > /msg\nCMD ["cat","/msg"]\n' > Dockerfile
docker build -q -t demo:1 .
docker run --rm demo:1
sha256:cf9d34fbd893f3e3be9e6fb0831ccf72b11a9a7c81cf22084bdfa578a2c0372b
built

-q prints only the image ID. The ID will differ on your machine.

Let two containers talk by name

docker network create net1
docker run -d --name n2 --network net1 nginx:alpine
docker run --rm --network net1 alpine:3.20 wget -qO- -T 3 http://n2 | head -3
<!DOCTYPE html>
<html>
<head>

On a user-defined network, containers resolve each other by container name. On the default bridge network the same lookup failed in this run with wget: bad address 'n4', so create a network when services must find each other. Compose does this for you by creating a project network.

Run Compose and validate the file first

docker compose config
docker compose up -d
docker compose ps --format '{{.Service}} {{.State}} {{.Ports}}'
docker compose down
web running 127.0.0.1:8082->80/tcp

Run docker compose config before up. It prints the resolved file, expands defaults such as the dc_default network, and fails on YAML or schema mistakes. The project name comes from the directory name, so web in a directory called dc becomes the container dc-web-1. down removes the containers and that network but keeps named volumes unless you add -v.

Pitfalls

  • Port already in use: Starting a second container on a published port fails with Bind for 127.0.0.1:8082 failed: port is already allocated. Stop the first container or pick another host port.
  • -it in a script or CI job: docker exec -it prints cannot attach stdin to a TTY-enabled container because stdin is not a terminal. Drop -t when there is no terminal.
  • Published ports skip your firewall rules: Docker writes its own firewall rules, so ufw rules may not block a published port. Docker's docs say a port published without an IP is reachable from outside the host. Bind to 127.0.0.1 or put a reverse proxy in front.
  • Exit code 127 and "executable file not found": Running docker run --rm alpine:3.20 nosuchcmd ends with exec: "nosuchcmd": executable file not found in $PATH and exit 127. The binary is not in the image, so check the image contents or the command spelling.
  • Exit 137 after docker stop: Status Exited (137) means the process was killed with SIGKILL, either because it ignored SIGTERM past the timeout or because of an out-of-memory kill. Handle SIGTERM in PID 1.
  • docker system prune surprises: It removes stopped containers and unused networks, but volumes are only pruned with --volumes, and then only anonymous ones. Build cache is always eligible. Use -f only when you have read what it lists.
  • Forgetting -d and losing the terminal: Without -d, docker run stays attached and Ctrl+C stops the container. Add -d, then read output with docker logs.
  • :latest is just a tag: It does not mean newest. Pin a version such as nginx:1.27 so a rebuild gives the same image.
  • Bind-mount permission errors: A container user with a different UID cannot write to a host directory. Match -u to the owner or fix the host mode, as described in the chmod Permissions Cheatsheet.

Related ZipKit tools

Related cheatsheets