Chapter 21: Containers with Podman

Building your own image

You rarely run an image exactly as you find it. A Containerfile is a short recipe that starts from a base image and adds your files, so the result is the same on every machine. podman build turns it into a new local image.

The recipe

A Containerfile: Select an instruction.

The simplest useful image puts a web page inside the web server image. In a directory ~/portal create the page and the recipe:

[student@servera ~]$ mkdir -p ~/portal && cd ~/portal
[student@servera portal]$ echo "Portal is up" > index.html
[student@servera portal]$ cat > Containerfile <<'EOT'
FROM registry.access.redhat.com/ubi9/httpd-24:latest
COPY index.html /var/www/html/index.html
EOT

Build and run

From files to an image: Step through podman build.

[student@servera portal]$ podman build -t localhost/portal:1 .
STEP 1/2: FROM registry.access.redhat.com/ubi9/httpd-24:latest
STEP 2/2: COPY index.html /var/www/html/index.html
COMMIT localhost/portal:1
--> 49203ad043a3
Successfully tagged localhost/portal:1
49203ad043a3e208fce8ed4aeb3ff117a24e0cd63f212dd89e3aac708edab38c
[student@servera portal]$ podman run -d --name portal -p 8080:8080 localhost/portal:1
[student@servera portal]$ curl -s localhost:8080
Portal is up

-t names and tags the image; the . is the build context, the directory whose files COPY may use. The page is part of the image now: there is no volume, and every container from this image shows the same page.

[student@servera portal]$ podman history localhost/portal:1 | head -3 | cut -c1-90
ID            CREATED                 CREATED BY                                     SIZE
cf1e25990315  Less than a second ago  /bin/sh -c #(nop) COPY file:702c4212… in /var/www/html/index.html  2.56kB

Each instruction is a layer; the small COPY layer sits on top of the large base image, so the new image costs almost no extra disk space.

Good habits

[student@servera portal]$ podman rm -f -t 1 portal
portal
[student@servera portal]$ podman images --format "{{.Repository}}:{{.Tag}} {{.Size}}"
localhost/portal:1 310 MB
registry.access.redhat.com/ubi9/httpd-24:latest 310 MB

Both lines show the same size because they share the base layers. (Stopping this web image waits ten seconds for a polite exit; -t 1 shortens that.)

Try it

Check your understanding