Cyber Deals - Get up to 65% off on CKA, CKAD, CKS, KCNA, KCSA exams and courses!

Docker and Podman Cheat Sheet

Podman and Docker share most CLI syntax. Key differences:

  • Podman is daemonless and rootless by default — no background service required.
  • Podman has native pod support (podman pod) and can run Kubernetes YAML (podman kube play).
  • Podman includes podman machine for Linux VMs on macOS/Windows.
  • Docker has Docker Swarm for native clustering; Podman delegates clustering to Kubernetes.

Commands show Podman first (the preferred default on RHEL/Fedora), then the Docker equivalent. All commands validated against docs.podman.io and docs.docker.com.

Also see: kubectl & oc Cheatsheet



Installation

Podman:

# RHEL / Fedora
sudo dnf install -y podman

# Ubuntu / Debian
sudo apt-get install -y podman

# macOS
brew install podman
podman machine init && podman machine start

Docker:

# RHEL / Fedora (requires Docker repo)
sudo dnf install -y docker-ce
sudo systemctl enable --now docker

# Ubuntu
sudo apt-get install -y docker-ce
sudo systemctl enable --now docker

# macOS — Docker Desktop from https://www.docker.com/products/docker-desktop

Version & Help

Podman:

podman --version
podman version                    # client info (no daemon needed)
podman info                       # host and runtime details
podman help
podman <command> --help

Docker:

docker --version
docker version                    # client and daemon info
docker info                       # system-wide info (alias: docker system info)
docker help
docker <command> --help

Registry Login & Logout

Podman:

podman login registry.example.com
podman login -u myuser -p mypassword registry.example.com
podman login -u myuser --password-stdin registry.example.com
                                  # pipe password via stdin (safer than -p)
podman login --tls-verify=false registry.local
                                  # skip TLS verification (non-production only)
podman login -u myuser -p ${TOKEN} quay.io
                                  # TOKEN=$(oc whoami -t) for OpenShift registry

podman logout registry.example.com
podman logout -a                  # --all: remove all registry credentials

Docker:

docker login registry.example.com
docker login -u myuser -p mypassword registry.example.com
docker login -u myuser --password-stdin registry.example.com

docker logout registry.example.com

Images

Podman:

podman search nginx
podman search quay.io/nginx
podman search --filter=is-official=true nginx
podman search --filter=stars=3 nginx

Docker:

docker search nginx
docker search --filter=is-official=true nginx
docker search --filter=stars=3 nginx
docker search --limit 10 nginx
docker search --format "{{.Name}}\t{{.StarCount}}" nginx

Pull

Podman:

podman pull nginx
podman pull nginx:1.27
podman pull quay.io/fedora/fedora:latest
podman pull --tls-verify=false registry.local/myimage

Docker:

docker pull nginx
docker pull nginx:1.27
docker pull --platform linux/arm64 nginx

List & Inspect

Podman:

podman images                     # list local images (alias: podman image ls)
podman images -a                  # include intermediate layers
podman image inspect nginx
podman history nginx

Docker:

docker images                     # alias: docker image ls
docker images -a
docker images --filter=dangling=true
docker images --format "{{.ID}}\t{{.Repository}}:{{.Tag}}"
docker image inspect nginx
docker history nginx
docker history --no-trunc nginx

Tag & Push

Podman:

podman tag nginx:latest quay.io/myuser/nginx:1.27
podman push quay.io/myuser/nginx:1.27
podman push --tls-verify=false registry.local/myimage:tag

Docker:

docker tag nginx:latest myuser/nginx:1.27
docker push myuser/nginx:1.27

Remove Images

Podman:

podman rmi nginx
podman rmi nginx:1.27
podman image prune                # remove dangling images only
podman image prune -a             # remove all unused images
podman image prune -f             # skip confirmation

Docker:

docker rmi nginx
docker image prune                # dangling images only
docker image prune -a             # all unused images
docker image prune -f

Save & Load

Podman:

podman save -o myimage.tar myimage:tag
podman load -i myimage.tar

Docker:

docker image save -o myimage.tar myimage:tag
docker image load -i myimage.tar

Running Containers

Podman:

