How to Run Containers with podman run

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:

text
podman run [options] IMAGE [command [arguments...]]

Three positions matter:

  • Options (-d, -p, -e, and the rest) come before the image name.
  • IMAGE is 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:

bash
podman run --rm quay.io/podman/hello

Sample output:

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.

bash
podman run --rm registry.access.redhat.com/ubi9/ubi-minimal echo "Hello from Podman"

Sample output:

output
Hello from Podman

Detached mode (-d) starts the container and returns immediately with the container ID:

bash
podman run -d --name podman-run-demo registry.access.redhat.com/ubi9/ubi-minimal sleep 300

Sample output (container ID):

output
664605894eaebb6d0ee5229b68cdef74b9da7c8daddea5e8573020897d4d1457

Confirm the container is still running:

bash
podman ps --filter name=podman-run-demo

Sample output:

output
664605894eae podman-run-demo Up 5 seconds

Detached 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:

bash
podman run --rm -it registry.access.redhat.com/ubi9/ubi-minimal /bin/bash

Inside 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:

bash
echo "piped input" | podman run --rm -i registry.access.redhat.com/ubi9/ubi-minimal cat

Sample output:

output
piped input

Use -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.

bash
podman run -d --name web-demo registry.access.redhat.com/ubi9/ubi-minimal sleep 300

List by name:

bash
podman ps --filter name=web-demo --format '{{.Names}} {{.Status}}'

Sample output:

output
web-demo Up 2 seconds

Later commands accept the name, full ID, or a unique prefix of the ID.

Reusing a name that is already taken fails:

bash
podman run -d --name web-demo registry.access.redhat.com/ubi9/ubi-minimal sleep 300

Sample output:

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:

text
HOST_PORT:CONTAINER_PORT

Nginx listens on port 80 inside the image, so map host 8080 to container 80:

bash
podman run -d --name web-demo -p 8080:80 docker.io/library/nginx:alpine

Bind only the loopback interface when the service should not face the LAN:

text
127.0.0.1:8080:80

Ask Podman which bindings exist:

bash
podman port web-demo

Sample output:

output
80/tcp -> 0.0.0.0:8080

A quick HTTP check from the host confirms the mapping:

bash
curl -sI http://127.0.0.1:8080/ | head -2

Sample output:

output
HTTP/1.1 200 OK
Server: nginx/1.31.4

Rootless 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:

bash
podman run --rm -e APP_ENV=production registry.access.redhat.com/ubi9/ubi-minimal printenv APP_ENV

Sample output:

output
production

Add multiple -e flags for several variables. Pass a host variable when the name already exists on the host:

bash
podman run --rm -e HOME registry.access.redhat.com/ubi9/ubi-minimal printenv HOME

For many keys, use a file:

bash
podman run --rm --env-file /path/to/app.env registry.access.redhat.com/ubi9/ubi-minimal printenv

Environment 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:

text
SOURCE:CONTAINER_PATH

Create a named volume first:

bash
podman volume create podman-run-data

Mount it and write a file:

bash
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:

bash
podman run --rm -v podman-run-data:/data registry.access.redhat.com/ubi9/ubi-minimal cat /data/example.txt

Sample output:

output
hello

Named 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:

bash
podman run --rm registry.access.redhat.com/ubi9/ubi-minimal echo "temporary container"

Sample output:

output
temporary container

Nothing remains in podman ps -a for that run.

Anonymous volumes behave differently from named volumes. An anonymous mount uses only a container path:

bash
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:

bash
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:

bash
podman inspect --format 'Status={{.State.Status}} Restarts={{.RestartCount}} ExitCode={{.State.ExitCode}}' fail-demo

Sample output:

output
Status=stopped Restarts=3 ExitCode=1

Podman 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:

bash
podman run -d --name signal-demo --stop-signal=SIGINT registry.access.redhat.com/ubi9/ubi-minimal sleep 300

Confirm the stored signal:

bash
podman inspect --format 'StopSignal={{.Config.StopSignal}}' signal-demo

Sample output:

output
StopSignal=SIGINT

sleep 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:

bash
podman create --name created-demo registry.access.redhat.com/ubi9/ubi-minimal sleep 300

The command prints a container ID. Check state:

bash
podman ps -a --filter name=created-demo --format '{{.Names}} {{.Status}}'

Sample output:

output
created-demo Created

Start it when you are ready:

bash
podman start created-demo

Sample output:

output
created-demo

Verify running status:

bash
podman ps --filter name=created-demo --format '{{.Names}} {{.Status}}'

Sample output:

output
created-demo Up 1 second

Use 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.


Frequently Asked Questions

1. What is the difference between podman run and podman create?

podman create creates the container filesystem and records its configuration but does not start the main process. podman run is create plus start in one step. Use create when you need a container prepared but intentionally not started yet—for inspection, later startup, or automation—and run for the common immediate workflow.

2. What does podman run -d do?

The -d flag runs the container in detached mode. Podman starts the container, prints the container ID, and returns your shell while the main process keeps running in the background. Detached does not keep the container alive if PID 1 exits immediately.

3. Does podman run --rm delete volumes?

--rm removes the container when its main process exits. Anonymous volumes created for that container are removed with it. Named volumes you created with podman volume create are not removed by --rm because they are independent storage objects.

4. What is the difference between podman run -i and -it?

-i keeps STDIN open so the container can read piped or typed input. -t allocates a pseudo-TTY for terminal-aware programs such as shells. Interactive shells usually need both as -it. Non-interactive commands that only read a pipe often need -i alone.

5. When should I use podman run --restart?

Use --restart when Podman itself should restart a container after its main process exits, subject to the policy you choose. For services managed by systemd or Quadlet, prefer the unit Restart= directive instead of layering Podman restart policy on top.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)