| Tested on | Red Hat Enterprise Linux 10.2 (Coughlan) |
|---|---|
| Package | podman-5.8.2-5.el10_2.x86_64 |
| Applies to | Any Linux host with Podman installed |
| Privilege | Rootful examples on the lab host; flags behave the same rootless unless noted |
| Scope | Practical podman run workflow — syntax, foreground and detached mode, -it, --name, -p, -e, -v, --rm, --restart, --stop-signal, and create vs run. Does not cover full volume management, SELinux mounts, networking architecture, lifecycle commands, health checks, or every CLI flag. |
| Related guides | Install Podman on RHEL What is Podman? List containers with podman ps |
podman run is how you turn an image into a running container on Linux. You choose runtime options, name the image, and optionally override the command the container executes. This guide walks through the flags you use in real workflows — not every line from podman run --help.
Podman run command syntax
The general form is:
podman run [options] IMAGE [command [arguments...]]Three positions matter:
- Options (
-d,-p,-e, and the rest) come before the image name. IMAGEis the OCI image reference Podman pulls or finds locally.- Everything after the image replaces or extends the image default command.
Start with the hello image to exercise pull, create, start, and cleanup:
podman run --rm quay.io/podman/helloSample output:
!... Hello Podman World ...!Behind that one line, Podman checks local storage, pulls the image if needed, creates the container, starts the OCI runtime, waits for the foreground process, and removes the container when --rm is set. For component-level detail, see Podman architecture — this page stays on the command workflow.
Run a container in the foreground or background
A foreground run attaches the container's main process to your terminal. Output prints directly; your shell returns when the process exits.
podman run --rm registry.access.redhat.com/ubi9/ubi-minimal echo "Hello from Podman"Sample output:
Hello from PodmanDetached mode (-d) starts the container and returns immediately with the container ID:
podman run -d --name podman-run-demo registry.access.redhat.com/ubi9/ubi-minimal sleep 300Sample output (container ID):
664605894eaebb6d0ee5229b68cdef74b9da7c8daddea5e8573020897d4d1457Confirm the container is still running:
podman ps --filter name=podman-run-demoSample output:
664605894eae podman-run-demo Up 5 secondsDetached does not mean the container stays up forever — it means your shell is free while PID 1 keeps running. If the main process exits, the container stops even in -d mode. When a detached container vanishes right after start, see Fix Podman container exits immediately for exit-code diagnosis.
Run an interactive container with -it
Treat -i and -t as separate switches:
-i— keep STDIN open (piped input or typing)-t— allocate a pseudo-TTY (full-screen shell programs)
Interactive shell session:
podman run --rm -it registry.access.redhat.com/ubi9/ubi-minimal /bin/bashInside the container, cat /etc/redhat-release confirms you are in the UBI image. Type exit to leave the shell; --rm deletes the container.
Piped input without a TTY uses -i alone:
echo "piped input" | podman run --rm -i registry.access.redhat.com/ubi9/ubi-minimal catSample output:
piped inputUse -it for shells and terminal UIs. Use -i without -t for pipelines. Batch commands need neither. To run a command in an already-running container, use Run commands with podman exec instead of starting a second shell with run.
Name containers with --name
Generated names like objective_williams are fine for throwaway tests; names you choose are easier in scripts.
podman run -d --name web-demo registry.access.redhat.com/ubi9/ubi-minimal sleep 300List by name:
podman ps --filter name=web-demo --format '{{.Names}} {{.Status}}'Sample output:
web-demo Up 2 secondsLater commands accept the name, full ID, or a unique prefix of the ID.
Reusing a name that is already taken fails:
podman run -d --name web-demo registry.access.redhat.com/ubi9/ubi-minimal sleep 300Sample output:
Error: creating container storage: the container name "web-demo" is already in use by 7e358f642fb78d68b1e5fd0a9e0120e001d18b2a6427e859f81ad3411e265836. You have to remove that container to be able to reuse that name: that name is already in use, or use --replace to instruct Podman to do so.Remove the old container with podman rm web-demo, or pass --replace when you intentionally want Podman to recreate the name.
Publish container ports with -p
Port publishing maps a host port to a port inside the container:
HOST_PORT:CONTAINER_PORTNginx listens on port 80 inside the image, so map host 8080 to container 80:
podman run -d --name web-demo -p 8080:80 docker.io/library/nginx:alpineBind only the loopback interface when the service should not face the LAN:
127.0.0.1:8080:80Ask Podman which bindings exist:
podman port web-demoSample output:
80/tcp -> 0.0.0.0:8080A quick HTTP check from the host confirms the mapping:
curl -sI http://127.0.0.1:8080/ | head -2Sample output:
HTTP/1.1 200 OK
Server: nginx/1.31.4Rootless privileged ports, firewalld rules, pod-level publishing, and source-IP behavior belong in Podman port mapping — not here.
Pass environment variables with -e
Inline environment variables set container configuration at start time:
podman run --rm -e APP_ENV=production registry.access.redhat.com/ubi9/ubi-minimal printenv APP_ENVSample output:
productionAdd multiple -e flags for several variables. Pass a host variable when the name already exists on the host:
podman run --rm -e HOME registry.access.redhat.com/ubi9/ubi-minimal printenv HOMEFor many keys, use a file:
podman run --rm --env-file /path/to/app.env registry.access.redhat.com/ubi9/ubi-minimal printenvEnvironment variables are fine for non-sensitive configuration such as APP_ENV or LOG_LEVEL. They are not a substitute for secrets — use Podman secrets when values must not appear in inspect output or process listings.
Mount storage with -v
Volume mounts connect host storage to a path inside the container:
SOURCE:CONTAINER_PATHCreate a named volume first:
podman volume create podman-run-dataMount it and write a file:
podman run --rm -v podman-run-data:/data registry.access.redhat.com/ubi9/ubi-minimal sh -c 'echo hello > /data/example.txt'Read the file back in a new container using the same volume:
podman run --rm -v podman-run-data:/data registry.access.redhat.com/ubi9/ubi-minimal cat /data/example.txtSample output:
helloNamed volumes persist after the container exits. Bind mounts use a host directory path as SOURCE instead of a volume name — see Podman volumes and Podman bind mount vs volume for depth. SELinux labels (:z, :Z, :U) and permission errors are covered in the volume permissions guide.
Automatically remove containers with --rm
--rm deletes the container record when the main process exits:
podman run --rm registry.access.redhat.com/ubi9/ubi-minimal echo "temporary container"Sample output:
temporary containerNothing remains in podman ps -a for that run.
Anonymous volumes behave differently from named volumes. An anonymous mount uses only a container path:
podman run --rm -v /data registry.access.redhat.com/ubi9/ubi-minimal sh -c 'echo anon-test > /data/t.txt'Podman creates an anonymous volume for /data and removes it when the --rm container exits — the volume count on the lab host stayed unchanged across that run.
Without --rm, removing the container leaves the anonymous volume on disk until you prune it. Named volumes such as podman-run-data survive regardless of --rm because they are separate objects you manage with podman volume.
Configure container restart policies
--restart tells Podman what to do when the container process exits:
| Policy | Behavior |
|---|---|
no |
Default — do not restart |
on-failure |
Restart when exit code is non-zero |
on-failure:N |
Restart at most N times on failure |
always |
Always restart when the process exits |
unless-stopped |
Like always, except after an explicit stop |
Demonstrate on-failure:3 with a command that always fails:
podman run -d --name fail-demo --restart=on-failure:3 registry.access.redhat.com/ubi9/ubi-minimal sh -c 'exit 1'After a few seconds, read the restart counter:
podman inspect --format 'Status={{.State.Status}} Restarts={{.RestartCount}} ExitCode={{.State.ExitCode}}' fail-demoSample output:
Status=stopped Restarts=3 ExitCode=1Podman retried three times, then stopped. podman stop or podman kill is different from a process crash — you are telling Podman to stop, not waiting for a failure policy.
On reboot, podman-restart.service can restart containers with applicable policies. When systemd or Quadlet owns the unit, set Restart= in the unit file instead of relying on --restart alone. Rootless logout behavior is a separate topic — see the container-stops-after-logout and rootless Quadlet lessons when services must survive user sessions.
Understand container signals and --stop-signal
podman stop sends a stop signal to PID 1, waits for a timeout, then escalates to SIGKILL. Images may define a default stop signal; you override it at create time:
podman run -d --name signal-demo --stop-signal=SIGINT registry.access.redhat.com/ubi9/ubi-minimal sleep 300Confirm the stored signal:
podman inspect --format 'StopSignal={{.Config.StopSignal}}' signal-demoSample output:
StopSignal=SIGINTsleep does not handle SIGINT gracefully, so podman stop may still escalate after the timeout — the lab showed a SIGKILL fallback. Production images should use a PID 1 that traps the stop signal. Full start, stop, and kill behavior lives in Start, stop, and restart containers.
podman create vs podman run
| Command | What it does |
|---|---|
podman create |
Create container storage and config; do not start PID 1 |
podman run |
Create and start in one step |
Create without starting:
podman create --name created-demo registry.access.redhat.com/ubi9/ubi-minimal sleep 300The command prints a container ID. Check state:
podman ps -a --filter name=created-demo --format '{{.Names}} {{.Status}}'Sample output:
created-demo CreatedStart it when you are ready:
podman start created-demoSample output:
created-demoVerify running status:
podman ps --filter name=created-demo --format '{{.Names}} {{.Status}}'Sample output:
created-demo Up 1 secondUse create when something else triggers the start (automation, inspection, or a delayed podman start). Use run for the usual immediate workflow.
Useful podman run examples
| Task | Example |
|---|---|
| One-shot command | podman run --rm IMAGE echo hello |
| Background service | podman run -d --name svc IMAGE sleep 300 |
| Interactive shell | podman run --rm -it IMAGE /bin/bash |
| Fixed name | podman run -d --name myapp IMAGE |
| Published port | podman run -d -p 8080:80 IMAGE |
| Environment | podman run --rm -e KEY=value IMAGE printenv KEY |
| Named volume | podman run --rm -v myvol:/data IMAGE |
| Auto cleanup | podman run --rm IMAGE command |
| Restart on failure | podman run -d --restart=on-failure:3 IMAGE |
| Create only | podman create --name hold IMAGE then podman start hold |
Each row expands in the sections above.
References
Summary
podman run [options] IMAGE [command] is the everyday entry point for Podman workloads. Foreground runs suit one-off commands; -d returns a container ID while PID 1 keeps running in the background. Combine -i and -t for shells, use --name for stable references, -p for port maps, -e for configuration, and -v for persistent or bind-mounted storage.
--rm removes the container on exit and also drops anonymous volumes tied to that container, but named volumes you created separately remain. Restart policies apply when the process exits on its own — systemd and Quadlet services should use unit-level Restart= instead. When you need create-without-start, podman create plus podman start splits the steps podman run performs together.