podman run nginx                  # foreground
podman run -d nginx               # detached (background)
podman run -d --name webserver nginx
podman run -it --rm fedora /bin/bash
                                  # interactive, auto-remove on exit
podman run -d -p 8080:80 nginx    # host port 8080 → container port 80
podman run -d \
  --name myapp \
  -p 8080:8080 \
  -e APP_ENV=production \
  -v /host/data:/app/data:Z \
  myimage:latest
                                  # -e: environment variable
                                  # -v ... :Z sets SELinux label (Podman-specific)

podman run --rm -v "$PWD":/work -w /work python:3.12 python script.py
                                  # one-shot, current dir mounted

Key podman run flags:

-d, --detach             background
-i, --interactive        keep stdin open
-t, --tty                pseudo-TTY
--rm                     remove container + anonymous volumes on exit
--name STRING
-p [[hostIP:]hostPort:]containerPort[/protocol]
-e KEY=VALUE             (--env)
--env-file FILE
-v [[source:]dest[:options]]     (:Z for SELinux label in Podman)
--network bridge|host|none|pasta|container:ID|NETNAME
--pod NAME               join an existing pod (Podman-specific)
--restart no|always|on-failure[:n]|unless-stopped
-u, --user name|uid[:group]
-w, --workdir PATH
--entrypoint CMD
--privileged             full host device access (disables isolation)
--cap-add CAPABILITY
--security-opt label=disable|no-new-privileges=true
--cpus DECIMAL
-m, --memory NUMBER[b|k|m|g]

Docker:

docker run nginx
docker run -d nginx
docker run -d --name webserver nginx
docker run -it --rm ubuntu /bin/bash
docker run -d -p 8080:80 nginx
docker run -d \
  --name myapp \
  -p 8080:8080 \
  -e APP_ENV=production \
  -v /host/data:/app/data \
  --restart unless-stopped \
  myimage:latest

Key docker run flags (same as Podman except where noted):

# Same: -d, -i, -t, --rm, --name, -p, -e, --env-file, -v, --network,
#       --restart, -u, --workdir/-w, --entrypoint, --privileged,
#       --cap-add, --cap-drop, --security-opt, --cpus, -m/--memory
# No --pod flag in Docker (Docker Swarm uses different grouping)

Container Lifecycle

Podman:

podman ps                         # running containers
podman ps -a                      # all containers
podman ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"

podman start <container>
podman stop <container>
podman stop -t 5 <container>      # wait 5s before SIGKILL
podman restart <container>
podman pause <container>
podman unpause <container>

podman rm <container>
podman rm -f <container>          # force-remove running container
podman rm $(podman ps -aq)        # remove all stopped containers

Docker:

docker ps
docker ps -a
docker ps -q                      # IDs only
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"

docker container start <container>
docker container stop <container>
docker container stop -t 5 <container>
docker container restart <container>
docker container pause <container>
docker container unpause <container>
docker container kill <container>            # default signal: KILL
docker container kill -s SIGTERM <container>

docker container rm <container>
docker container rm -f <container>
docker container rm -v <container>           # -v also removes associated volumes
docker rm $(docker ps -aq)

Execute & Interact

Podman:

podman exec -it <container> /bin/bash
podman exec <container> env
podman exec -it <container> sh -c "ls /app"
podman exec -u root -it <container> /bin/bash

Docker:

docker container exec -it <container> /bin/bash
docker container exec <container> env
docker container exec -it <container> sh -c "ls /app"
docker container exec -u root -it <container> /bin/bash

Logs

Podman:

podman logs <container>
podman logs -f <container>        # follow
podman logs --tail=100 <container>
podman logs --since=1h <container>
podman logs --timestamps <container>

Docker:

docker container logs <container>
docker container logs -f <container>
docker container logs -n 100 <container>     # -n is short for --tail
docker container logs --tail=100 <container>
docker container logs --since=1h <container>
docker container logs --timestamps <container>

Copy Files

Podman:

podman cp /local/file <container>:/remote/path
podman cp <container>:/remote/file /local/path

Docker:

docker container cp /local/file <container>:/remote/path
docker container cp <container>:/remote/file /local/path

Build Images

docker build is an alias for docker buildx build (canonical form). Both are valid; flags are identical.

