CertGrid CertGrid
Hands-on Lab·Podman

Essential Podman CLI Commands

The dozen commands that cover most days, and the `--format` template that turns any of them into a single line you can script against. Includes the environment variable that tells a process it is in a container.

Containers and Images Guide 6 of 47 Beginner

Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.

Every command on this page ran on podman01.
Server NameIP AddressOSRolesCPURAMHDD
PODMAN01192.168.0.21Ubuntu 26.04 LTSPrimary Container Host2 Core4 GB50 GB

Before you start

  1. Run a command inside something already running

    podman exec runs a new process in an existing container's namespaces. Two shapes:

    • podman exec site nginx -v - one command, output, done
    • podman exec -it site sh - an interactive shell, for looking around

    Reading a config file out of a running container is the everyday use, and it answers a question that guessing cannot: not what the image is documented to contain, but what this container actually has.

    Worth knowing that exec starts a process outside the entrypoint's supervision. It is not part of the container's lifecycle, so it does not restart with it and killing it does not stop the container.

    bash Example session
    podman exec site nginx -vnginx version: nginx/1.31.4podman exec site cat /etc/nginx/conf.d/default.confserver {    listen       80;    listen  [::]:80;    server_name  localhost;     #access_log  /var/log/nginx/host.access.log  main;     location / {        root   /usr/share/nginx/html;        index  index.html index.htm;    } 

    Expected resultAn nginx version, then the default server block.

    Success conditionYou have read a file out of a running container without stopping it.

  2. Templates: --format is the whole scripting story

    Almost every Podman command takes --format with a Go template, and it is the difference between parsing output and asking for a value.

    Two forms worth memorising:

    • --format 'table {{.Names}} {{.Status}}' - pick columns, keep the header
    • --format 'x={{.Field}}' - one line, no header, ready for a shell variable

    Ranging over a list works too. {{range .Config.Env}}{{println .}}{{end}} prints the container's environment, and the first line is the interesting one:

    container=podman

    Podman sets that itself. A process inside can read $container to discover both that it is containerised and by what - which is how some software decides whether to expect systemd, or a real init, or a TTY.

    The field names come from the JSON that podman inspect returns with no --format at all, so that is where to look when a template does not resolve.

    bash Example session
    podman inspect site --format 'image={{.ImageName}} started={{.State.StartedAt}} restarts={{.RestartCount}}'image=docker.io/library/nginx:alpine started=2026-08-22 11:35:41.711978243 +0000 UTC restarts=0podman inspect site --format '{{range .Config.Env}}{{println .}}{{end}}'container=podmanNJS_VERSION=1.0.0PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binNJS_RELEASE=1ACME_VERSION=0.4.1NGINX_VERSION=1.31.4PKG_RELEASE=1DYNPKG_RELEASE=1HOME=/rootHOSTNAME=725ae48d0232

    Expected resultOne summary line, then the container's environment with container=podman first.

    Success conditionYou can extract a single field without piping anything through grep.

  3. Move a file out, and read the event log

    podman cp site:/etc/nginx/nginx.conf ./nginx.conf copies out. It works in both directions and on stopped containers too, which makes it the usual way to retrieve something from a container that has already failed.

    podman events is the command most people discover last and then use constantly. It is one timeline of everything the engine did - creates, pulls, starts, deaths - and --since 3m --stream=false gives a bounded chunk rather than a live tail.

    Look at what it remembers: create objective_elgamal, the generated name of the throwaway container from the previous guide. The container is long gone and the event log still has it, which is exactly why this is the first place to look when something ran and vanished before you could inspect it.

    bash Example session
    podman cp site:/etc/nginx/nginx.conf ./nginx.confwc -l nginx.conf32 nginx.confpodman events --since 3m --stream=false --format '{{.Status}} {{.Name}}'refreshcreate objective_elgamalpull docker.io/library/alpineinit objective_elgamalstart objective_elgamalattach objective_elgamaldied objective_elgamalremove objective_elgamal

    Expected resultA 32-line file on the host, and an event list including the removed container's generated name.

    Success conditionYou have a file from inside a container and a timeline of what the engine did.

Troubleshooting

Official sources