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.
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 - Detached vs interactive
- Naming and auto-cleanup
- Publishing ports
- Volumes and bind mounts
- Environment variables
- Networking
- Restart policies
- Resource limits (memory, CPU, PID)
- Platform, user, working directory
- Overriding ENTRYPOINT and CMD
- Common one-liners
- FAQ
The 30-second shape of docker run
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:
docker run -d --name :container -p :host_port::container_port :imageImage is always in the middle. Flags before, command after.
Detached vs interactive
# Detached: container runs in the background, prints the container ID, returns the shell
docker run -d --name :container :image
# Interactive shell: attach a TTY and stdin, give me a shell
docker run -it --name :container :image bash
# Use 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
# Name your container so you can find it again
docker run -d --name :container :image
# Remove the container automatically when it exits (great for one-shots)
docker run --rm -it :image command
# --rm + -it for a throwaway interactive shell
docker run --rm -it :image bashWithout --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
# Publish container port 80 on host port 8080
docker run -d --name :container -p :host_port::container_port :image
# Publish on all interfaces (default) — accessible from anywhere on the network
docker run -d -p :host_port::container_port :image
# Publish only on localhost — not exposed to your LAN
docker run -d -p 127.0.0.1::host_port::container_port :image
# Random host port (read the assignment with docker port :container)
docker run -d -p :container_port :image
# UDP port (default is TCP)
docker run -d -p :host_port::container_port/udp :image
# Multiple ports
docker run -d -p 80:80 -p 443:443 :imageOrder 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
# Named volume — Docker manages the underlying storage
docker run -d --name :container -v :volume:/path/in/container :image
# Bind mount — map a host directory into the container
docker run -d --name :container -v /host/path:/path/in/container :image
# Read-only bind mount
docker run -d -v /host/path:/path/in/container:ro :image
# Anonymous volume — no name, persists in /var/lib/docker/volumes, hard to clean up
docker run -d -v /path/in/container :image
# tmpfs — in-memory only, gone when the container stops
docker run -d --tmpfs /tmp :imageThe 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
# Single env var
docker run -e KEY=VALUE :image
# Pass an existing host env var through (no = sign)
docker run -e DATABASE_URL :image
# Multiple
docker run -e KEY1=VALUE1 -e KEY2=VALUE2 :image
# Load from a file
docker 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
# Default bridge — works, but container-to-container by name does NOT resolve here
docker run -d --name :container :image
# Create and use a user-defined bridge — service-name DNS works
docker network create app-net
docker run -d --name :container --network app-net :image
# Host network (Linux only — on Mac and Windows this is more limited)
docker run -d --network host :image
# No network at all
docker run -d --network none :image
# Add an /etc/hosts entry
docker run --add-host db:192.168.1.10 :imageThe 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
# Never restart (default)
docker run -d --restart no :image
# Restart if the process exits with a non-zero code, up to N times
docker run -d --restart on-failure:5 :image
# Restart always, even if you manually stopped it
docker run -d --restart always :image
# Restart unless you explicitly stopped it (best default for services)
docker run -d --restart unless-stopped :imageunless-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)
# Cap memory at 512 MB (container OOM-kills past this)
docker run -d --memory 512m :image
# Memory + swap (the total)
docker run -d --memory 512m --memory-swap 1g :image
# Cap CPU at 0.5 cores (50% of one core)
docker run -d --cpus 0.5 :image
# Pin to specific CPUs (cores 0 and 2)
docker run -d --cpuset-cpus 0,2 :image
# Cap process count
docker run -d --pids-limit 200 :imageMemory 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
# Force the image platform (Apple Silicon running x86 images)
docker run --platform linux/amd64 :image
# Run as a specific UID:GID
docker run --user 1000:1000 :image
# Run as a named user inside the image (must exist in /etc/passwd)
docker run --user node :image
# Override the working directory
docker run --workdir /app :image
# Set the container hostname
docker 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
# Override CMD (the default) by passing a new command after the image
docker run :image echo hello
# Override ENTRYPOINT
docker run --entrypoint sh :image
# Both — explicit entrypoint with arguments
docker 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:
docker run --rm -it --entrypoint sh :imageCommon one-liners
# 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 :imageFor 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.
- docker run — official CLI referencedocs.docker.com
- Networking in Dockerdocs.docker.com
- Volumes — Docker docsdocs.docker.com



![Bash while loop reference: read files with while IFS= read -r, retry-with-backoff, wait-for-service polling, the subshell-scoping bug fix, the until and select siblings, plus [[ ]] vs [ ] vs (( )) test contexts.](https://techearl.com/cdn-cgi/image/width=1536,format=auto,quality=90/https://images.techearl.com/bash-while-loop/bash-while-loop.jpg?v=2026-04-25T13%3A18%3A00Z)
