Skip to content

The docker run Command Explained with Real Examples

Understand docker run for real: -d, -p, -v, -e, --name, --rm, and --restart, with copy-paste examples for Nginx, Postgres, and one-off commands.

SDSysadmin Desk September 26, 2026 7 min read
Breakdown of a docker run command with each flag labeled: detached, port mapping, volume, environment, and name

docker run is the first command most people learn and the one they understand the least. It does a lot in a single line — pulls an image, creates a container, wires up ports and storage, sets environment variables, and starts the process — and the flags that control all that are easy to fumble.

This guide takes docker run apart with examples you can paste and run. We’ll go flag by flag through the ones you’ll actually use, then put them together into real commands for Nginx, Postgres, and quick one-off tasks.

One thing to get straight up front: docker run always creates a new container. It’s not how you restart something you stopped — that’s docker start. Run it twice and you have two containers.

The anatomy of a docker run command

Every docker run follows the same shape:

docker run [OPTIONS] IMAGE [COMMAND] [ARGS]

Options come first, then the image, then an optional command to run inside the container instead of the image’s default. A complete real example:

docker run -d --name web -p 8080:80 --restart unless-stopped nginx:1.27

That single line says: run the nginx:1.27 image detached, name the container web, publish container port 80 as host port 8080, and restart it automatically unless I stop it. Let’s unpack each flag.

The flags you’ll use constantly

The docker run flags worth memorizing

-d, --detach Run in the background and return your prompt. Use for services.
-p, --publish Map a port as HOST:CONTAINER, e.g. -p 8080:80.
-v, --volume Mount storage: a named volume or a host path into the container.
-e, --env Set an environment variable, e.g. -e POSTGRES_PASSWORD=secret.
--name Give the container a readable name instead of a random one.
--rm Delete the container automatically when it exits. Good for one-offs.
-it Interactive terminal: -i keeps stdin open, -t gives a TTY.
--restart Set a restart policy, e.g. unless-stopped.

-d: run in the background

Without -d, a container runs in the foreground and takes over your terminal until the process ends or you press Ctrl+C. That’s useful when you want to watch output, but for a service you want it out of the way:

# Foreground: terminal is occupied, logs stream live
docker run nginx:1.27

# Detached: runs in the background, prompt returns
docker run -d nginx:1.27

-p: publish a port

A container’s ports are isolated from the host until you publish them. The format is HOST:CONTAINER:

docker run -d -p 8080:80 nginx:1.27
# Browse to http://localhost:8080 — host 8080 maps to Nginx's port 80

-v: mount storage

-v attaches storage to a container so data lives outside it. There are two forms:

# Named volume (Docker manages where it lives on disk)
docker run -d -v db-data:/var/lib/postgresql/data postgres:16

# Bind mount (a specific host folder, absolute path)
docker run -d -v /home/me/site:/usr/share/nginx/html:ro nginx:1.27

A name with no slash (db-data) is a named volume. A path (/home/me/site) is a bind mount of that exact host folder. The :ro suffix makes the mount read-only. The differences matter more than they look — the bind mount vs named volume guide covers when to use each.

-e: set environment variables

Most official images are configured through environment variables. Repeat -e for each one:

docker run -d \
  -e POSTGRES_USER=appuser \
  -e POSTGRES_PASSWORD=change-me \
  -e POSTGRES_DB=appdb \
  postgres:16

For many variables, keep them in a file and load it with --env-file env.list instead of a long chain of -e flags.

Real examples you can paste

Nginx serving a local folder

Run a web server that serves files from a folder on your machine, named so it’s easy to manage, and set to survive reboots:

docker run -d \
  --name web \
  -p 8080:80 \
  -v "$(pwd)/site:/usr/share/nginx/html:ro" \
  --restart unless-stopped \
  nginx:1.27

Put an index.html in a site folder, run this from that folder’s parent, and open http://localhost:8080. The :ro keeps the container from writing to your files.

Postgres with a persistent volume

A database is the case where storage matters most. Use a named volume so the data survives the container:

