# Managing Containers with Podman

> Chapter 19 of the Courseiva REDHAT-RHCSA curriculum — https://courseiva.com/learn/redhat-rhcsa/container-management-with-podman

**Official objective:** 6.1 — Run and manage containers using Podman and Skopeo.

## Introduction

Managing Containers with Podman. This is the skill that lets you run an application in a self-contained, portable package without needing a full virtual machine. For the EX200 exam, mastering Podman means you can deploy, inspect, and troubleshoot software the way modern IT teams do — fast, reliably, and without messing up your host system.

## The Shared House Kitchen Analogy

A container image is a frozen ready-meal in the freezer. It has all the ingredients and spices pre-portioned, just add heat. A running container is that ready-meal after you've microwaved it on a plate — the meal is now active and you can eat it, but the original frozen meal is still in the freezer, untouched. Podman is the chef who takes the frozen meal out of the freezer, puts it on a plate, and microwaves it for exactly the right time.

The key insight for managing containers with Podman is that your host computer — the one you are sat at — is the shared house kitchen. Every container is a separate meal on a separate plate. One container might be spaghetti bolognese, another a Thai green curry. They each have their own plate (their own filesystem), their own set of cutlery (their own processes), and their own spice rack (their own software libraries). But they all share the same kitchen sink (the host operating system's kernel) and the same oven (the CPU). Podman is the house rule: anyone can grab a frozen meal from the freezer, defrost it on the counter (pull the image), microwave it (run the container), eat from it (interact with the application), and when they are finished, they throw the plate in the dishwasher (stop and remove the container). The frozen meal remains ready for the next person.

This analogy works for what EX200 tests because the exam wants you to understand that containers are isolated from each other on the same host. Just as you do not want your Thai curry to taste of bolognese, you do not want one container's broken application to crash another. Podman gives you the controls to manage that isolation.

## Core explanation

Podman is an open-source tool for running and managing containers on Linux. A container is a lightweight, standalone, executable package that includes everything needed to run a piece of software: code, runtime, system tools, libraries, and settings. Containers are isolated from each other and from the host system, but they share the host's operating system kernel — the core of the OS that manages hardware and processes. This makes them much faster and more efficient than virtual machines, which each run a full guest OS.

Podman is designed to be a drop-in replacement for Docker, the most famous container tool. It uses the same command syntax (e.g. `podman run`, `podman ps`), so if you know Docker, you know Podman. The big difference is that Podman does not require a daemon — a background service that runs constantly with root privileges. Docker runs a daemon called `dockerd` that has full control over containers. Podman runs containers directly as child processes of the user's shell, using something called the "fork-exec" model. This means each container is started by the user's own user ID, not by a system-wide daemon. This is more secure because an attacker who compromises Podman cannot escalate to root privileges through a daemon.

Let us start with the fundamental concepts. An image is a read-only template. Think of it as a snapshot of a filesystem containing a specific application and all its dependencies. Images are hosted in registries — servers that store and serve images. The default registry for Podman is Red Hat's registry.access.redhat.com, but you can also use Docker Hub, Quay.io, or any private registry. You download (pull) an image using `podman pull`. For example, `podman pull registry.access.redhat.com/ubi8/ubi` retrieves the Red Hat Universal Base Image 8. Once pulled, the image sits on your local machine. To create a running environment from that image, you use `podman run`. This command creates a new writable layer (called the container) on top of the read-only image, and starts the application inside it. The container is ephemeral — changes you make inside it are lost when you stop the container, unless you explicitly commit those changes to a new image.

You can list running containers with `podman ps`. To see all containers, including stopped ones, use `podman ps -a`. To stop a running container, use `podman stop`. To remove a container, use `podman rm`. To remove an image, use `podman rmi`. These commands mirror Docker exactly.

Podman also supports pods. A pod is a group of one or more containers that share the same network namespace (they can communicate over localhost) and the same storage. This is borrowed from Kubernetes, the large-scale container orchestration platform. Podman can create and manage pods with `podman pod create`, `podman pod start`, etc.

Another key feature is rootless containers. By default, Podman runs containers without root privileges. The user namespace feature maps the root user inside the container to a non-root user on the host. This means even if a container gets compromised, the attacker cannot gain administrative privileges on the host system. This is a major security improvement over older container runtimes.

Managing containers also involves inspecting them. Use `podman inspect` to view detailed metadata about a container or image in JSON format. Use `podman logs` to see the application output from a container. Use `podman exec` to run a command inside a running container — for example, `podman exec -it mycontainer /bin/bash` opens an interactive shell.

Finally, you can manage images with `podman tag` to give an image an alias, and `podman push` to upload an image to a registry. 

For EX200, you will need to be comfortable with these commands and concepts. The exam expects you to run containers from Red Hat's official registries, manage container lifecycle (pull, run, stop, remove), inspect their state, and understand the difference between images and containers. You will also need to know how to expose network ports using the `-p` flag (e.g., `-p 8080:80` maps host port 8080 to container port 80) and how to set environment variables with `-e`.

## Real-world context

Imagine you work for a small e-commerce company called ShopFast. The development team has just built a new version of their product catalogue microservice. In the old days, deploying this would involve provisioning a new virtual machine, installing a specific version of Python, the correct library dependencies, and then manually copying the code. That process took hours and often failed because the production server had slightly different library versions than the development laptop.

With Podman, the developer creates a Containerfile (the Red Hat equivalent of a Dockerfile) that specifies exactly what the application needs. They build an image and push it to the company's private registry on Quay.io. The operations team then pulls that image onto the production server using:

podman pull quay.io/shopfast/catalogue:2.4.1

Then they run the container:

podman run -d --name catalogue-v2 -p 3000:3000 quay.io/shopfast/catalogue:2.4.1

The `-d` flag runs the container in detached mode (background), and `--name` gives it a human-readable name. Now the new microservice is running on port 3000. The old version, still running on port 3001, stays up until they are ready to switch traffic.

A week later, the server runs out of disk space because the container logs are growing. The administrator runs:

podman logs --tail 50 catalogue-v2

To see the last 50 log lines. They realise the logs are verbose, so they use:

podman exec catalogue-v2 ls /var/log/

To explore the container's filesystem and then clean up old logs with a script. They also run:

podman inspect catalogue-v2 | grep -i mount

To see where the container's writable layer is stored on the host, so they can monitor disk usage.

When the new version is fully tested, they stop and remove the old container:

podman stop catalogue-v1
podman rm catalogue-v1

Then they tag the new image as "latest" and push it back to the registry for other teams. The entire operation, from pulling the image to having the new version live, takes under two minutes. The developer's environment is exactly reproduced because the container image includes the correct Python version and all dependencies.

## Exam focus

The EX200 exam tests objective 6.1 “Run and manage containers using Podman and Skopeo”. Expect four to six questions on this topic, mostly in the form of performance-based tasks where you must execute commands in a terminal. Questions rarely ask for theoretical definitions; they ask you to prove you can use the tools.

Here is what the exam specifically tests:

- Running a container from a Red Hat registry: You must use `podman run` with an image from `registry.access.redhat.com` or `registry.redhat.io`. The exam will give you an image name. You must know how to pull it and start it. They may ask you to run it in detached mode (`-d`) and give it a name (`--name`). They will test port mapping with `-p` — e.g., expose host port 8080 to container port 80.

- Managing container lifecycle: You must be able to list running containers (`podman ps`), list all containers (`podman ps -a`), stop a container (`podman stop`), start a stopped container (`podman start`), and remove a container (`podman rm`). They may ask you to remove a container that is still running, which requires `podman rm -f` or stopping it first.

- Inspecting containers and images: You will use `podman inspect` on a container or an image. They may ask you to find a specific piece of metadata — for example, the IP address of a container, the mounts, or the operating system the image is based on. You must know that `inspect` outputs JSON and be able to use `grep` or `jq` to filter it.

- Working with images: You must pull an image (`podman pull`), list images (`podman images`), and remove an image (`podman rmi`). They may test that you cannot remove an image that is in use by a container — you must first remove the container.

- Rootless containers: The exam environment runs as a non-root user. By default, Podman runs containers rootlessly. They may ask you to notice that certain commands (like binding to a port below 1024) will fail without root — for example, `podman run -p 80:80` will fail. The correct approach is to use a higher port like 8080.

- Pods: You must be able to create a pod (`podman pod create`), list pods (`podman pod ps`), and run a container inside a pod (`podman run --pod mypod`). They may ask you to run two containers in the same pod so they can communicate over localhost.

- Environment variables: Questions frequently require you to pass environment variables with `-e`, e.g., `podman run -e MYSQL_ROOT_PASSWORD=mysecret ...`.

Common traps:
- Forgetting the `-a` flag with `podman ps` to see stopped containers.
- Trying to remove an image that a container refers to without first removing the container.
- Using `podman start` on a container that has been removed (you can't start a removed container, only a stopped one).
- Confusing `podman run` (creates and starts a new container) with `podman start` (starts an existing stopped container).
- Not realising that changes inside a container are lost after `podman rm` — they are not saved back to the image.

Key definitions to memorise:
- Image: read-only template.
- Container: runnable instance of an image.
- Registry: server storing images.
- Pod: group of containers sharing network namespace.
- Rootless: running containers without root privileges.
- Detached mode: container runs in the background.

## Step by step

1. **Pull an image from a registry** — You run `podman pull registry.access.redhat.com/ubi8/ubi`. Podman downloads the image layers and stores them locally. If the image already exists, it does nothing. This step ensures you have the template needed to create a container.
2. **Run a container from that image** — You run `podman run -d --name myfirstcontainer registry.access.redhat.com/ubi8/ubi sleep 3600`. The `-d` flag detaches the container (runs in background), `--name` gives it an easy-to-remember name, and `sleep 3600` is the command that keeps the container alive for an hour. Without a command like `sleep`, the container would exit immediately.
3. **List and inspect running containers** — Run `podman ps` to verify the container is running. Then run `podman inspect myfirstcontainer` to view detailed metadata. You will see the container's ID, state, mounts, and network settings. This helps troubleshoot configurations.
4. **Execute a command inside the running container** — Run `podman exec -it myfirstcontainer /bin/bash`. This opens an interactive Bash shell inside the container. You can explore the filesystem, check processes, or debug issues. Type `exit` when done.
5. **Stop and remove the container** — First, stop the container with `podman stop myfirstcontainer`. This sends a SIGTERM signal to the main process. Then remove the container with `podman rm myfirstcontainer`. If you skip the stop, you can use `podman rm -f` to force removal. After removal, the container is gone, and you can remove the image with `podman rmi registry.access.redhat.com/ubi8/ubi`.

## Comparisons

### Podman vs Docker

**Podman:**
- Daemonless architecture (no background service needed)
- Rootless containers by default for improved security
- Native support for pods and systemd integration

**Docker:**
- Requires a daemon (dockerd) running as root
- Rootless mode available but not default
- Pods not supported natively (only Docker Compose for multi-container groups)

### Container vs Virtual Machine

**Container:**
- Shares the host OS kernel
- Startup in seconds
- Isolated processes, not a full OS

**Virtual Machine:**
- Runs a full guest OS with its own kernel
- Startup in minutes
- Full hardware-level isolation

### Image vs Container

**Image:**
- Read-only template
- Stored in a registry or locally
- Cannot be modified directly

**Container:**
- Read-write instance of an image
- Ephemeral runtime environment
- Can be modified but changes lost on removal

### Podman Pull vs Podman Run

**Podman Pull:**
- Downloads an image to local storage
- Does not create a container
- Can be run independently of run

**Podman Run:**
- Creates and starts a container in one step
- Automatically pulls the image if not present
- Requires an image name as argument

## Diagram

_Lifecycle of a container managed with Podman: from pulling an image to running, inspecting, and finally removing the container and image._

```mermaid
flowchart TD
    A[Podman CLI] --> B[Pull Image]
    B --> C[Image stored locally]
    C --> D[Podman Run]
    D --> E[Running Container]
    E --> F[Podman PS]
    E --> G[Podman Exec]
    E --> H[Podman Logs]
    E --> I[Podman Stop]
    I --> J[Stopped Container]
    J --> K[Podman Start]
    J --> L[Podman RM]
    L --> M[Container Removed]
    M --> N[Podman RMI]
    N --> O[Image Removed]
```

## Common misconceptions

- **Misconception:** Podman is just a different name for Docker and works identically in all situations. **Reality:** Podman has the same command-line syntax as Docker but works without a daemon and uses a different security model (rootless by default). Some features like Docker Swarm are not present in Podman. (Because the commands look identical (run, ps, stop, rm), beginners assume they are the same under the hood. The difference only appears when troubleshooting daemon-related errors or security issues.)
- **Misconception:** When I run a container and make changes to files inside it, those changes are permanent and saved back to the image. **Reality:** Changes to a container's writable layer are ephemeral. They are lost when the container is removed. To save changes, you must explicitly commit the container to a new image using `podman commit`. (In the real world, users often edit configuration files inside a container and expect them to persist. This works until the container is deleted, then the changes vanish, causing confusion.)
- **Misconception:** I can only use images from Docker Hub with Podman. **Reality:** Podman can pull images from any OCI-compliant registry, including Docker Hub, Quay.io, Red Hat's registries, and private registries. You specify the registry in the image name. (Because Docker Hub is the most well-known registry, beginners assume it is the only source. The EX200 exam specifically uses Red Hat's registries, so this misconception causes failures.)
- **Misconception:** A container is like a virtual machine but lighter. **Reality:** A container shares the host OS kernel, whereas a virtual machine runs a complete guest OS including its own kernel. Containers are isolated processes, not full operating systems. (The performance benefits are similar (fast startup, low overhead), so the mental model of a mini-VM is tempting. But the security and architecture implications are very different.)
- **Misconception:** Podman is only for Red Hat Enterprise Linux and cannot be used on other distros. **Reality:** Podman is open source and runs on most Linux distributions, including Fedora, CentOS, Ubuntu, and Debian. It is also available on macOS and Windows via Podman Machine. (Because Podman is developed by Red Hat and heavily integrated into RHEL, beginners assume it is Red Hat-exclusive. This limits their willingness to practise on their own machines.)

## Key takeaways

- A container is a runnable instance of a read-only image; changes inside a container are lost when the container is removed unless you commit them.
- Podman does not require a daemon; it runs containers as child processes of the user's shell, enhancing security.
- Use `podman run -d --name myapp -p 8080:80 registry/image:tag` to deploy a container in detached mode with port mapping.
- List all containers, including stopped ones, with `podman ps -a`; just `podman ps` shows only running containers.
- You cannot remove an image that a container references; remove the container first with `podman rm` before using `podman rmi`.
- Pods in Podman allow multiple containers to share a network namespace, enabling communication over localhost.
- Environment variables are passed into containers using the `-e` flag, e.g., `-e DB_HOST=localhost`.

## FAQ

**What is the difference between podman run and podman start?**

`podman run` creates a new container from an image and starts it. `podman start` starts an existing stopped container that was previously created with `podman run` or `podman create`.

**How do I see logs from a container that exited?**

Use `podman logs <container-name>` even after the container has stopped. The logs are stored until the container is removed. For stopped containers, you must use the name or ID from `podman ps -a`.

**Can Podman run containers from Docker Hub?**

Yes. Just specify the full image path, e.g., `podman pull docker.io/library/nginx:latest`. Podman uses the same OCI image format, so Docker Hub images work.

**Why does my container exit immediately after I run it?**

A container exits when its main process finishes. If you run a container that has no long-running process (like a shell without a terminal), it exits. Use a command like `sleep 3600` or a service entrypoint to keep it alive.

**How do I make a container start automatically on boot?**

Podman does not include a built-in restart policy like Docker. Instead, use `podman generate systemd` to create a systemd service file, then enable it with `systemctl enable`.

**What is a pod in Podman?**

A pod is a group of one or more containers that share the same network namespace and can communicate over localhost. It is used for co-located containers, similar to Kubernetes pods.

## Check your understanding

1. **What command lists all containers, including those that are stopped?**

   Answer: `podman ps -a` lists all containers (running and stopped). `podman ps` alone shows only running containers.

2. **How do you run a container with port mapping so that host port 8080 maps to container port 80?**

   Answer: Use `podman run -p 8080:80 image-name`. The syntax is `-p host-port:container-port`.

3. **What is the difference between an image and a container?**

   Answer: An image is a read-only template; a container is a runnable instance of that image with a writable layer.

4. **After you remove a container, are changes made inside it saved?**

   Answer: No. Changes are lost because they are stored in the container's writable layer, which is deleted when the container is removed. To save changes, use `podman commit`.

5. **Which flag is used to run a container in the background (detached mode)?**

   Answer: The `-d` flag runs a container in detached mode, meaning it runs in the background and does not attach to the terminal.

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/redhat-rhcsa/container-management-with-podman
