Cheat Sheets

Podman Cheat Sheet: Rootless, Pods and Quadlet Commands (PDF)

podman pull nginx works on Rocky Linux 10 and fails on Ubuntu 26.04 with a short-name error. That one difference shows why a generic Podman cheat sheet lets you down, because the two distros ship different Podman releases, different registry defaults and different security modules, so the same command can pull, fail, or return a 403 depending on where you type it.

Original content from computingforgeeks.com - post 177016

This Podman cheat sheet covers the commands you need for rootless containers, pods, Quadlet services, secrets, Docker compatibility, Compose, builds and cleanup, with the real output and the errors you are likely to hit. We tested everything here in October 2026 on Ubuntu 26.04 with Podman 5.7.0 and Rocky Linux 10.2 with Podman 5.8.2, both from the distro repositories, and every place the two behave differently is called out. The whole sheet is also a one-page PDF.

Find a Podman command fast

Each row below is explained further down with the output our two lab hosts printed. Podman takes the same flags as Docker for most everyday work, so if you already know docker run, most of this will look familiar:

TaskCommand
Run a web server as your userpodman run -d --name web -p 8080:80 docker.io/library/nginx:1.29
Replace a container with the same namepodman run -d --replace --name web -p 8080:80 docker.io/library/nginx:1.29
List running containerspodman ps
Show host UIDs behind container userspodman top web huser user
Create a pod with a published portpodman pod create --name app -p 8081:80
Export a pod to Kubernetes YAMLpodman kube generate app > app.yaml
Recreate it from the YAMLpodman kube play app.yaml
List Quadlet unitspodman quadlet list
Store a secret without echoing itread -rs DBPASS && printf '%s' "$DBPASS" | podman secret create dbpass -
Start the Docker-compatible API socketsystemctl --user enable --now podman.socket
Check disk usagepodman system df

Install Podman on Ubuntu 26.04 and Rocky Linux 10

Both distros package Podman themselves (Ubuntu in its universe component, Rocky in AppStream), so there is no third-party repo to add. On Ubuntu, install the plain package and let apt pull in its recommended packages, because rootless Podman needs two of them:

sudo apt install podman

Ubuntu lists the rootless pieces as recommends rather than hard dependencies, so this one command decides whether rootless Podman works. On our host it pulled in, among others:

  • uidmap, which provides newuidmap and newgidmap
  • passt, the pasta network helper
  • slirp4netns, the older network helper
  • buildah and criu

If your apt config skips recommends, or you install with --no-install-recommends to keep an image small, the first rootless run fails like this:

Error: command required for rootless mode with multiple IDs: exec: "newuidmap": executable file not found in $PATH

Fix it with sudo apt install uidmap passt, then run podman system migrate so Podman restarts its pause process, which worked on our host. On Rocky Linux the dependencies are hard requirements, so passt always comes along. Podman Compose is not in AppStream, which means you need EPEL for it:

sudo dnf install podman podman-docker
sudo dnf install epel-release
sudo dnf install podman-compose

For the Docker and Compose sections further down, add the compatibility packages too. On Ubuntu that is sudo apt install podman-docker podman-compose, both from universe. The podman-docker package on Ubuntu also recommends docker-compose, which pulled in Ubuntu’s docker-compose-v2 on our host and changes what podman compose runs, as the Compose section explains. Our longer guides cover installing Podman on Ubuntu 26.04 and Podman and Buildah on Rocky Linux and AlmaLinux step by step.

Check your Podman version and setup

Start with the version, because the two distros are a minor release apart and a few commands below only exist on the newer one. A local Podman prints only a Client section, since there is no remote server to report on, and the Build Origin line tells you whose package you are running:

podman version

Ubuntu 26.04 reported the 5.7 line built by Ubuntu, and Rocky printed 5.8.2 with a Rocky build origin. Features that arrived in 5.8, such as several Quadlet units in one .quadlets file, therefore exist only on Rocky, so check the version before you copy a newer example:

Client:        Podman Engine
Version:       5.7.0
API Version:   5.7.0
Go Version:    go1.25.0
Built:         Mon Feb 23 15:35:32 2026
Build Origin:  Ubuntu
OS/Arch:       linux/amd64

podman info prints a long YAML document. Pull out the fields that decide behaviour with a format string instead, so you can compare hosts at a glance:

