mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-19 02:43:17 +00:00
72 lines
3.2 KiB
Docker
72 lines
3.2 KiB
Docker
# mkosi-builder — the image-build toolchain, pinned and self-contained.
|
|
#
|
|
# Everything a system-image build needs lives here rather than on the CI
|
|
# runner: the runner then needs only Docker, the toolchain cannot drift
|
|
# between runners, and the same build runs identically on a laptop.
|
|
#
|
|
# Debian is the build host regardless of what is being built — mkosi bootstraps
|
|
# the target distribution from its own archive, so an Ubuntu image builds fine
|
|
# from here (see ubuntu-keyring below).
|
|
FROM debian:trixie-slim@sha256:a29215f6a35e51e22adffa17f89e9d2ef06214e64a2bad10d765c46aea49f11f
|
|
|
|
# The runner user is uid 1000; matching it keeps bind-mounted build output
|
|
# owned by the invoking user instead of root.
|
|
ARG BUILDER_UID=1000
|
|
ARG BUILDER_GID=1000
|
|
|
|
# systemd-repart is a separate package on Debian, not part of systemd, and
|
|
# uidmap is only a Recommends — so a --no-install-recommends image has neither
|
|
# unless they are named explicitly. Both are required: repart lays down the
|
|
# partition table offline, and uidmap provides the setuid newuidmap/newgidmap
|
|
# helpers that map mkosi's user namespace.
|
|
#
|
|
# ubuntu-keyring is the cross-distro requirement: apt on a Debian host refuses
|
|
# to verify the Ubuntu archive signature without it.
|
|
#
|
|
# qemu-utils and awscli are for the publish half — qcow2 conversion and the
|
|
# upload to R2 — so build and publish share one toolchain.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends \
|
|
mkosi \
|
|
systemd-repart \
|
|
uidmap \
|
|
ubuntu-keyring \
|
|
debian-archive-keyring \
|
|
qemu-utils \
|
|
awscli \
|
|
ca-certificates \
|
|
curl \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Profiles= is the basis of the composition model and landed in mkosi 24. An
|
|
# older toolchain parses the config and ignores the profile silently, yielding
|
|
# a base image with none of the composed content, so fail at image build time
|
|
# rather than shipping a quietly wrong artefact.
|
|
RUN set -eu; \
|
|
v="$(mkosi --version | grep -oE '[0-9]+' | head -1)"; \
|
|
if [ "${v}" -lt 24 ]; then \
|
|
echo "mkosi ${v} too old — Profiles= requires >= 24" >&2; exit 1; \
|
|
fi
|
|
|
|
# mkosi must not run as root here. As root it sees uid 0, concludes it is
|
|
# privileged, and unshares the mount namespace on its own — which needs real
|
|
# CAP_SYS_ADMIN that a non-privileged container does not have. As an ordinary
|
|
# user it takes the user-namespace path instead and gains CAP_SYS_ADMIN inside
|
|
# that namespace, which is what the sandbox is designed around.
|
|
#
|
|
# The subordinate id ranges are the ids that namespace maps onto. They are set
|
|
# here rather than on the host precisely so no runner has to carry them.
|
|
RUN groupadd -g "${BUILDER_GID}" builder \
|
|
&& useradd -m -u "${BUILDER_UID}" -g "${BUILDER_GID}" builder \
|
|
&& echo "builder:165536:65536" > /etc/subuid \
|
|
&& echo "builder:165536:65536" > /etc/subgid
|
|
|
|
# The cache path must exist in the image, owned by builder, before anything
|
|
# mounts a named volume over it: Docker seeds a fresh volume from the image's
|
|
# directory (ownership included), but creates it empty and root-owned if the
|
|
# path is absent — which mkosi then cannot write to.
|
|
RUN install -d -o builder -g builder -m 0755 /home/builder/.cache
|
|
|
|
USER builder
|
|
WORKDIR /work
|