bootc-base-images/Containerfile

83 lines
3.7 KiB
Docker

# This container build uses some special features of podman that allow
# a process executing as part of a container build to generate a new container
# image "from scratch".
#
# This container build uses nested containerization, so you must build with e.g.
# podman build --security-opt=label=disable --cap-add=all --device /dev/fuse <...>
#
# # Why are we doing this?
#
# Today this base image build process uses rpm-ostree. There is a lot of things that
# rpm-ostree does when generating a container image...but important parts include:
#
# - auto-updating labels in the container metadata
# - Generating "chunked" content-addressed reproducible image layers (notice
# how there are ~60 layers in the generated image)
#
# The latter bit in particular is currently impossible to do from Containerfile.
# A future goal is adding some support for this in a way that can be honored by
# buildah (xref https://github.com/containers/podman/discussions/12605)
#
# # Why does this build process require additional privileges?
#
# Because it's generating a base image and uses containerization features itself.
# In the future some of this can be lifted.
FROM quay.io/fedora/fedora:rawhide as repos
# BOOTSTRAPPING: This can be any image that has rpm-ostree and selinux-policy-targeted.
FROM quay.io/fedora/fedora:41 as builder
RUN dnf -y install rpm-ostree selinux-policy-targeted
ARG MANIFEST=fedora-bootc.yaml
# Copy in the source code
COPY . /src
WORKDIR /src
# Construct the base rootfs
RUN --mount=type=cache,target=/workdir \
--mount=type=bind,from=repos,src=/,dst=/repos <<EORUN
set -xeuo pipefail
# Synchronize the repo files (and RPM gpg keys, and DNF variables) from the "repos" image into our builder rootfs.
for d in /etc/yum.repos.d /etc/pki/rpm-gpg /etc/dnf/vars; do
rm -rf $d
cp -a /repos${d} $d
done
# For legacy reasons we need the .repo files here too in the context directory
cp /etc/yum.repos.d/* .
mkdir /tmp-ostree
ostree --repo=/tmp-ostree init --mode=bare-user
rm /workdir/target-rootfs -rf
rpm-ostree compose install --unified-core --cachedir=/workdir --repo=/tmp-ostree --source-root=/repos ${MANIFEST} /workdir/target-rootfs
EORUN
# Add whatever you want here! e.g.
# FROM quay.io/examplecorp/someartifact:latest as artifacts
# COPY --from=artifacts /usr /usr
# Final steps: postprocess and commit, then generate an OCI archive
RUN --mount=type=cache,target=/workdir --mount=type=bind,rw=true,src=.,dst=/buildcontext,bind-propagation=shared <<EORUN
set -xeuo pipefail
rpm-ostree compose commit --repo=/tmp-ostree --write-commitid-to=/tmp/commit.txt ${MANIFEST} /workdir/target-rootfs/rootfs
rpm-ostree compose container-encapsulate --repo=/tmp-ostree --image-config fedora-bootc-config.json $(cat /tmp/commit.txt) oci-archive:/buildcontext/out.ociarchive
EORUN
# At this point we're done with the builder image and we have our OCI archive.
FROM oci-archive:./out.ociarchive
# We've cargo culted this one around, xref https://pagure.io/fork/cverna/fedora-kiwi-descriptions/c/a12446bbe98404cb4b30d4b07505ecf71a88dfcb
ENV container=oci
# Required for systemd being the default entrypoint
STOPSIGNAL SIGRTMIN+3
# https://containers.github.io/bootc/bootc-images.html#standard-metadata-for-bootc-compatible-images
LABEL containers.bootc 1
# This is our recommended way to link between the base image and
# a tool to make disk images.
LABEL bootc.diskimage-builder quay.io/centos-bootc/bootc-image-builder
# Need to reference builder here to force ordering. But since we have to run
# something anyway, we might as well cleanup after ourselves.
RUN --mount=type=bind,from=builder,src=.,target=/var/tmp \
--mount=type=bind,rw=true,src=.,dst=/buildcontext,bind-propagation=shared \
rm /buildcontext/out.ociarchive