Skip to content

Expert · Boot, recovery and containers · topic 42 of 57 · 35 min

Containers with Podman: images, run, ports and logs

Explanation

A container runs an application with everything it needs, isolated from the rest of the system but sharing the host's kernel. Podman is RHEL's container tool; it needs no background daemon and can run containers as a normal user. You pull images from registries, run them with podman run, publish ports with -p, and inspect them with ps, logs and exec.

Containers and virtual machines

A virtual machine simulates a whole computer, with its own kernel. A container is just a group of normal processes on the host, but the kernel gives them their own view of files, network, process list and users (namespaces) and limits their resources (cgroups). Containers start in a second and use far less memory, which is why apps are now often shipped as container images.

Think of it like this: Virtual machines are separate houses, each with its own foundation, water tank and electricity meter. Containers are flats in one building: they share the foundation and the main water line (the kernel), but each flat has its own lock, rooms and meter. Building a new flat is much faster than a new house.

Images, containers and registries

  • Image: a read-only package with an application and its files, built in layers. Like a template.
  • Container: a running (or stopped) instance of an image, with a thin writable layer on top.
  • Registry: a server that stores images, such as registry.access.redhat.com (Red Hat's public images), registry.redhat.io (needs a Red Hat login) or quay.io.
  • Image name: registry/namespace/name:tag, for example registry.access.redhat.com/ubi9/httpd-24:latest. The tag picks a version; if you leave it out, latest is used.

UBI (Universal Base Image) images are RHEL-based images that Red Hat lets anyone use and redistribute, a good base for your own containers.

First container

bash
$ sudo dnf install -y container-tools        # podman, skopeo, buildah
$ podman search httpd-24 --limit 3
$ podman pull registry.access.redhat.com/ubi9/httpd-24
$ podman images
REPOSITORY                                  TAG     IMAGE ID      CREATED      SIZE
registry.access.redhat.com/ubi9/httpd-24    latest  2b6f1c7e8d9a  2 weeks ago  387 MB
$ podman run -d --name web -p 8080:8080 registry.access.redhat.com/ubi9/httpd-24
5c1e9f0a7b...
$ podman ps
CONTAINER ID  IMAGE                                            COMMAND               CREATED        STATUS        PORTS                   NAMES
5c1e9f0a7b2d  registry.access.redhat.com/ubi9/httpd-24:latest  /usr/bin/run-http...  5 seconds ago  Up 5 seconds  0.0.0.0:8080->8080/tcp  web
$ curl -s localhost:8080 | head -1
<!DOCTYPE html>
-d runs it in the background (detached); --name gives it a name; -p HOST:CONTAINER publishes a port.

Everyday commands

bash
$ podman logs web              # the container's output (add -f to follow)
$ podman exec -it web /bin/bash   # a shell inside the running container
$ podman inspect web | grep -i ipaddress
$ podman stop web; podman start web
$ podman rm web                # remove a stopped container (-f to force a running one)
$ podman rmi registry.access.redhat.com/ubi9/httpd-24   # remove the image
$ podman run --rm -it registry.access.redhat.com/ubi9/ubi cat /etc/redhat-release
Red Hat Enterprise Linux release 9.4 (Plow)
--rm deletes the container when it exits; -it gives an interactive terminal.

Many images are configured with environment variables, passed with -e. For example a MariaDB image needs a root password and a database name: podman run -d --name db -e MYSQL_ROOT_PASSWORD=... -e MYSQL_DATABASE=shop -p 3306:3306 registry.redhat.io/rhel9/mariadb-105. The image's documentation lists its variables.

Rootless by default

When a normal user runs podman, the containers are rootless: they run with that user's rights on the host, even if the program inside thinks it is root. A break-out from the container gets only that user's access. Each user has their own images and containers (stored in ~/.local/share/containers). Rootless containers cannot publish host ports below 1024 by default, which is why the example uses 8080, not 80.

Common mistakes

  • Using -p 8080 alone, or swapping the order. The format is -p HOST_PORT:CONTAINER_PORT.
  • Expecting data written inside a container to survive podman rm. The container's own layer is deleted with it; use volumes (next lesson).
  • Running podman with sudo and then looking for the container as a normal user, or the reverse: root and each user see different containers.
  • Forgetting the host firewall when others must reach the published port.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Containers with Podman: images, run, ports and logs · 1/6

VM = own kernel container = shared kernel

A container is a group of processes with its own view of files and network, sharing the host kernel.

Prefer a video by a teacher? Find free videos on “podman tutorial rhel 9 run container ports beginners” on YouTube ↗

In real life: Same app, every environment, at a Pune SaaS company

A Pune SaaS team used to fight "works on my machine" bugs between developer laptops, test and production. They now build one container image per release and push it to their registry. The test server and the production RHEL servers run exactly the same image with podman, only with different environment variables. Rolling back a bad release means running the previous image tag.

bash
$ podman run -d --name api -p 8443:8443 -e APP_ENV=production registry.example.com/billing/api:2.7.1
$ podman ps --format "{{.Names}} {{.Image}} {{.Status}}"
api registry.example.com/billing/api:2.7.1 Up 3 hours

Practice (0/3 done)

Task 1 · Question

In "podman run -d -p 8080:80 nginx", which is the port on the HOST?

Task 2 · Code · Python

Write parse_image(ref) that splits a container image reference into a dict with registry, path and tag. Rules: the tag is after the last ":" only if that colon comes after the last "/"; otherwise the tag is "latest". The registry is the first part before "/" if it contains a "." or ":" or is "localhost"; otherwise the registry is "" (unqualified). path is the rest. Example: "registry.access.redhat.com/ubi9/httpd-24:1-300" → {"registry": "registry.access.redhat.com", "path": "ubi9/httpd-24", "tag": "1-300"}.

Task 3 · Practice

As a normal user, run the UBI httpd image published on port 8080, change its home page from inside the container, check the logs, then stop and remove it.

Quick quiz

Question 1

1.What do containers share with the host that virtual machines do not?

Question 2

2.Which command shows running containers?

Question 3

3.Which tag is used if you do not give one?

Question 4

4.Why can't a rootless container publish host port 80 by default?

Question 5

5.What does podman exec -it web /bin/bash do?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What do containers share with the host that virtual machines do not?

Answer: The kernel

Containers run on the host kernel.

Which command shows running containers?

Answer: podman ps

podman ps (add -a for stopped ones too).

Which tag is used if you do not give one?

Answer: latest

latest is the default tag.

Why can't a rootless container publish host port 80 by default?

Answer: Ports below 1024 need root privileges

Unprivileged users cannot bind low ports by default.

What does podman exec -it web /bin/bash do?

Answer: Opens a shell inside the running container web

exec runs a command in a running container.

Why does a container start much faster than a virtual machine?Related

Answer: It does not boot an operating system kernel; it is just an isolated process

The host kernel is already running, so starting a container is close to starting a process.

From Containers, images and registries

What is Google Cloud's current registry for container images?Related

Answer: Artifact Registry

Artifact Registry replaced Container Registry.

From Containers, images and registries

What happens to files written inside a container (not in a volume) after podman rm?Related

Answer: They are deleted with the container

The container layer is removed.

From Persistent storage and containers as systemd services

Two containers are on the default bridge network. Why can the api container not reach the database at the host name db?Related

Answer: The default bridge network has no DNS by container name; use a user-defined network

User-defined bridge networks provide name resolution; the default bridge does not.

From Running containers: ports, volumes, networks and limits

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Boot, recovery and containers” before its exam: Persistent storage and containers as systemd services.
  2. Module 8 exam: Boot, recovery and containers · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Ansible fundamentals. 57 topics left in the course before the final exam.

← Previous: Recovering a lost root password