TechEarl

docker run Cheat Sheet: Flags and Common Patterns

Every docker run flag I actually use, grouped by job: detach, interactive shells, ports, volumes, environment, network, restart, resources, platform, user, and the one-shot --rm pattern.

Ishan Karunaratne⏱️ 11 min readUpdated
Share thisCopied
Every docker run flag worth knowing, grouped by job: detach, interactive shells, ports, volumes, env, network, restart, resources, platform, user, and the --rm one-shot pattern.

docker run is the command you type most. Its flag list is long, but the working set is small. This page is that working set, grouped by what each flag actually does, with the patterns I reach for daily: detached services, interactive shells, port and volume mappings, environment variables, networks, restart policies, resource limits, and the one-shot --rm pattern for quick experiments.

Use the inputs above to swap the placeholders (IMAGE, CONTAINER, HOST_PORT, CONTAINER_PORT, VOLUME) into the commands below.

Try it with your own values

Set your image, container name, ports, and a volume name. Every example below updates as you type.

Jump to:

The 30-second shape of docker run

bash
docker run [FLAGS] :image [COMMAND] [ARGS...]

Everything before the image is a flag for docker run. Everything after the image is a command to run inside the container, overriding the image's CMD (and sometimes ENTRYPOINT). When in doubt about where the image goes:

bash
docker run -d --name :container -p :host_port::container_port :image

Image is always in the middle. Flags before, command after.

Detached vs interactive

bash
Detached: container runs in the background, prints the container ID, returns the shelldocker run -d --name :container :imageInteractive shell: attach a TTY and stdin, give me a shelldocker run -it --name :container :image bashUse sh when the image does not ship bash (alpine, distroless, scratch)docker run -it --name :container :image sh

-d is for services (databases, web servers). -it is for sessions where you are typing into the container. -i keeps stdin open, -t allocates a pseudo-TTY; the two are almost always used together when you want a shell.

If you start a service with -d and want a shell inside it later, do not re-run; use docker exec -it :container bash to attach. See docker exec.

Naming and auto-cleanup

bash
Name your container so you can find it againdocker run -d --name :container :imageRemove the container automatically when it exits (great for one-shots)docker run --rm -it :image command--rm + -it for a throwaway interactive shelldocker run --rm -it :image bash

Without --name, Docker invents a name like gracious_lalande. Fine for quick tests, miserable when you want to docker logs db after you've forgotten what it picked. With --rm, the container disappears the instant its main process exits — perfect for docker run --rm -it python:3.12 python style scratchpads.

Names must be unique. If you try to reuse one while the old container still exists (even stopped), the run fails. Either docker rm OLD_NAME first or pick a different name.

Publishing ports

bash
Publish container port 80 on host port 8080docker run -d --name :container -p :host_port::container_port :imagePublish on all interfaces (default) — accessible from anywhere on the networkdocker run -d -p :host_port::container_port :imagePublish only on localhost — not exposed to your LANdocker run -d -p 127.0.0.1::host_port::container_port :imageRandom host port (read the assignment with docker port :container)docker run -d -p :container_port :imageUDP port (default is TCP)docker run -d -p :host_port::container_port/udp :imageMultiple portsdocker run -d -p 80:80 -p 443:443 :image

Order matters: HOST:CONTAINER. The container always listens on its own port; the host side is what your browser / app on the host connects to. Containers on the same Docker network do not need published ports to reach each other — service-name DNS handles that. Publishing is only for traffic from the host or the outside world.

Volumes and bind mounts

bash
Named volume — Docker manages the underlying storagedocker run -d --name :container -v :volume:/path/in/container :imageBind mount — map a host directory into the containerdocker run -d --name :container -v /host/path:/path/in/container :imageRead-only bind mountdocker run -d -v /host/path:/path/in/container:ro :imageAnonymous volume — no name, persists in /var/lib/docker/volumes, hard to clean updocker run -d -v /path/in/container :imagetmpfsin-memory only, gone when the container stopsdocker run -d --tmpfs /tmp :image

The rule of thumb: named volumes for data you care about (databases, uploads, generated files); bind mounts for code you are editing on the host (development); tmpfs for caches and scratch space.

The full breakdown of when to use each is in Docker Volumes vs Bind Mounts.

Environment variables

bash
Single env vardocker run -e KEY=VALUE :imagePass an existing host env var through (no = sign)docker run -e DATABASE_URL :imageMultipledocker run -e KEY1=VALUE1 -e KEY2=VALUE2 :imageLoad from a filedocker run --env-file .env :image