Podman:

podman build -t myimage:latest .
podman build -t myimage:latest -f Dockerfile.prod .
podman build --build-arg VERSION=1.2 -t myimage:1.2 .
podman build --no-cache -t myimage:latest .
podman build --layers -t myimage:latest .
                                  # --layers: cache intermediate layers (default true)
podman build --platform linux/amd64 -t myimage .
podman build --target build-stage -t myimage .
podman build --pull=always -t myimage .
                                  # --pull: always|missing|never|newer (policy string)

Docker:

docker buildx build -t myimage:latest .   # canonical
docker build -t myimage:latest .          # alias (same flags)
docker build -t myimage:latest -f Dockerfile.prod .
docker build --build-arg VERSION=1.2 -t myimage:1.2 .
docker build --no-cache -t myimage:latest .
docker build --target build-stage -t myimage .
docker build --platform linux/amd64,linux/arm64 -t myimage .
docker build --pull -t myimage .
                                  # --pull is boolean in Docker (true/false)
docker build --progress=plain -t myimage .
                                  # --progress: auto|tty|plain|quiet|rawjson

Commit a running container as a new image:

Podman:

podman commit <container> myimage:new-tag

Docker:

docker container commit [-m "message"] [-a "author"] <container> myimage:new-tag

Volumes

Podman:

podman volume create my-volume
podman volume ls
podman volume inspect my-volume
podman volume rm my-volume
podman volume prune               # remove all unused volumes

podman run -d --name mydb \
  -v my-volume:/var/lib/mysql \
  mysql:8.0

Docker:

docker volume create my-volume
docker volume ls
docker volume inspect my-volume
docker volume rm my-volume
docker volume prune               # remove unused local volumes
docker volume prune -a            # include named volumes not referenced by a container

docker run -d --name mydb \
  -v my-volume:/var/lib/mysql \
  mysql:8.0

Networks

Podman:

podman network ls
podman network create my-net
podman network inspect my-net
podman network rm my-net
podman network prune
podman network connect my-net <container>
podman network disconnect my-net <container>

Docker:

docker network ls
docker network create my-net
docker network create -d bridge --subnet 172.20.0.0/16 my-net
docker network inspect my-net
docker network rm my-net
docker network prune
docker network connect my-net <container>
docker network disconnect -f my-net <container>

Inspect & Stats

Podman:

podman inspect <container>
podman inspect --format '{{.State.Status}}' <container>
podman inspect <image>
podman stats                      # live all containers
podman stats <container>
podman top <container>

Docker:

docker container inspect <container>
docker container inspect --format '{{.State.Status}}' <container>
docker image inspect <image>
docker container stats                        # live all containers
docker container stats --no-stream <container>
docker container top <container>

Cleanup

Podman:

podman system prune               # stopped containers + dangling images + unused networks
podman system prune -a            # + all unused images (not just dangling)
podman system prune --volumes     # + unused volumes (excluded by default — data loss risk)
podman system prune -f            # skip confirmation
podman system prune --build       # also remove leftover build containers
podman system prune --external    # clean storage remnants from unclean shutdowns
                                  # --external is incompatible with -a and --filter
podman system df                  # disk usage breakdown

Docker:

docker system prune               # stopped containers + dangling images + unused networks
docker system prune -a            # + all unused images
docker system prune --volumes     # + anonymous volumes
docker system prune -f
docker system df                  # disk usage breakdown
docker system df -v               # verbose breakdown per object

Podman — Pods

Podman supports Kubernetes-style pods — a group of containers sharing network and IPC namespaces. No Docker equivalent.

podman pod create --name mypod
podman pod create --name mypod -p 8080:80
podman pod create --name mypod --network my-net

podman pod ps                     # list pods (also: podman pod ls / list)
podman pod inspect mypod

podman pod start mypod
podman pod stop mypod
podman pod stop -t 10 mypod
podman pod restart mypod
podman pod pause mypod
podman pod unpause mypod
podman pod kill mypod
podman pod kill -s SIGTERM mypod

podman pod rm mypod               # stops and removes pod + all its containers
podman pod rm -f mypod
podman pod prune                  # remove all stopped pods

podman pod stats mypod
podman pod top mypod
podman pod logs mypod