podman info --format 'network={{.Host.NetworkBackend}} cgroups={{.Host.CgroupsVersion}} db={{.Host.DatabaseBackend}} runtime={{.Host.OCIRuntime.Name}} rootless={{.Host.Security.Rootless}} pasta={{.Host.Pasta.Executable}}'

Both hosts printed the same line, which is the modern stack: Netavark networking, cgroups v2, the SQLite database and crun. That matters because Podman 6 removes the older alternatives (CNI, cgroups v1, BoltDB), so a host that prints anything else here needs a migration before its next major upgrade, while these two need none:

network=netavark cgroups=v2 db=sqlite runtime=crun rootless=true pasta=/usr/bin/pasta

Rootless and rootful Podman keep separate image stores, so an image you pulled with sudo is invisible to your user and the other way round. Check where each one lives:

podman info --format 'graphroot={{.Store.GraphRoot}} runroot={{.Store.RunRoot}} driver={{.Store.GraphDriverName}}'
sudo podman info --format 'graphroot={{.Store.GraphRoot}} rootless={{.Host.Security.Rootless}}'

Your user’s images and volumes sit in your home directory, and root’s under /var/lib/containers. So a full /home can be Podman’s doing, and a backup that only covers /var/lib/containers misses every rootless container on the box:

graphroot=/home/josphat/.local/share/containers/storage runroot=/run/user/1000/containers driver=overlay
graphroot=/var/lib/containers/storage rootless=false

Rootless containers also need a block of subordinate UIDs, which the installer or useradd adds to /etc/subuid and /etc/subgid. Ubuntu gave our user the range starting at 100000 and Rocky the one starting at 524288. podman unshare cat /proc/self/uid_map shows how Podman maps them, with container root as your own UID and everything else from the range:

         0       1000          1
         1     100000      65536

If the second line is missing, Podman has only your own UID to work with, and images that ship files owned by other users fail to unpack. The errors section shows what that looks like and how to add a range.

Pull images without short-name surprises

Podman refuses to guess which registry nginx means unless your config tells it, and the two distros configure that very differently. Ubuntu’s /etc/containers/registries.conf has no active settings at all, so only the 132 names in its alias file resolve. Rocky sets three search registries and turns on enforcing mode, with 139 aliases. Run the same pull on both:

podman pull nginx

Ubuntu has no alias for nginx and no registry to search, so it stops straight away. Nothing is wrong with the network or Docker Hub here, which is what most people check first, because the error comes from Podman’s own config before any request leaves the host:

Error: short-name "nginx" did not resolve to an alias and no unqualified-search registries are defined in "/etc/containers/registries.conf"

Rocky resolved nginx through its alias file and pulled docker.io/library/nginx:latest. So the same short name can end three different ways, depending on the distro and on whether a terminal is attached:

  • Ubuntu, any name outside the alias file: fails at once
  • Rocky, a name in the alias file: pulls from the aliased registry
  • Rocky, any other name: asks in a terminal, fails in a script

In a script or CI job Podman can’t ask, so podman pull redis failed on Rocky with the message below. Typed at a terminal, the same command showed a menu with registry.access.redhat.com/redis:latest highlighted first and Docker Hub last, so pressing Enter without reading picks Red Hat’s registry, which has no redis image, and you don’t get the image most tutorials mean. A pipeline can also fail on a command that worked when you tested it by hand:

Error: short-name resolution enforced but cannot prompt without a TTY

The fix is the same everywhere: write the full name, registry and tag included. It is also safer, because a short name that resolves to the wrong registry is a classic supply-chain trap:

podman pull docker.io/library/nginx:1.29

Every example on this page uses full names for that reason, and so should anything you put in a script, a Compose file or a Quadlet unit.

Run rootless containers

Rootless is the default when you run Podman as a normal user, and the flags match Docker’s, so most of your Docker habits carry over. The difference is that the container runs inside your user namespace with no daemon in between, which means it lives and dies with your user session unless you enable lingering. Start nginx and check it answers:

podman run -d --name web -p 8080:80 docker.io/library/nginx:1.29
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080

The container answered with 200. podman inspect -f '{{.HostConfig.NetworkMode}}' web printed pasta, which is the rootless network helper Podman uses by default since the 5.0 release, replacing slirp4netns. Inside a pasta container, host.containers.internal resolved to 169.254.1.2, so that is the name to use when a container needs a service on the host.