--env-file reads a file of KEY=VALUE lines (one per line; # for comments). It is the cleanest way to keep secrets out of shell history. The trade-off is that everything in that file becomes an environment variable inside the container — there is no scoping.

ARG (build-time) and ENV (runtime) are different things. Full breakdown in Docker Environment Variables.

Networking

bash
Default bridge — works, but container-to-container by name does NOT resolve heredocker run -d --name :container :imageCreate and use a user-defined bridge — service-name DNS worksdocker network create app-net
docker run -d --name :container --network app-net :imageHost network (Linux only — on Mac and Windows this is more limited)docker run -d --network host :imageNo network at alldocker run -d --network none :imageAdd an /etc/hosts entrydocker run --add-host db:192.168.1.10 :image

The most useful network is a user-defined bridge (docker network create). On that network, containers can find each other by name: ping db from one container resolves to the container named db on the same network. The default bridge does not give you that.

--network host puts the container on the host's network stack — same IPs and ports. On Linux this is convenient and fast. On macOS and Windows it is more limited because Docker is running in a VM and "host" means the VM, not your Mac/PC. Full picture in Docker Networking Basics.

Restart policies

bash
Never restart (default)docker run -d --restart no :imageRestart if the process exits with a non-zero code, up to N timesdocker run -d --restart on-failure:5 :imageRestart always, even if you manually stopped itdocker run -d --restart always :imageRestart unless you explicitly stopped it (best default for services)docker run -d --restart unless-stopped :image

unless-stopped is what I use for almost every long-running service: it survives container crashes and host reboots, but it does not fight you when you actually meant to stop it. Compose uses the same values via restart: in docker-compose.yml. See Docker Restart Policies and Health Checks.

Resource limits (memory, CPU, PID)

bash
Cap memory at 512 MB (container OOM-kills past this)docker run -d --memory 512m :imageMemory + swap (the total)docker run -d --memory 512m --memory-swap 1g :imageCap CPU at 0.5 cores (50% of one core)docker run -d --cpus 0.5 :imagePin to specific CPUs (cores 0 and 2)docker run -d --cpuset-cpus 0,2 :imageCap process countdocker run -d --pids-limit 200 :image

Memory caps are the most useful — without them, a single container can OOM the whole host. On a multi-container host, set them. --cpus is fractional and easier to reason about than the older --cpu-quota / --cpu-period pair. Exit code 137 in docker logs (or docker inspect) is the OOM kill signature.

Platform, user, working directory

bash
Force the image platform (Apple Silicon running x86 images)docker run --platform linux/amd64 :imageRun as a specific UID:GIDdocker run --user 1000:1000 :imageRun as a named user inside the image (must exist in /etc/passwd)docker run --user node :imageOverride the working directorydocker run --workdir /app :imageSet the container hostnamedocker run --hostname app-1 :image

--user is the cheapest way to avoid leaving root-owned files behind on bind mounts. --platform linux/amd64 is the workaround when an image lacks an arm64 manifest and you are on Apple Silicon — slower (emulation) but unblocks you. See exec format error — Apple Silicon and Multi-Arch Docker Images.

Overriding ENTRYPOINT and CMD

bash
Override CMD (the default) by passing a new command after the imagedocker run :image echo helloOverride ENTRYPOINTdocker run --entrypoint sh :imageBoth — explicit entrypoint with argumentsdocker run --entrypoint /bin/sh :image -c "echo hello && sleep 1"

Inside a Dockerfile, ENTRYPOINT is the executable and CMD is the default arguments. At docker run time, anything after the image overrides CMD. To override ENTRYPOINT, you need the --entrypoint flag explicitly. This is the unlock for getting into images that ship with a stubborn ENTRYPOINT and refuse a shell otherwise:

bash
docker run --rm -it --entrypoint sh :image

Common one-liners

bash
# Throwaway interactive shell — gone when you exit
docker run --rm -it :image bash

# Throwaway shell in alpine (no bash)
docker run --rm -it :image sh

# Run a one-shot command with the working directory bind-mounted
docker run --rm -v $(pwd):/work -w /work :image command

# Run a one-shot command as the current user (no root-owned files)
docker run --rm -u $(id -u):$(id -g) -v $(pwd):/work -w /work :image command

# Try a CLI tool without installing it (e.g. jq, yq, ffmpeg)
docker run --rm -i ghcr.io/jqlang/jq <<< '{"a":1}'

# Run a service with the common production-ish defaults
docker run -d --name :container -p :host_port::container_port \
-v :volume:/data --restart unless-stopped :image

# Run with a healthcheck attached
docker run -d --name :container \
--health-cmd 'curl -f http://localhost/healthz || exit 1' \
--health-interval 30s --health-retries 3 :image

For the full "run X without installing X" pattern across databases, web servers, language runtimes, and dev tools, see How to Run Anything on Your Computer Without Installing It.

FAQ

Sources

Authoritative references this article was fact-checked against.

TagsDockerdocker runContainersCLICheat Sheet

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Software Systems Architect · Senior Software Engineer · Engineering Leadership

Software systems architect and senior software engineer with more than two decades designing, building, and running production software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Now a CTO, though what I write here is drawn from the full arc of that work, across architecture, engineering, and operations, not any single job.

Keep reading

Related posts