# Run a container inside a pod
podman run -d --pod mypod --name app myimage
podman run -d --pod mypod --name db postgres:16

Podman — Machine (macOS / Windows)

podman machine runs a Linux VM so Podman works on macOS and Windows. Docker Desktop is the equivalent on those platforms.

podman machine init
podman machine init --cpus=4 -m 4096 --disk-size=60
                                  # -m/--memory in MiB; --disk-size in GiB
podman machine init --now         # start immediately after init
podman machine init --rootful     # prefer rootful execution mode
podman machine init --image URL   # custom VM image (flag is --image, not --image-path)

podman machine start
podman machine stop
podman machine restart
podman machine list               # list VMs (also: podman machine ls)
podman machine info               # active machine details
podman machine inspect
podman machine ssh                # open a shell inside the VM
podman machine set                # update machine settings
podman machine rm                 # remove default VM
podman machine rm -f myvm         # force remove named VM
podman machine reset              # reset all machines and environment

Troubleshooting — cannot connect:

podman system connection list

# Restart the machine
podman machine stop && podman machine start

# On macOS, if SSH_AUTH_SOCK causes connection failures
unset SSH_AUTH_SOCK

Podman — Kubernetes YAML

Run Kubernetes-compatible YAML locally without a cluster. No Docker equivalent.

# Play (run) a Kubernetes YAML file
podman kube play file.yaml
podman kube play file.yaml --start=false          # create but don't start
podman kube play --down file.yaml                 # tear down pods from a previous run
podman kube play --replace file.yaml              # tear down then recreate
podman kube play --network my-net file.yaml
podman kube play --tls-verify=false file.yaml
podman kube play --configmap configmap.yaml file.yaml

# Legacy alias (still valid):
podman play kube file.yaml

# Generate Kubernetes YAML from a running container or pod
podman kube generate mypod
podman kube generate -f output.yaml mypod
podman kube generate -s mypod                    # -s: include a Service object
podman kube generate --type deployment mypod     # pod|deployment|daemonset|job

# Legacy alias (deprecated form, may still work):
# podman generate kube mypod

# Apply YAML to a running pod (update in place)
podman kube apply mypod

Podman — Systemd via Quadlet

podman generate systemd is deprecated (no new features; Quadlet is the replacement).

Quadlet generates systemd units from declarative .container, .pod, .volume, and .network files.

Unit file locations:

ScopePath
Rootless~/.config/containers/systemd/
Root/etc/containers/systemd/

Minimal .container unit file:

# ~/.config/containers/systemd/myapp.container

[Unit]
Description=My Application

[Container]
Image=quay.io/myuser/myapp:latest
ContainerName=myapp
PublishPort=8080:8080
Environment=APP_ENV=production
Volume=/data/myapp:/app/data:Z
Network=my-net.network

[Service]
Restart=always
TimeoutStartSec=900

[Install]
WantedBy=default.target
# After creating or editing unit files
systemctl --user daemon-reload

systemctl --user start myapp
systemctl --user stop myapp
systemctl --user status myapp
systemctl --user enable myapp     # start on login
systemctl --user disable myapp

# Debug Quadlet unit generation
/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun

Docker Compose

docker compose (space, not hyphen) is the built-in plugin since Docker CLI 20.10. Podman has podman compose (built-in since Podman 4.7+) or use podman-compose (third-party).

Docker:

docker compose up                             # create and start containers
docker compose up -d                          # detached
docker compose up --build                     # rebuild images before starting
docker compose up --remove-orphans
docker compose up --scale web=3

docker compose down                           # stop and remove containers, networks
docker compose down -v                        # also remove volumes
docker compose down --rmi all                 # also remove images
docker compose down --remove-orphans -t 30

docker compose ps                             # list containers in project
docker compose ps -a
docker compose ps -q

docker compose logs
docker compose logs -f
docker compose logs --tail=100 web
docker compose logs --timestamps

docker compose build
docker compose build --no-cache
docker compose pull
docker compose pull --ignore-pull-failures

docker compose exec web /bin/bash
docker compose run --rm web pytest
docker compose stop [SERVICE]
docker compose start [SERVICE]
docker compose restart [SERVICE]
docker compose config                         # validate and view merged compose file

