Podman pods allow you to run multiple containers that share the same network namespace, mirroring the Kubernetes pod model without requiring a container orchestrator. On RHEL 8, Podman is available in the default AppStream repositories and provides native rootless pod support out of the box. This tutorial covers creating and managing pods, running multi-container workloads inside them, and generating Kubernetes-compatible YAML manifests from a running pod. Understanding pods is an essential step toward moving containerized workloads from a single RHEL 8 host to a Kubernetes or OpenShift cluster.
Prerequisites
- RHEL 8 server with root or sudo access
container-toolsmodule installed (dnf module install -y container-tools)- Basic familiarity with container concepts and the
podmanCLI - Internet access to pull container images from a registry
Step 1 — Install Podman and Verify
Install the container tools module which includes Podman, Buildah, and Skopeo:
dnf module install -y container-tools
podman --version
podman info | grep -E "version|os|arch"
Step 2 — Create a Pod and Understand the Infra Container
A Podman pod always starts with an invisible infra container (based on k8s.gcr.io/pause) that holds the network namespace and port bindings for the entire pod. All other containers in the pod share that namespace.
# Create a pod named mypod, expose port 8080 on the host mapped to 80 inside the pod
podman pod create --name mypod -p 8080:80
# Inspect the pod and note the infra container ID
podman pod inspect mypod
# List pods — note STATUS is "Created" until at least one app container starts
podman pod list
# The infra container is already running to hold the namespace
podman ps --all
Step 3 — Add Application Containers to the Pod
Containers joined to a pod share the network and IPC namespaces of the infra container. Port 8080:80 was already declared at pod creation, so you do not re-specify it on individual containers:
# Run nginx inside the pod — it will listen on port 80 of the shared namespace
podman run -d --pod mypod --name web docker.io/library/nginx:latest
# Run redis inside the same pod — it shares 127.0.0.1 with nginx
podman run -d --pod mypod --name cache docker.io/library/redis:latest
# Verify both containers are running in the pod
podman ps --pod
# nginx and redis can communicate over localhost inside the pod
# From the nginx container, redis is reachable at 127.0.0.1:6379
podman exec web curl -s http://127.0.0.1/
podman exec cache redis-cli ping
Step 4 — Manage Pod Lifecycle
Podman provides pod-level commands that act on all containers in the pod simultaneously:
# Stop all containers in the pod (infra container stays running)
podman pod stop mypod
# Start the pod again
podman pod start mypod
# Restart all containers in the pod
podman pod restart mypod
# View per-container resource stats for the pod
podman pod stats mypod
# View logs for all containers in the pod
podman pod logs mypod
# Remove the pod and all its containers (must stop first)
# podman pod rm --force mypod
Step 5 — Generate Kubernetes YAML
One of Podman’s most powerful features is generating a Kubernetes Pod spec from a running pod. This YAML can be applied directly to an OpenShift or Kubernetes cluster:
# Generate a Kubernetes-compatible Pod manifest from the running pod
podman generate kube mypod > mypod.yaml
cat mypod.yaml
The generated YAML will include both the web (nginx) and cache (redis) containers with their images, ports, and resource references. You can edit the file to add resource limits, environment variables, or config map references before deploying to a cluster.
Step 6 — Play Back the YAML with Podman
You can recreate the exact pod locally from the YAML manifest using podman play kube. This is useful for testing manifests before sending them to a cluster:
# First remove the running pod if still active
podman pod stop mypod && podman pod rm mypod
# Recreate the pod from the YAML manifest
podman play kube mypod.yaml
# Verify the pod and containers are running
podman pod list
podman ps --pod
# Test the nginx endpoint
curl http://localhost:8080/
# Tear down what was created by play kube
podman play kube --down mypod.yaml
Conclusion
You have created a Podman pod on RHEL 8, added multiple application containers sharing a single network namespace, managed the pod lifecycle with pod-level commands, and round-tripped the configuration through Kubernetes YAML using podman generate kube and podman play kube. The infra container pattern ensures port mappings and network namespaces persist independently of individual application container restarts, making pods more resilient than standalone containers. Podman pods provide a seamless path for testing Kubernetes workloads locally on RHEL 8 before deploying to OpenShift or any upstream cluster.
Next steps: Running Rootless Pods with Podman on RHEL 8, Deploying Podman Pod YAML to OpenShift, and Automating Podman Pod Startup with Systemd Quadlet on RHEL 8.