CertGrid CertGrid

Docker to Podman translation sheet

Not the commands that are identical - the ones that are not. What changes silently, what has no equivalent, and what needs a flag Docker never asked for. Every row with a Play example was executed on Ubuntu 26.04 with Podman 5.7.0.

Works unchanged

  • podman run / ps / stop / rm / exec / logs / cp / inspect

    Same flags, same behaviour. A script of these generally runs untouched.

    Full guide
  • podman build -t app:1 .

    Dockerfiles need no changes. `Containerfile` is preferred but `Dockerfile` is read as a fallback.

    Full guide
  • docker --version

    With podman-docker installed, `docker` is a three-line shim that execs podman. It reports podman's version rather than pretending.

    Full guide
  • podman --format 'table {{.Names}} {{.Status}}'

    Go templates work the same way. Field names come from `inspect` JSON.

    Full guide

Changes silently - fix these first

  • podman build -t app:1 . # -> localhost/app:1 Caution

    Locally built images gain a `localhost/` prefix. Anything grepping image names breaks, and a push needs a re-tag.

    Full guide
  • podman pull docker.io/library/alpine

    No implicit Docker Hub. Qualify every image reference - this is the single highest-value change when migrating.

    A bare name resolves via a 132-entry alias table, or fails. `hello-world` maps to quay.io/podman/hello.

    Full guide
  • podman pull traefik

    An unaliased bare name fails outright rather than assuming a registry.

    Full guide
  • podman inspect c --format '{{.NetworkSettings.IPAddress}}' Caution

    EMPTY for a rootless container on the default network - there is no bridge address to report.

    Full guide
  • podman exec a getent hosts b

    Fails on the default network. Container DNS needs a network you created.

    Full guide
  • podman network create appnet

    The fix for both of the above: a user-defined network has DNS and real bridge addresses.

    Full guide

Needs a flag Docker never needed

  • podman run --userns=keep-id -v ~/src:/src ...

    Without it, a non-root container user writes files owned by UID 100999 that you cannot delete.

    Full guide
  • podman unshare rm -rf ./dir Destructive

    Delete a directory tree a container left behind, from inside the namespace where you own it.

    Full guide
  • sudo sysctl net.ipv4.ip_unprivileged_port_start=80 Caution

    Required before a rootless container can publish a port below 1024.

    Host-wide, and does not survive a reboot. A reverse proxy is usually better.

    Full guide
  • podman run -p 80:80 ... # fails rootless

    pasta cannot bind a privileged port as your user.

    Full guide
  • podman run --init ...

    Makes stops fast. Without it a process that ignores SIGTERM as PID 1 takes the full 10-second timeout and a SIGKILL.

    Full guide
  • loginctl enable-linger $USER

    Without it a rootless service starts at first LOGIN, not at boot - so a rebooted host serves nothing until someone connects.

    The migration step most likely to cause a real outage if skipped.

    Full guide
  • [[registry]] insecure = true

    Podman assumes TLS for every registry and will not downgrade. A plain HTTP registry must be declared, per client.

    Full guide

No Docker equivalent

  • podman pod create --name app -p 8080:80

    A first-class pod. Containers in it share one network namespace and talk over localhost.

    Full guide
  • podman kube generate app

    Export a running pod as a real Kubernetes manifest.

    Full guide
  • podman kube play app.yaml

    Run a Kubernetes manifest on one host with no cluster.

    Full guide
  • podman image scp localhost/app:1 lab02::

    Copy an image host to host over ssh with no registry.

    Full guide
  • podman volume export data -o data.tar

    Back a volume up in one command. Docker has no equivalent and needs a helper container.

    Full guide
  • podman generate systemd # deprecated, use Quadlet

    A container as a systemd unit, described in a nine-line file that systemd regenerates on every reload.

    Full guide
  • podman auto-update

    Pull a newer image behind the same tag and restart the unit. No orchestrator involved.

    Full guide
  • podman unshare cat /proc/self/uid_map

    Run a command inside your own user namespace. There is no Docker analogue because Docker has no user namespace to enter.

    Full guide
  • docker swarm init Caution

    NO EQUIVALENT. Podman has no orchestrator. Use Kubernetes, or systemd units per host.

    Declared not-executed: there is nothing to run.

Architecture differences you can verify

  • pgrep -a podman # nothing, while containers run

    There is no daemon. One conmon per container, parented to PID 1.

    Full guide
  • systemctl is-active podman.service

    `inactive` is the correct, healthy state immediately after installing.

    Full guide
  • podman info --format '{{.Store.GraphRoot}}'

    Rootless images live under your home and count against its quota. `sudo podman` is a separate, empty store.

    Full guide
  • sudo podman images # empty on a host full of images

    Rootful and rootless are two machines that share a binary. `sudo` is not a fix.

    Full guide
  • podman run --rm alpine grep CapEff /proc/self/status

    Rootless and rootful get the SAME eleven capabilities. The difference is reach, not the bitmask.

    Full guide
  • journalctl --user CONTAINER_NAME=c

    Logs go to journald and OUTLIVE the container. `podman logs` fails once it is removed; the journal does not.

    Full guide

Rough edges to know about

  • podman run --read-only -p 8080:80 ... Caution

    BREAKS the published port on rootless 5.7.0. The container runs, serves its own loopback, and resets forwarded connections.

    Full guide
  • podman kube down app.yaml Caution

    Prints a rootless netns error and exits 0 anyway. Check `$?`, not the text.

    Full guide
  • docker compose down # under Podman Caution

    Same netns error, worse: exits 1 and leaves a container behind.

    Full guide
  • systemctl --user restart app-web.service # a pod member Caution

    Fails on BindsTo and takes the whole pod down. Restart the POD unit instead.

    Full guide
  • podman kube play dep.yaml # replicas > 1

    Warns and gives you ONE pod. The manifest applied and did not do what it says.

    Full guide
  • podman build ... # chown above your subuid range

    `Invalid argument`, not permission denied - the UID has no mapping. Ceiling is the count in /etc/subuid.

    Full guide
  • podman system connection add name ssh://...

    Succeeds WITHOUT testing anything. The ssh error waits for first use.

    Full guide
  • podman volume prune -f Destructive

    Removes every volume no RUNNING container references - including a stopped database's. No undo.

    Full guide