docker run -d \
  --name pg \
  -e POSTGRES_USER=appuser \
  -e POSTGRES_PASSWORD=change-me \
  -e POSTGRES_DB=appdb \
  -v pg-data:/var/lib/postgresql/data \
  -p 5432:5432 \
  --restart unless-stopped \
  postgres:16

The POSTGRES_* variables come straight from the official Postgres image documentation — they’re read on first start to create the user and database. Remove and recreate the container all you like; as long as the pg-data volume exists, your data is there.

A one-off command with —rm

When you just want to run something once and not leave a stopped container behind, combine --rm with an interactive terminal:

# Drop into a shell in a temporary Ubuntu container, gone when you exit
docker run --rm -it ubuntu:24.04 bash

# Run a quick throwaway command and clean up
docker run --rm alpine echo "hello from a container"

--rm deletes the container the moment it exits, so these don’t accumulate. The -it pair gives you an interactive terminal for the shell example.

run vs start: a common mix-up

Because docker run creates a new container every time, using it to “restart” something leaves you with duplicates and orphaned state. The right commands once a container exists:

docker stop web      # stop a running container, keep it around
docker start web     # start it again with all its original settings
docker restart web   # stop then start in one step
docker rm web        # remove a stopped container for good

run vs start vs restart

docker run Create a brand-new container from an image and start it
docker start Start an existing, stopped container with its saved settings
docker restart Stop and start an existing container in one step
docker rm Delete a stopped container (data in named volumes survives)

Sanity-check a docker run before you press enter

  • -p has the host port on the left, container port on the right
  • -v uses a named volume for data you want to keep
  • Image tag is pinned to a real version, not 'latest'
  • Secrets come from --env-file, not inline -e in shell history
  • --rm only on throwaway runs, never on a service you want to keep

Where this leads

Once a docker run command grows past a few flags, you’re really describing a small configuration — and that’s exactly what Docker Compose is for. A long docker run becomes a few readable lines of YAML you can edit and commit. When you’re managing more than one container, that switch pays off fast; the Docker Compose beginner guide picks up right where this leaves off.

For now, the flags here — -d, -p, -v, -e, --name, --rm, and --restart — cover the large majority of what you’ll type day to day. Get comfortable with them and docker run stops being a magic incantation and becomes something you can read at a glance.

Frequently asked questions

What's the difference between docker run and docker start?

docker run creates a new container from an image and starts it. docker start restarts an existing container that you previously stopped, keeping its settings and data. If you run docker run twice you get two separate containers; use start to bring an existing one back.

What does the -d flag do?

-d runs the container detached, in the background, and returns your prompt. Without it, the container runs in the foreground and ties up your terminal, streaming its output until you stop it with Ctrl+C. Use -d for services and leave it off when you want to watch a one-off command.

Why isn't my published port reachable?

Check the order in -p HOST:CONTAINER. The left side is the host port you browse to, the right side is the port the app listens on inside the container. If the container port is wrong, or the host port is already taken, the connection fails. Confirm the app's real port on its Docker Hub image page.

What does --rm do and when should I use it?

--rm automatically deletes the container when it exits. It's ideal for one-off commands and tests so you don't pile up stopped containers. Don't use it for services or anything whose container state you want to keep, and remember data in named volumes survives regardless.

How do I pass configuration into a container?

Use -e KEY=value to set environment variables, repeating -e for each one, or --env-file to load many from a file. Most official images read their settings from environment variables documented on their Docker Hub page, like POSTGRES_PASSWORD for Postgres.

Sources & further reading

Official vendor documentation referenced while writing this guide.

SD

Sysadmin Desk

Infrastructure & Cloud

Hands-on guidance for infrastructure, virtualization, and containers — Hyper-V, VMware, Docker, and the day-to-day operations work that keeps environments running.

MCSA Guru provides independent, educational IT guidance. Microsoft, Windows, Windows Server, Microsoft 365, Exchange, and Microsoft Teams are trademarks of Microsoft Corporation; Docker is a trademark of Docker, Inc. MCSA Guru is not affiliated with or endorsed by Microsoft or Docker. Always test changes in a safe environment before applying them in production.

Related guides

Fixing something right now?

Jump straight into the guide library or search for the exact error or task you are dealing with.