Run Commands Inside a Container with `podman exec`

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 podman exec on running containers — syntax, one-off commands, -it shells, --user, -w, --env, --env-file, -d, flag ordering, exit codes, and a short exec vs attach comparison. Does not cover podman run, lifecycle commands, SSH server setup, user-namespace mappings, or full attach reference.
Related guides List containers with podman ps
Install Podman on RHEL
What is Podman?

podman exec runs a command inside a container that is already running. Container creation belongs in Run containers with podman run; this page reuses one long-running container named exec-demo for every example.


Podman exec syntax

The general form is:

text
podman exec [options] CONTAINER COMMAND [arguments...]

Option order matters. Think of it as two layers:

text
podman exec [PODMAN EXEC OPTIONS] CONTAINER COMMAND [COMMAND OPTIONS]

Everything before CONTAINER is interpreted by Podman. Everything after is the program to run inside the container namespace.

Create the demo container:

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

Confirm it is running before any exec:

bash
podman ps --filter name=exec-demo

Sample output:

output
CONTAINER ID  IMAGE                                               COMMAND      CREATED        STATUS       NAMES
9e4c96730863  registry.access.redhat.com/ubi9/ubi-minimal:latest  sleep 3600   2 seconds ago  Up 1 second  exec-demo

Run a command inside a running container

Start with a read-only inspection command:

bash
podman exec exec-demo cat /etc/os-release

Sample output:

output
NAME="Red Hat Enterprise Linux"
VERSION="9.8 (Plow)"
ID="rhel"
PRETTY_NAME="Red Hat Enterprise Linux 9.8 (Plow)"

podman exec starts another process in the existing container namespace. It does not create a second container, and the main process (sleep 3600 here) keeps running. When the exec command exits, the container normally stays up unless you exec'd into PID 1 or otherwise changed container state.


Open an interactive shell with podman exec -it

Interactive shells need STDIN kept open and a pseudo-TTY:

  • -i — keep STDIN open for typed or piped input
  • -t — allocate a terminal

On exec-demo (UBI 9 minimal), Bash is available:

bash
podman exec -it exec-demo /bin/bash

Your prompt moves inside the container until you type exit or press Ctrl+D.

Many minimal images ship only sh. Create a short-lived Alpine container to show the Bash mistake:

bash
podman run -d --name exec-alpine docker.io/library/alpine:3.20 sleep 3600

Request Bash on an image that only ships sh:

bash
podman exec exec-alpine /bin/bash

Sample output on Alpine 3.20:

output
Error: crun: executable file `/bin/bash` not found: No such file or directory: OCI runtime attempted to invoke a command that was not found

Use the shell the image actually provides:

bash
podman exec -it exec-alpine /bin/sh

Inspect the image (podman inspect or the image Dockerfile) instead of installing SSH just to obtain a shell.


Put podman exec options before the container name

Flags must come before the container name. Correct form:

bash
podman exec -it exec-demo /bin/sh

Swapping the order fails:

bash
podman exec exec-demo -it /bin/sh

Sample output on Podman 5.8.2:

output
Error: crun: executable file `-it` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found

After Podman reads exec-demo, the next token is the command. -it is not a valid program name inside the container, so crun reports executable file not found. The same mistake with mistyped flags produces similar errors — always place Podman options first.


Run a command as another user

Without --user, exec runs as the container's configured user (root by default on many images):

bash
podman exec exec-demo id

Sample output:

output
uid=0(root) gid=0(root) groups=0(root)

Run as a specific account by name or numeric UID:

bash
podman exec --user 1000 exec-demo id

Sample output:

output
uid=1000 gid=0(root) groups=0(root)

The UID inside the container is not necessarily the same UID on the host when user namespaces are enabled. Mapping details live in Podman user namespaces — this page only shows the exec flag.


Set the working directory with -w

-w sets the working directory for the exec process only:

bash
podman exec -w /tmp exec-demo pwd

Sample output:

output
/tmp

It does not change the container's permanent configuration. A path that does not exist fails:

bash
podman exec -w /no/such/dir exec-demo pwd

Sample output:

output
Error: crun: chdir to `/no/such/dir`: No such file or directory

The command itself may exist; this failure occurs because crun cannot change into the requested working directory before starting it. Create the directory inside the container first, or pick a path that already exists.


Pass environment variables to podman exec