Private Registry — Kubernetes Secret

kubectl create secret docker-registry registry-cred \
  --docker-server=myregistry.example.com \
  --docker-username=myuser \
  --docker-password=mypassword \
  -n my-namespace

Reference in a Pod or Deployment spec (at the same level as containers):

spec:
  imagePullSecrets:
    - name: registry-cred
  containers:
    - name: myapp
      image: myregistry.example.com/myapp:latest

Dockerfile Reference

A Dockerfile works identically for podman build and docker build.

FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
                                  # base image — prefer UBI for Red Hat targets

LABEL org.opencontainers.image.authors="[email protected]" \
      version="1.0"

ARG VERSION=1.0                   # build-time variable (not available at runtime)

# Combine RUN commands to minimise layers
RUN microdnf install -y python3 && \
    microdnf clean all

WORKDIR /app                      # working directory for subsequent instructions

COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt

COPY . .

ENV APP_PORT=8080                 # available at build time and runtime

EXPOSE 8080                       # documents the port; does not publish it

USER 1001                         # run as non-root (required by OpenShift)

HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1

CMD ["python3", "app.py"]

Dockerfile instruction reference:

InstructionSyntaxPurpose
FROMFROM [--platform=P] IMAGE[:TAG] [AS NAME]Base image; starts a build stage
RUNRUN CMD or RUN ["exec","arg"]Execute during build; creates a layer
COPYCOPY [OPTIONS] SRC... DESTCopy from build context into image
ADDADD [OPTIONS] SRC... DESTLike COPY; also unpacks local tars and fetches URLs
CMDCMD ["exec","arg1"]Default command (overridable at docker run)
ENTRYPOINTENTRYPOINT ["exec","arg1"]Fixed entrypoint
ENVENV KEY=VALUERuntime environment variable (persists in image)
ARGARG NAME[=DEFAULT]Build-time variable only (not in final image)
EXPOSEEXPOSE PORT[/PROTOCOL]Documents a listening port; does not publish
WORKDIRWORKDIR /pathWorking directory for subsequent instructions
USERUSER user[:group]Run-as identity
VOLUMEVOLUME ["/path"]Declares a mount point
LABELLABEL key=valueImage metadata
ONBUILDONBUILD INSTRUCTIONDeferred instruction executed in child builds
HEALTHCHECKHEALTHCHECK [OPTIONS] CMD cmdContainer health probe
STOPSIGNALSTOPSIGNAL signalSignal sent to stop the container
SHELLSHELL ["exec","params"]Override default shell for shell-form instructions
MAINTAINERMAINTAINER nameDeprecated — use LABEL org.opencontainers.image.authors=

References: Podman commands · Docker CLI reference · Dockerfile reference · Podman Quadlet

Disclaimer: Views expressed in articles are those of the respective authors and do not necessarily reflect the views of their employers or this site. While we aim for accuracy, please verify information before relying on it, and let us know if you spot an error.
Share:

Related Posts

Ansible Automation Platform - Disaster Recovery

Ansible Automation Platform - Disaster Recovery

These are official references to implement Disaster Recovery (DR) designs for Ansible Automation Platform.

Ansible Automation Platform - CLI Cheat Sheet

Ansible Automation Platform - CLI Cheat Sheet

AAP CLI Commands $ aap-gateway-manage update_password --username='<username>' --password='<password>' # For containerized …

Git - Tips and Notes

Git - Tips and Notes

Git Cheat Sheet How to clean Git commit history How to get latest content to branch which already checked in How to fetch latest content from main …

Ansible LightSpeed

Ansible LightSpeed

Introduction Ansible Lightspeed is a generative AI service designed to streamline the creation and maintenance of Ansible Playbooks. Here’s a …

CI/CD Practices

CI/CD Practices

Collection of articles on CI/CD implementation using Jenkins, GitHub Actions, GitLab CICD and different container registries.

Ansible Tower - Load Balancing

Ansible Tower - Load Balancing

1. Ansible Tower Installation 1. Ansible Tower Installation 1.1. Ansible Tower Installation and Reference Guide v3.6.1 1.2. Ansible Tower Quick …