These are the container commands we use most. None of them needs sudo, because each one talks to your own container store and not to a system daemon:

JobCommand
Readable listpodman ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
Last log linespodman logs --tail 2 web
Command insidepodman exec web nginx -v
Shell insidepodman exec -it web sh
CPU and memory oncepodman stats --no-stream web
Container and host userspodman top web huser user
Stop and removepodman rm -f web
Start restart-policy containers at boot (needs linger)systemctl --user enable podman-restart.service

podman top web huser user is the quickest way to see rootless mapping at work. nginx’s root process runs as your own UID 1000 on the host, and its workers, which are user nginx inside the container, run as UID 100100 on Ubuntu and 524388 on Rocky, so a process that escapes the container lands as an unprivileged user:

HUSER       USER
1000        root
100100      nginx
100100      nginx

Two defaults differ from Docker in ways that matter for workloads you move across. Podman gave our containers an open files limit of 524288, where Docker Engine 29 now gives 1024, so a database or proxy that ran fine under Podman can run out of file descriptors after a move to Docker unless you pass --ulimit. The memory limit behaves the same on both engines: --memory 16m plus tail /dev/zero ended in exit code 137 on both hosts, with no message, so treat 137 as a memory limit until proven otherwise.

Publish ports below 1024

Unprivileged users can’t bind ports under 1024, and Podman reports it two different ways depending on the network. On the default pasta network, -p 80:80 failed like this on Rocky (Ubuntu’s older passt build words it as Listen failed for HOST TCP port */80: Permission denied):

Error: pasta failed with exit code 1:
Failed to bind port 80 (Permission denied) for option '-t 80-80:80-80'

On a user-defined bridge network, created with podman network create appnet, the port is handled by rootlessport instead, and its message spells out the fix:

Error: rootlessport cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or choose a larger port number (>= 1024): listen tcp 0.0.0.0:80: bind: permission denied

Lowering the limit fixed both cases on both hosts: nginx then answered on port 80 on the default pasta network and on appnet. It lets every local user bind those ports, so on a shared server prefer a reverse proxy on 80 and 443 that forwards to a high port. Change it for the running system first:

sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80

To keep it after a reboot, put the setting in its own file under /etc/sysctl.d/:

sudo vim /etc/sysctl.d/90-unprivileged-ports.conf

The file needs one line:

net.ipv4.ip_unprivileged_port_start=80

A busy port gives a pasta error too: our second container on 8080 failed with Address already in use in the same format as above, so read the text after pasta failed rather than the first line. On Ubuntu 26.04, removing containers on appnet may also fail with rootless netns: kill network process: permission denied; the errors section has the AppArmor fix.

Group containers in pods and Kubernetes YAML

A pod is a group of containers that share one network namespace, so they talk to each other over localhost, exactly like containers in a Kubernetes pod. The port is published on the pod, not on the containers:

podman pod create --name app -p 8081:80
podman run -d --pod app --name app-web docker.io/library/nginx:1.29
podman run -d --pod app --name app-cache docker.io/library/redis:8
podman pod ps

The pod shows three containers, because Podman adds a small infra container that holds the shared namespaces. The members share that namespace, ports included, which is why you publish ports on the pod and never on a member container:

POD ID        NAME        STATUS      CREATED                 INFRA ID      # OF CONTAINERS
c11dcb792748  app         Running     Less than a second ago  da1cfc843376  3

A Redis client started with --pod app reached the cache on 127.0.0.1 and got PONG, with no network to create. To move the pod elsewhere, or to keep it in Git, export it as Kubernetes YAML and play it back:

podman kube generate app > app.yaml
podman pod stop app && podman pod rm app
podman kube play app.yaml
podman kube down app.yaml

The generated file was 30 lines and started with a comment naming the Podman version that made it. podman kube play --replace app.yaml recreates a running pod in one step. The older podman play kube spelling still works as an alias, but use podman kube in anything new. On Ubuntu 26.04, kube down reported rootless netns: kill network process: permission denied until we applied the AppArmor fix in the errors section.

Run containers as services with Quadlet

