Skip to content
Search RunEntLinux

Searches general documentation on RunEntLinux. Each distribution has its own documentation search.

    Browse this documentation

    Getting Started with Podman

    Podman is a container engine developed primarily by Red Hat. The key differences from Docker are:

    FeaturePodmanDocker
    DaemonDaemonlessRequires dockerd daemon
    Root privilegesNative rootless container supportRequires extra configuration
    Command compatibilityCompatible with Docker CLI-
    Pod supportNative Pod support (similar to Kubernetes)Not supported
    System integrationUses systemd for container lifecycle managementOwn daemon management
    Default availabilityIncluded in RHEL/CentOS/AlmaLinux default repositoriesRequires third-party repository
    Terminal window
    sudo dnf install -y podman

    Verify the installation:

    Terminal window
    podman --version
    podman info
    Terminal window
    # Pull an image from Docker Hub
    podman pull docker.io/library/nginx:latest
    # Pull an image from Quay.io
    podman pull quay.io/centos/centos:stream9
    # List local images
    podman images
    Terminal window
    # Run in the foreground, automatically remove on exit
    podman run --rm -it centos:stream9 /bin/bash
    # Run Nginx in the background, map port 8080 to container port 80
    podman run -d --name my-nginx -p 8080:80 docker.io/library/nginx:latest
    # Mount a local directory to the container
    podman run -d --name my-web \
    -p 8080:80 \
    -v /srv/www:/usr/share/nginx/html:Z \
    docker.io/library/nginx:latest
    Terminal window
    # View running containers
    podman ps
    # View all containers (including stopped ones)
    podman ps -a
    # View container details
    podman inspect my-nginx
    # View container logs
    podman logs my-nginx
    # Follow logs in real time
    podman logs -f my-nginx
    Terminal window
    # Stop a container
    podman stop my-nginx
    # Start a stopped container
    podman start my-nginx
    # Restart a container
    podman restart my-nginx
    # Remove a stopped container
    podman rm my-nginx
    # Force remove a running container
    podman rm -f my-nginx
    # Remove all stopped containers
    podman container prune
    Terminal window
    # Enter a container with an interactive terminal
    podman exec -it my-nginx /bin/bash
    # Execute a single command inside a container
    podman exec my-nginx cat /etc/nginx/nginx.conf

    Create a Containerfile (equivalent to a Dockerfile):

    FROM docker.io/library/almalinux:9-minimal
    # Install application
    RUN microdnf install -y httpd && microdnf clean all
    # Copy configuration and web files
    COPY index.html /var/www/html/index.html
    COPY httpd.conf /etc/httpd/conf/httpd.conf
    # Expose port
    EXPOSE 80
    # Start command
    CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
    Terminal window
    # Build the image, -t specifies name and tag
    podman build -t my-httpd:v1 .
    # View the built image
    podman images
    # Run a container using the custom image
    podman run -d --name web -p 8080:80 my-httpd:v1
    Terminal window
    # Save an image to a tar file
    podman save -o my-httpd-v1.tar my-httpd:v1
    # Load an image from a tar file
    podman load -i my-httpd-v1.tar

    podman-compose is a compatible alternative to Docker Compose.

    Terminal window
    # Prefer the packaged version (EPEL / distribution repos; the package name varies by EL release, so check once)
    sudo dnf install -y podman-compose || sudo dnf install -y python3-podman-compose
    # Do not `pip3 install podman-compose` system-wide: on EL9/EL10 the system Python may enforce
    # PEP 668 (externally-managed-environment) and refuse the install; if you must use pip, use a venv.

    Create docker-compose.yml:

    version: "3"
    services:
    web:
    image: docker.io/library/nginx:latest
    ports:
    - "8080:80"
    volumes:
    - ./html:/usr/share/nginx/html:Z
    depends_on:
    - app
    app:
    image: docker.io/library/python:3.11-slim
    working_dir: /app
    volumes:
    - ./app:/app:Z
    command: python3 -m http.server 5000
    ports:
    - "5000:5000"
    db:
    image: docker.io/library/mariadb:10.11
    environment:
    MYSQL_ROOT_PASSWORD: changeme
    MYSQL_DATABASE: myapp
    volumes:
    - db_data:/var/lib/mysql
    volumes:
    db_data:
    Terminal window
    # Start all services (in the background)
    podman-compose up -d
    # View service status
    podman-compose ps
    # View logs
    podman-compose logs -f
    # Stop and remove all services
    podman-compose down

    Rootless containers are one of Podman’s core advantages, allowing regular users to run containers without root privileges.

    1. Verify that UID mapping is configured for the user:

      Terminal window
      cat /etc/subuid
      cat /etc/subgid

      If the current user has no entry, add one manually:

      Terminal window
      sudo usermod --add-subuids 100000-165535 $(whoami)
      sudo usermod --add-subgids 100000-165535 $(whoami)
    2. Run a container as a regular user:

      Terminal window
      podman run -d --name rootless-nginx -p 8080:80 docker.io/library/nginx:latest
    3. Verify container process ownership:

      Terminal window
      ps aux | grep nginx
      podman top rootless-nginx

    Prefer Quadlet (Podman 4.4+ systemd integration, available on EL9/EL10 — see Quadlet). podman generate systemd is deprecated upstream and is kept here only so old deployments can be read; the rest of this page already recommends Quadlet.

    Terminal window
    # Legacy (deprecated): generate a systemd unit for an existing container
    podman generate systemd --name rootless-nginx --files --new
    # Move the generated file to the user systemd directory
    mkdir -p ~/.config/systemd/user/
    mv container-rootless-nginx.service ~/.config/systemd/user/
    # Reload and enable the service
    systemctl --user daemon-reload
    systemctl --user enable --now container-rootless-nginx.service
    # Allow user services to continue running after the user logs out
    loginctl enable-linger $(whoami)

    Check the service status:

    Terminal window
    systemctl --user status container-rootless-nginx.service
    Section titled “Quadlet: the recommended approach on EL 9+”

    Where Quadlet files go:

    • System level (root): /etc/containers/systemd/
    • User level (rootless): ~/.config/containers/systemd/

    Create a .container file describing the container:

    ~/.config/containers/systemd/nginx.container
    [Unit]
    Description=Nginx (managed by Quadlet)
    After=network-online.target
    [Container]
    Image=docker.io/library/nginx:latest
    PublishPort=8080:80
    # Volume mounts get SELinux labels automatically, equivalent to :Z
    Volume=%h/nginx/html:/usr/share/nginx/html:Z
    [Service]
    Restart=always
    [Install]
    # Start automatically on boot (user login)
    WantedBy=default.target

    Apply the configuration:

    Terminal window
    # Have systemd re-read the files and generate nginx.service
    systemctl --user daemon-reload
    systemctl --user start nginx.service
    # Check status (the service name is the filename: .container -> .service)
    systemctl --user status nginx.service
    # Keep rootless containers running after the user logs out
    loginctl enable-linger $(whoami)

    To change the container config, just edit the .container file and daemon-reload — no need to regenerate the unit as with podman generate systemd. For system-level units, place the file in /etc/containers/systemd/ and use systemctl (without --user).

    Pods are a unique Podman feature, similar to the Kubernetes Pod concept, where multiple containers share the same network namespace.

    Terminal window
    # Create a Pod with port mappings
    podman pod create --name my-pod -p 8080:80 -p 3306:3306
    # Run Nginx in the Pod
    podman run -d --pod my-pod --name pod-nginx docker.io/library/nginx:latest
    # Run MariaDB in the same Pod
    podman run -d --pod my-pod --name pod-db \
    -e MYSQL_ROOT_PASSWORD=changeme \
    docker.io/library/mariadb:10.11
    # View Pod status
    podman pod ps
    podman pod inspect my-pod
    # Stop and remove a Pod (affects all containers in the Pod)
    podman pod stop my-pod
    podman pod rm my-pod
    Terminal window
    # Clean up unused images
    podman image prune
    # Clean up all unused resources (images, containers, volumes)
    podman system prune -a
    # View disk usage
    podman system df
    # View container resource usage
    podman stats

    EL 10 upgrades Podman from 4.x to Podman 5.x. Key changes:

    FeaturePodman 4.x (EL 9)Podman 5.x (EL 10)
    Rootless network backendslirp4netnspasta (default)
    PerformanceBaselineBetter network performance
    API compatibility-Mostly compatible with Podman 4.x

    Rootless network backend change

    On EL 10, rootless containers use pasta as the network backend by default (replacing slirp4netns), which generally offers better performance with no extra configuration. If needed, you can switch back:

    Install slirp4netns (for legacy behavior)
    sudo dnf install slirp4netns
    Verify Podman version
    podman --version
    podman info | grep -i network