How to build Fedora container images

With the rise of containers and container technology, all major Linux distributions nowadays provide a container base image. This article presents how the Fedora project builds its base image. It also shows you how to use it to create a layered image.

Base and layered images

Before we look at how the Fedora container base image is built, let’s define a base image and a layered image. A simple way to define a base image is an image that has no parent layer. But what does that concretely mean? It means a base image usually contains only the root file system (rootfs) of an operating system. The base image generally provides the tools needed to install software in order to create layered images.

A layered image adds a collections of layers on top of the base image in order to install, configure, and run an application. Layered images reference base images in a Dockerfile using the FROM instruction:

FROM fedora:latest

How to build a base image

Fedora has a full suite of tools available to build container images. This includes podman, which does not require running as the root user.

Building a rootfs

A base image comprises mainly a tarball. This tarball contains a rootfs. There are different ways to build this rootfs. The Fedora project uses the kickstart installation method coupled with imagefactory software to create these tarballs.

The kickstart file used during the creation of the Fedora base image is available in Fedora’s build system Koji. The Fedora-Container-Base package regroups all the base image builds. If you select a build, it gives you access to all the related artifacts, including the kickstart files. Looking at an example, the %packages section at the end of the file defines all the packages to install. This is how you make software available in the base image.

Using a rootfs to build a base image

Building a base image is easy, once a rootfs is available. It requires only a Dockerfile with the following instructions:

FROM scratch
ADD layer.tar /
CMD ["/bin/bash"]

The important part here is the FROM scratch instruction, which is creating an empty image. The following instructions then add the rootfs to the image, and set the default command to be executed when the image is run.

Let’s build a base image using a Fedora rootfs built in Koji:

$ curl -o fedora-rootfs.tar.xz https://kojipkgs.fedoraproject.org/packages/Fedora-Container-Base/Rawhide/20190902.n.0/images/Fedora-Container-Base-Rawhide-20190902.n.0.x86_64.tar.xz
$ tar -xJvf fedora-rootfs.tar.xz 51c14619f9dfd8bf109ab021b3113ac598aec88870219ff457ba07bc29f5e6a2/layer.tar 
$ mv 51c14619f9dfd8bf109ab021b3113ac598aec88870219ff457ba07bc29f5e6a2/layer.tar layer.tar
$ printf "FROM scratch\nADD layer.tar /\nCMD [\"/bin/bash\"]" > Dockerfile
$ podman build -t my-fedora .
$ podman run -it --rm my-fedora cat /etc/os-release

The layer.tar file which contains the rootfs needs to be extracted from the downloaded archive. This is only needed because Fedora generates images that are ready to be consumed by a container run-time.

So using Fedora’s generated image, it’s even easier to get a base image. Let’s see how that works:

$ curl -O https://kojipkgs.fedoraproject.org/packages/Fedora-Container-Base/Rawhide/20190902.n.0/images/Fedora-Container-Base-Rawhide-20190902.n.0.x86_64.tar.xz
$ podman load --input Fedora-Container-Base-Rawhide-20190902.n.0.x86_64.tar.xz
$ podman run -it --rm localhost/fedora-container-base-rawhide-20190902.n.0.x86_64:latest cat /etc/os-release

Building a layered image

To build a layered image that uses the Fedora base image, you only need to specify fedora in the FROM line instruction:

FROM fedora:latest

The latest tag references the latest active Fedora release (Fedora 30 at the time of writing). But it is possible to get other versions using the image tag. For example, FROM fedora:31 will use the Fedora 31 base image.

Fedora supports building and releasing software as containers. This means you can maintain a Dockerfile to make your software available to others. For more information about becoming a container image maintainer in Fedora, check out the Fedora Containers Guidelines.

Fedora Project community

11 Comments

  1. Sandra

    Have it been considered to write an article “docker-compose the podman way”?

    According to this article and podman docs, there will never be an official podman-compose, so it would be very useful to get an article on how to migrate away from docker-compose.

    https://mkdev.me/en/posts/dockerless-part-3-moving-development-environment-to-containers-with-podman

    • @Sandra I think that this would be a great article. Would you be interested in writing it ? In case you are I ll point you to the documentation on how to start contributing 🙂 https://docs.fedoraproject.org/en-US/fedora-magazine/contributing/

    • 0xSheepdog

      That would be amazing. One of my biggest frustrations trying to learn “the container way” without drinking the docker kool-aid is nearly everything is offered as a docker container/cluster with docker-compose. I feel like i have to learn a LOT of docker just so I can understand how to do containers WITHOUT docker.

    • Blaise

      Yes!!!
      Or maybe using ansible to direct the compose settings to podman?

    • Raphael G

      Thanks for sharing the link. It’s a nice one!

  2. Osqui

    Why not talking about mkosi? It’s another beast but using it with systemd-nspawn is a charm. Thanks

  3. Ph0zzy

    What about:

    #!/bin/bash

    #
    # Generate minimal container image
    #

    set -ex

    # start new container from scratch
    newcontainer=$(buildah from scratch)
    scratchmnt=$(buildah mount ${newcontainer})

    # install the packages
    dnf install --installroot ${scratchmnt} bash coreutils --releasever 30 --setopt=tsflags=nodocs --setopt=override_install_langs=en_US.utf8 -y

    # Clean up dnf cache
    if [ -d "${scratchmnt}" ]; then
      rm -rf "${scratchmnt}"/var/cache/dnf
    fi

    # configure container label and entrypoint
    buildah config --label name=f30-minimal ${newcontainer}
    buildah config --cmd /bin/bash ${newcontainer}

    # commit the image
    buildah unmount ${newcontainer}
    buildah commit ${newcontainer} f30-minimal

    ?

  4. Bill

    Has any thought been given to using a 64 bit base image and adding an image of a current install as a layer to convert from 32-bit to 64 bit Fedora?

  5. Raphael Groner

    What about Foreman or SaltStack? There’s definitely a comparison need. Although, I don’t intend to start a flamewar about features.

  6. Mohnish

    Nice suggestions everyone, thanks. Please take the lead in writing a write-up/follow-up for future edition.

Comments are Closed

The opinions expressed on this website are those of each author, not of the author's employer or of Red Hat. Fedora Magazine aspires to publish all content under a Creative Commons license but may not be able to do so in all cases. You are responsible for ensuring that you have the necessary permission to reuse any work on this site. The Fedora logo is a trademark of Red Hat, Inc. Terms and Conditions