Quadlet is how Podman runs containers under systemd now. You write a small .container file, and a systemd generator turns it into a full service unit at every daemon-reload. podman generate systemd still exists but its help text starts with [DEPRECATED], and running it prints It is recommended to use Quadlets for running containers and pods under systemd. Create a rootless unit in your user’s Quadlet directory:

mkdir -p ~/.config/containers/systemd && vim ~/.config/containers/systemd/qweb.container

That directory is one of several places the generator reads, and the first one a rootless user should use. Quadlet looks for rootless units in these paths:

  • ~/.config/containers/systemd/ for your own units
  • /etc/containers/systemd/users/$(UID) for one user, set by root
  • /etc/containers/systemd/users/ for every user
  • $XDG_RUNTIME_DIR/containers/systemd/ for temporary units, gone at reboot

Put this unit in ~/.config/containers/systemd/. It is the exact file we ran on both hosts, and the image is fully qualified on purpose, because AutoUpdate=registry needs a full name to know where to look for updates and Quadlet prints a warning for short names:

[Unit]
Description=nginx web via Quadlet

[Container]
Image=docker.io/library/nginx:1.29
ContainerName=qweb
PublishPort=8082:80
AutoUpdate=registry

[Service]
Restart=always

[Install]
WantedBy=default.target

Before you start it, check what the generator makes of the file. The dry run prints the service unit or the error that would stop it, which is much faster than debugging a unit that silently never appears:

/usr/libexec/podman/quadlet -dryrun -user

The interesting part is the ExecStart line Quadlet builds, which shows the label that enables auto-updates and the --replace flag that makes restarts safe:

ExecStart=/usr/bin/podman run --name qweb --replace --rm --cgroups=split --sdnotify=conmon -d --label io.containers.autoupdate=registry --publish 8082:80 docker.io/library/nginx:1.29

Reload systemd so the generator runs, then start the service. Quadlet only reads the file during a reload, so an edit does nothing until you run daemon-reload again, which is the most common reason a change seems to be ignored:

systemctl --user daemon-reload
systemctl --user start qweb
podman quadlet list

The unit ran on both hosts and nginx answered on port 8082. podman quadlet list shows the file, the generated unit and its state, so it is the first thing to run when a service you expect is missing:

NAME            UNIT NAME     PATH ON DISK                                             STATUS          APPLICATION
qweb.container  qweb.service  /home/josphat/.config/containers/systemd/qweb.container  active/running  

Don’t run systemctl --user enable qweb. It fails with Failed to enable unit: Unit /run/user/1000/systemd/generator/qweb.service is transient or generated, because the [Install] section in the file already does that job at boot. What a rootless service does need is lingering, otherwise systemd stops your user manager, and your containers with it, when you log out:

sudo loginctl enable-linger $USER

loginctl show-user $USER -p Linger went from Linger=no to Linger=yes. The rest of the Quadlet workflow is a handful of short commands:

JobCommand
Copy a unit file into placepodman quadlet install ~/qtest/sleeper.container
Show the file behind a unitpodman quadlet print qweb.container
Remove a unit filepodman quadlet rm sleeper.container
See which containers would updatepodman auto-update --dry-run
Update them on a schedulesystemctl --user enable --now podman-auto-update.timer
Run a unit as root insteadPut the file in /etc/containers/systemd/ and use sudo systemctl

The auto-update dry run listed qweb.service with policy registry and UPDATED false. The timer was disabled on both hosts until we ran systemctl --user enable --now podman-auto-update.timer, so auto-updates never happen by themselves. Our Podman Quadlet guide goes further, with pods, volumes and networks as units.

Use secrets and health checks

Podman secrets keep passwords out of your image and out of podman inspect, which matters because a value passed with -e shows up there in plain text for anyone who can inspect the container. Read the value without echoing it and pipe it in, so it never appears on the command line or in your shell history. After you press Enter, type the password and press Enter again; nothing is shown while you type:

read -rs DBPASS && printf '%s' "$DBPASS" | podman secret create dbpass -

A secret can be mounted as a file under /run/secrets/, which is the default, or exposed as an environment variable. Both worked on both hosts:

podman run --rm --secret dbpass docker.io/library/alpine:3.22 cat /run/secrets/dbpass
podman run --rm --secret dbpass,type=env,target=DB_PASS docker.io/library/alpine:3.22 sh -c 'echo len=${#DB_PASS}'

