Learn › RHCSA (EX200) › Containers
podman - a hands-on Linux lab on a real virtual machine.
Run containers interactively and in the background. Map ports, pass environment variables, exec into running containers, and check logs. These are the daily operations.
Your progress is tracked automatically. Just type commands naturally and run check-progress to see your status.
> "Manage containers, including running, stopping, and removing them."
This is where containers become practical. You will run containers in the foreground and background, map ports so you can access services, pass environment variables, execute commands inside running containers, and manage the container lifecycle.
podman run registry.access.redhat.com/ubi9/ubi-minimal echo "hello"
This pulls the image (if not already local), creates a container, runs the echo command, and exits. The container is now in "stopped" state.
For long-running services (web servers, databases), run in detached mode:
podman run -d --name web registry.access.redhat.com/ubi9/httpd-24
Without -d, the container runs in the foreground and takes over your terminal.
To get a shell inside a container:
podman run -it registry.access.redhat.com/ubi9/ubi-minimal /bin/bash
Type exit to leave the container. The container stops when its main process exits.
Containers have their own network namespace. To access a containerized web server from the host, you map ports:
podman run -d --name web -p 8080:80 registry.access.redhat.com/ubi9/httpd-24
The -p 8080:80 flag means: host port 8080 maps to container port 80. Requests to localhost:8080 reach the web server inside the container.
Host port 8080 ---> Container port 80 (httpd)
Test it:
curl http://localhost:8080
Rootless containers cannot bind to ports below 1024. Use ports like 8080, 8443, 9090. If the exam says "port 8080 on the host," that works rootless. If it says "port 80 on the host," you need rootful (sudo).
Pass configuration to a container using -e:
podman run -d --name db -e MYSQL_ROOT_PASSWORD=secret -e MYSQL_DATABASE=appdb \
registry.access.redhat.com/rhel9/mysql-80
Each -e KEY=VALUE sets an environment variable inside the container. Many official images use environment variables for configuration.
# Run a single command
podman exec web cat /etc/hostname
# Get an interactive shell
podman exec -it web /bin/bash
exec runs a command inside an ALREADY RUNNING container. Unlike podman run, it does not create a new container.
# Show all logs
podman logs web
# Follow logs in real time
podman logs -f web
# Show last 20 lines
podman logs --tail 20 web
Logs show everything the container writes to stdout and stderr. For a web server, this includes access logs and error logs.
# Stop a running container
podman stop web
# Start a stopped container
podman start web
# Remove a stopped container
podman rm web
# Force-remove a running container
podman rm -f web
# Running containers only
podman ps
# All containers (running + stopped)
podman ps -a
You will see:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 registry.access.redhat.com/ubi9/httpd-24:latest /usr/bin/run-httpd 5 minutes ago Up 5 minutes ago 0.0.0.0:8080->80/tcp web
Key columns: STATUS shows if the container is running or exited. PORTS shows port mappings. NAMES is the container name.
podman inspect web gives full details about a running container in JSON format:
podman inspect web --format "{{.State.Status}}"
This returns running, exited, or created. Use --format to extract specific fields instead of reading through the full JSON output.
A container with that name already exists (running or stopped). Remove it first: podman rm web or podman rm -f web
You tried podman exec or podman logs on a stopped container. Start it first: podman start web
Rootless containers cannot bind ports below 1024. Use a higher port: -p 8080:80 instead of -p 80:80
1. Forgetting --name - Without a name, podman generates a random one like "quirky_babbage." On the exam, if a task says "container named web," you must use --name web.
2. Port syntax backwards - -p 8080:80 is HOST:CONTAINER. Getting it reversed means the wrong port is exposed.
3. Not using -d for services - A web server without -d blocks your terminal. You cannot complete other tasks. Always detach long-running containers.
4. Removing without stopping - podman rm web fails if the container is running. Use podman stop web first, or podman rm -f web to force.
Run, manage, and inspect containers. Practice the full lifecycle from creation to removal.
podman run -d --name web registry.access.redhat.com/ubi9/httpd-24
podman ps
Verify the container named "web" is running.
Stop and remove the first container, then re-run with port mapping.
podman rm -f web
podman run -d --name web -p 8080:80 registry.access.redhat.com/ubi9/httpd-24
curl http://localhost:8080
You should see HTML output from the web server.
podman exec web cat /etc/hostname
The hostname inside the container will be the container ID (a short hex string), not the host system hostname.
podman logs web > ~/container-logs.txt
cat ~/container-logs.txt
The log file should contain access log entries from your curl request in Task 2.
podman stop web
podman ps -a
podman rm web
podman ps -a
After removal, podman ps -a should show no container named "web." Run check-progress to confirm all tasks pass.
Reflection: What happens to data written inside a container when you run podman rm? It is gone. Containers are ephemeral by design. To keep data, you need volumes or bind mounts (next lessons).
Practice Running Containers in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.