Skip to content

Podman - Containerfile a brief rundown - Part 9

Difficult Level:
1
2
3
4
5

A containerfile, what is it, what can it do and what purpose do it serve?, those are some of the things we will talk about in this part.

What is it

A containerfile is file with a set of instructions given to podman or other container software to build an image ready for distribution or usage in your own environment, these are then the images we download when creating our own containers.

Not to confuse with bildah that is more aimed at creating pure OCI container images with or without additional software. it does not run any containers, podman / docker creates container images based on both the OCI images made with bildah and often additional software and has the purpose of running containers.

Container file

As said above containerfile is a text file with a set of instruction on how to build a new image, you can add files, install software and so on into your own image to make it the way you want it.

A basic containerfile can look like this, here we build an iPerf speed test image.

# syntax=docker/dockerfile:1
## Labels
LABEL com.example.image.authors="me@example.com"
LABEL com.example.version="1.0"
LABEL com.example.release-date="2023-09-14"
## Build image
FROM opensuse/leap:latest
RUN zypper -n update
## install iPerf
RUN zypper --non-interactive install iperf
RUN zypper clean --all
## Copy file
COPY info.txt /
## Ports to open
EXPOSE 5201/tcp
EXPOSE 5201/udp
## Set user to run as
USER 1001
## Startup script
CMD /usr/bin/iperf3 -s

As you can see there are some command like LABEL, FROM, RUN and so on above, these are all part of a set of commands used to tell podman or other image building software what to do. They are all done from the top down in order to create a complete image ready for distribution and usage.

Container options

Each command in a containerfile serves it's purpose, and here we will talk a little more about some of them.

As you can see they are all uppercase, instructions are not case-sensitive, but the convention is to use upper case. This improves readability by differentiating between the Instruction call and instruction operation

LABEL

LABEL com.example.image.authors="me@example.com"
LABEL com.example.version="1.0"
LABEL com.example.release-date="2023-09-14"

A way to assign labels to the built image telling others who made it, version of it and so on. These three i usually use when labeling my images.

Where com.example would be replaced with your information, and add your values within the "".

To see more label options you can head over to OCI GitHub page here.

FROM

FROM opensuse/leap:latest

This defines what base operating system image to use when building your own image, in above example i used openSUSE Leap with the latest tag.

RUN

RUN zypper -n update
RUN zypper --non-interactive install iperf
RUN zypper clean --all

This executes given commands inside the image that your build, like above i updated package information, then installed iPerf package and finally cleaned up any leftover installation temp files.

EXPOSE

EXPOSE 5201/tcp
EXPOSE 5201/udp

This tells whoever that will be using your image that these ports needs to be open to be able to access the service within, this is not a requirement but a good practice to use.

USER

USER 1001

This sets what user to run the image as, here i set 1001 which is the root user and default on most images, that is not good practice and should be used as little as possible, better to create a user in the container and run the service as that user instead.

By leaving this one out the default user will be whatever the base image has been built with, most probably root.

COPY

COPY info.txt /

With this you can copy files into the container during build, put the files in the same folder or sub-folder as the containerfile file, the format is like this, COPY file.txt /path/inside/image/

CMD

CMD /usr/bin/iperf3 -s

This tells the image what to actually start and run when the image is connected to a container, this one should always be last in the containerfile.

Building

When building or creating an image we use the above file and run podman like this.

$ podman build --file ./Containerfile --tag iperf
STEP 1/8: FROM opensuse/leap:latest
STEP 2/8: RUN zypper -n update
Retrieving repository 'Update repository of openSUSE Backports' metadata [......done]
...

This will build an image for us with iperf ready to run, if you would like to try this remove the COPY step from the containerfile above, it's not needed.

Note that under --tag i only wrote iperf, normally you would put a complete repository path here so we can push it when we validated that the image works.

Check your image list and you will see what full name and tag it got and see what the openSUSE image has that was used as a base image for our own image.

$ iPerf_Server> podman image list
REPOSITORY                 TAG       IMAGE ID      CREATED         SIZE
localhost/iperf            latest    6d36c5ee1015  2 minutes ago   313 MB
docker.io/opensuse/leap    latest    f66ef03c6e85  6 weeks ago     116 MB

Here you see that our image has localhost/iperf as repository while openSUSE has docker.io/opensuse/leap and both has the latest tag, we wrote iperf as --tag name didn't we?, well yes but it takes what we wrote as part of the repository name, above is fine while doing test builds locally before creating our final image.

When building your final image the tag name would be something like this, where the path would be to your repository.

$ podman build --file ./containerfile --tag docker.io/reponame/iperf:latest

The tag do not need to be latest, if you have a special version you can write that, like this...

$ podman build --file ./containerfile --tag docker.io/reponame/iperf:3.1.1

And that would render something like this when listing images, and localhost would be replaced.

$ iPerf_Server> podman image list
REPOSITORY                 TAG       IMAGE ID      CREATED         SIZE
docker.io/reponame/iperf   3.1.1     6d36c5ee1015  2 minutes ago   313 MB
docker.io/opensuse/leap    latest    f66ef03c6e85  6 weeks ago     116 MB

Recap

We briefly talked about how a basic containerfile might look like when creating your own container images, this just scratches the surface on the concept of containerfile used to build images, there are much more options to use in a containerfile than the ones i touched on above.

Think i need to do a separate how-to just for that in the future.