Add variables for a single exec session with --env:

bash
podman exec --env DEMO=value exec-demo printenv DEMO

Sample output:

output
value

For several variables, write a host file first:

bash
printf "DEMO_FILE=from-file\n" > /tmp/exec-env.txt

Pass that file into one exec session:

bash
podman exec --env-file /tmp/exec-env.txt exec-demo printenv DEMO_FILE

Those variables apply to the exec process only. They do not rewrite the container's stored environment the way podman run -e does at create time.


Run a command in the background

-d starts the exec process detached and prints an exec session ID:

bash
podman exec -d exec-demo sh -c "echo detached-exec > /tmp/exec-test.txt"

Sample output:

output
ed134f4557e3645177c768b3ee920b8b799c1ebff72ad64b3c32f87cf49afabc

Verify the command ran inside the container:

bash
podman exec exec-demo cat /tmp/exec-test.txt

Sample output:

output
detached-exec

Do not confuse podman run -d with podman exec -d. run -d creates and starts a new container in the background. exec -d adds another process inside a container that is already running.


What happens if the container is stopped?

podman exec requires a running container. Stop exec-demo first:

bash
podman stop exec-demo

Then exec fails because nothing is running:

bash
podman exec exec-demo /bin/sh -c "echo hi"

Sample output:

output
Error: can only create exec sessions on running containers: container state improper

Start the container, then the same exec succeeds:

bash
podman start exec-demo

Retry the command:

bash
podman exec exec-demo /bin/sh -c "echo after-start"

Sample output:

output
after-start

Lifecycle commands that change running state are covered in Start, stop, and restart containers.


Understand podman exec exit codes

Podman follows Docker-style exit conventions for exec:

Exit code Meaning
125 Podman itself failed, such as invalid options or another Podman-level error
126 Command was found but cannot be invoked
127 Command was not found
Other Exit status returned by the executed command

Command not found inside the container:

bash
podman exec exec-demo command-that-does-not-exist

Check the shell exit status:

bash
echo $?

Sample output:

output
127

Non-zero exit from the command itself is passed through:

bash
podman exec exec-demo sh -c "exit 3"

Podman returns the command's exit code:

bash
echo $?

Sample output:

output
3

Exit 126 appears when the target exists but cannot execute — for example a directory path:

bash
podman exec exec-demo /etc

That yields 126:

bash
echo $?

Sample output:

output
126

Podman-level failures use 125, such as a missing container name:

bash
podman exec no-such-container id

Missing containers surface as 125:

bash
echo $?

Sample output:

output
125

podman exec vs podman attach

podman exec podman attach
Starts a new process in the running container Connects to the existing main process
You supply the command (/bin/sh, cat, etc.) No new command — attaches to PID 1's I/O
Can set --user, -w, and --env per exec Uses the running process context
Common for shells and one-off admin tasks Common for foreground apps started with run

podman attach supports detach keys (default Ctrl+P, Ctrl+Q) so you can leave the main process running without stopping it. Use exec when you need a separate command; use attach when you need the original foreground session.


Do you need SSH inside a Podman container?

Most images do not run sshd. For administration on the host where Podman runs, podman exec is the direct path to a shell or diagnostic command — no SSH hop required.

When you need to move files in or out without opening a shell, copy files with podman cp works on stopped containers too — unlike exec.

SSH inside a container can still be valid for specially designed images or remote-access patterns. This article stays on podman exec as the default local mechanism.


References


Summary

podman exec runs additional processes inside a container that is already running. The main workload keeps going while you inspect files, open a shell, or run a one-off command. Place every Podman flag before the container name — putting -it after the name makes Podman try to execute a program literally named -it, which is a common copy-paste mistake with a clear error on Podman 5.8.2.

Use -it for interactive shells, but match the shell the image provides (/bin/sh on Alpine, /bin/bash on UBI). --user, -w, and --env apply only to the exec session. -d runs exec in the background and returns a session ID. Exec fails when the container is stopped; start it first. Exit codes 125, 126, and 127 distinguish Podman errors, non-executable targets, and missing commands — check echo $? in scripts that branch on failure.

For foreground workloads you started with podman run, podman attach reconnects to PID 1 instead of launching a new process. For everything else on a running container, exec is the tool you reach for — not SSH, unless the image was built for that on purpose.

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)