The file variant printed the value and the env variant len=11. The default file driver stores secrets unencrypted in your Podman storage, and podman secret inspect --showsecret --format '{{.SecretData}}' dbpass printed the value straight back, so treat secrets as protection against leaks in images and logs, not against someone who already has your account.

Health checks run inside the container on a timer, and podman ps shows the result. You can add one at run time and change it later without recreating the container, which Docker can’t do:

podman run -d --name hc --health-cmd 'curl -fs http://localhost/ || exit 1' --health-interval 5s docker.io/library/nginx:1.29
podman healthcheck run hc
podman update --health-cmd 'curl -fsS http://localhost/ >/dev/null || exit 1' --health-interval 30s hc

After the update, podman healthcheck run hc returned 0, podman ps still showed Up 11 seconds (healthy), and podman inspect -f '{{.Config.Healthcheck.Test}}' hc showed the new command. Use a tool the image actually has: the nginx image ships curl but not wget, so a wget check would turn the container unhealthy a few intervals later.

Use Docker tools and Compose with Podman

The podman-docker package installs a docker command that runs Podman. It prints a notice on every call, which breaks scripts that parse the output, so silence it once:

Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.

Creating the file with sudo touch /etc/containers/nodocker removed the line on both hosts. Tools that talk to the Docker API rather than the CLI need Podman’s API socket. The rootless one runs under your user:

systemctl --user enable --now podman.socket
curl -s --unix-socket $XDG_RUNTIME_DIR/podman/podman.sock http://d/_ping

The ping answered OK, so the API is up. The socket only exists while your user session or lingering keeps the user manager running, which matters for CI agents that connect over SSH. Tools that speak the Docker API, such as the real Docker CLI or Testcontainers, connect to it when you set export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock. The docker command from podman-docker doesn’t need it, because it is Podman itself.

podman compose is only a wrapper that hands your file to an external Compose program, and which one it picks depends on what is installed. Podman’s source checks them in this order and runs the first one it finds:

  1. Docker’s Compose plugin in the cli-plugins directories
  2. a docker-compose binary on your PATH
  3. podman-compose

That is why Ubuntu ran Docker’s Compose: docker-compose-v2 came in with podman-docker and put its plugin in /usr/libexec/docker/cli-plugins/. Check which one you get:

podman compose version

Ubuntu printed the Docker Compose banner below, while Rocky ran /usr/bin/podman-compose and printed podman-compose version 1.5.0. The banner goes to every command, so silence it once you know which provider you have, either with PODMAN_COMPOSE_WARNING_LOGS=false or with compose_warning_logs=false under the [engine] table of ~/.config/containers/containers.conf:

>>>> Executing external compose provider "/usr/libexec/docker/cli-plugins/docker-compose". Please see podman-compose(1) for how to disable this message. <<<<

Docker Compose version 2.40.3+ds1-0ubuntu1

Both providers started our two-service file and published its port, but they name containers differently: stack-web-1 with Docker Compose and stack_web_1 with podman-compose. Scripts that call podman exec stack-web-1 break when the provider changes, so pin it with export PODMAN_COMPOSE_PROVIDER=podman-compose (or compose_providers under [engine] in containers.conf) on every host that runs the same files.

Build images and store artifacts

podman build reads a Containerfile or a Dockerfile and uses Buildah underneath, so you don’t need a daemon or root to build images. This is the file we built on both hosts:

FROM docker.io/library/alpine:3.22
RUN apk add --no-cache curl
CMD ["curl", "--version"]

Build it with a localhost/ prefix. Podman stores an unqualified build name under localhost/ anyway, so writing it out makes the name you type match what podman images prints and keeps it clearly apart from registry images:

podman build -t localhost/hello:1.0 .

The build ended with Successfully tagged localhost/hello:1.0, and the image was 13.8 MB. Unlike Docker 29, podman images still prints the classic REPOSITORY, TAG and SIZE columns. podman save -o /tmp/hello.tar localhost/hello:1.0 exported it as a 14M tar file, and podman push sends it to a registry after podman login.

OCI artifacts let you push files that are not container images, such as config bundles or model weights, to the same registry. We stored a config file and extracted it again:

podman artifact add localhost/cfg:1 ~/cfg.txt
podman artifact ls
podman artifact extract localhost/cfg:1 ~/out

podman artifact ls listed localhost/cfg with a size of 10B, and the extracted file matched the original on both hosts. Artifacts became a stable feature in the 5.6 release, so both distros have them, but older Podman builds on other distros may not.

Use volumes and SELinux labels

A rootless named volume lives in your home directory, next to your images, so backups of /var/lib/containers don’t include it. After podman volume create appdata, podman volume inspect -f '{{.Mountpoint}}' appdata returned /home/josphat/.local/share/containers/storage/volumes/appdata/_data. Bind mounts are where the two distros part ways. Create a test page and mount it without a label option:

mkdir -p ~/site && echo '<h1>podman bind</h1>' > ~/site/index.html
podman run -d --name bm -p 8084:80 -v ~/site:/usr/share/nginx/html:ro docker.io/library/nginx:1.29

On Ubuntu, which uses AppArmor, nginx served the page with a 200. On Rocky it returned 403, because Podman runs containers with SELinux labels and ~/site carries your home directory’s label. This is the opposite of Docker CE, which leaves SELinux labelling off unless you enable it. Add :Z and Podman relabels the directory for that one container:

podman run -d --replace --name bm -p 8084:80 -v ~/site:/usr/share/nginx/html:ro,Z docker.io/library/nginx:1.29

Rocky then served the page, and ls -Z ~/site/index.html showed system_u:object_r:container_file_t:s0:c395,c486. Use :z (lowercase) for a directory that several containers share. On Ubuntu the option is accepted and does nothing, so you can keep it in files that run on both. Never relabel a system directory or your whole home this way; our Podman SELinux guide explains the labels in detail.

Clean up Podman storage

podman system df shows what is using space and how much of it you can reclaim. Run it as your user and again with sudo, because the rootless and rootful stores are counted separately and a full disk is often the one you forgot to check:

TYPE           TOTAL       ACTIVE      SIZE        RECLAIMABLE
Images         5           2           326.9MB     162.3MB (50%)
Containers     2           2           24.15kB     0B (0%)
Local Volumes  1           1           0B          0B (0%)

Be careful with volumes on Podman 5. podman volume prune -f removed our named volume appdata as soon as no container used it, which is the old Docker behaviour. Podman 6 changes this to anonymous volumes only, with --all for the rest, so the same command will mean different things on different hosts for a while. Check podman volume ls before every prune. The other cleanup commands:

JobCommand
Remove stopped containerspodman container prune -f
Remove all unused imagespodman image prune -a -f
Remove unused volumes (5.x: named too)podman volume prune -f
Everything unused, including volumespodman system prune -a --volumes
Wipe all of your user’s Podman datapodman system reset
Re-read subuid ranges after a changepodman system migrate

podman system reset deletes every image, container, volume and network of the user who runs it, after a single confirmation (-f skips even that). Run it with sudo and it wipes root’s store instead, which is a different set of data.

Fix common Podman errors

These are the errors we triggered on the two lab hosts, with the text Podman printed. When Podman runs from a script, as ours did, it prints warnings as time=... level=warning msg=... lines, so search for the text inside msg= rather than the prefix.

Error: “rootless netns: kill network process: permission denied”

This one is specific to Ubuntu 26.04. Removing a container on a user-defined network, podman kube down and podman compose down all failed with it, while the same commands worked on Rocky. The kernel log shows why: Ubuntu’s AppArmor profile for pasta blocks the stop signal that Podman sends it:

apparmor="DENIED" operation="signal" class="signal" profile="pasta" pid=33598 comm="podman" requested_mask="receive" denied_mask="receive" signal=term peer="podman"

The profile has no local/ include, so a drop-in file is ignored. Add the rule to the profile itself and reload it, after keeping a copy of the original with sudo cp -p /etc/apparmor.d/usr.bin.pasta /root/usr.bin.pasta.orig:

sudo vim /etc/apparmor.d/usr.bin.pasta

Add this line directly under include <abstractions/pasta>, inside the profile’s braces:

  signal (receive) peer=podman,

Reload the profile with sudo apparmor_parser -r /etc/apparmor.d/usr.bin.pasta. After that, podman rm -f, podman network rm and podman compose down all completed on our Ubuntu host. The kernel log showed no further pasta denials. The profile is a package conffile, so a future passt update may ask whether to keep your version; keep it until the package ships the rule.

Error: “cannot find UID/GID for user tester: no subuid ranges found”

The user has no entry in /etc/subuid, which happens with accounts created by tools that skip useradd‘s defaults. Podman falls back with Using rootless single mapping into the namespace. This might break some images. Add a range and refresh Podman’s view of it:

sudo usermod --add-subuids 200000-265535 --add-subgids 200000-265535 tester
sudo -iu tester podman system migrate

After the migrate, the same pull and run worked for the test user on both hosts, without the single-mapping warning.

Warning: “The cgroupv2 manager is set to systemd but there is no systemd user session available”

You switched users with sudo -iu or su, so the account has no systemd user session. Podman also suggests loginctl enable-linger and falls back to --cgroup-manager=cgroupfs. Plain sudo -u is worse, because it keeps your working directory and failed with cannot chdir to /home/josphat: Permission denied. Enable lingering for the account and pass its runtime directory, which ran with zero warnings on both hosts:

sudo loginctl enable-linger tester
sudo -iu tester env XDG_RUNTIME_DIR=/run/user/$(id -u tester) podman run --rm docker.io/library/alpine:3.22 echo hi

Logging in as the user over SSH gives the same clean result, because it creates a real systemd user session, so use that for anything you run regularly.

Error: the container name “web” is already in use

A container with that name exists, running or stopped. Podman’s message ends with the quickest fix: or use --replace to instruct Podman to do so. podman run -d --replace --name web ... removed the old container and started the new one in one step on both hosts.

Error: “cannot remove container … as it is running”

podman rm web refuses a running container with running or paused containers cannot be removed without force: container state improper. Use podman rm -f web, or stop it first. An alpine container running sleep infinity took the full 10 seconds and logged StopSignal SIGTERM failed to stop container hold in 10 seconds, resorting to SIGKILL, because sleep as PID 1 ignores SIGTERM. Pass -t 0 to podman stop for throwaway containers.

Error: “volume appdata is being used by the following container(s)”

A container still mounts the volume, even if it is stopped, and Podman refuses to pull storage out from under it. Remove the container first, or find it with podman ps -a --filter volume=appdata, because a stopped container from an old test is the usual culprit.

Get ready for Podman 6

Podman 6 is out upstream and already in Fedora 45, while Ubuntu 26.04 and Rocky Linux 10.2 still ship the 5.x line. It drops CNI networking, iptables, slirp4netns, cgroups v1 and the BoltDB database, so a host that still relies on any of them breaks on upgrade. The podman info check from earlier tells you whether yours does:

  • network=netavark, not cni
  • cgroups=v2
  • db=sqlite, not boltdb
  • pasta installed, since slirp4netns is gone

Both of our hosts passed all four, so the real change for them is behavioural: podman volume prune stops deleting named volumes unless you add --all, and podman commit pauses the container by default. Our Podman 6 breaking changes guide lists every removal and how to upgrade, and the Docker cheat sheet covers the Docker side of the commands above.

For a book that covers rootless containers, Quadlet, SELinux and signed images in depth, Podman for DevOps (paid link) (second edition, Packt, February 2026) by Alessandro Arrichiello and Gianni Salinetti is the most current one we know of, and it was written for the Podman 5 era these commands come from.

Keep reading

Claude Code Cheat Sheet: Commands, Shortcuts and Flags (PDF) AI Claude Code Cheat Sheet: Commands, Shortcuts and Flags (PDF) OpenAI Codex CLI Cheat Sheet: Shortcuts, Commands, Flags (PDF) AI OpenAI Codex CLI Cheat Sheet: Shortcuts, Commands, Flags (PDF) Best UI Applications for Managing Docker Containers Containers Best UI Applications for Managing Docker Containers Install OpenCloud with Docker Compose, Traefik and Collabora Containers Install OpenCloud with Docker Compose, Traefik and Collabora Kubectl Cheat Sheet for Kubernetes Admins and CKA Exam Prep Kubernetes Kubectl Cheat Sheet for Kubernetes Admins and CKA Exam Prep Linux Commands Cheat Sheet for Ubuntu and Rocky Linux (PDF) Cheat Sheets Linux Commands Cheat Sheet for Ubuntu and Rocky Linux (PDF)

Leave a Comment

Press ESC to close