Containerfile
| 1 | # The build VM image. Hearthforge starts one container of it per build_image |
| 2 | # step. The container runs QEMU, and the VM inside runs buildah. See CI.md. |
| 3 | # Hearthforge embeds this directory and builds the image on first use with |
| 4 | # the engine's classic build API, so it must not need BuildKit. |
| 5 | |
| 6 | ARG ALPINE=docker.io/library/alpine:3.24 |
| 7 | |
| 8 | # The system that boots inside the VM. |
| 9 | FROM ${ALPINE} AS guest |
| 10 | RUN apk add --no-cache buildah crun netavark e2fsprogs tar ca-certificates |
| 11 | COPY guest/ / |
| 12 | # The embedded copy loses file modes. |
| 13 | RUN chmod 755 /init |
| 14 | |
| 15 | # --no-scripts skips the mkinitfs trigger. Its initramfs is not used. |
| 16 | FROM ${ALPINE} AS kernel |
| 17 | RUN apk add --no-cache --no-scripts linux-virt kmod |
| 18 | # Modules are stored uncompressed and numbered in load order, so the guest |
| 19 | # init needs only busybox insmod. |
| 20 | RUN set -eu; \ |
| 21 | kver=$(ls /lib/modules); \ |
| 22 | mkdir -p /out/modules; \ |
| 23 | for m in virtio_blk virtio_net ext4 overlay virtio_rng; do \ |
| 24 | modprobe -S "$kver" --show-depends "$m"; \ |
| 25 | done | awk '$1 == "insmod" && !seen[$2]++ { print $2 }' > /tmp/modules; \ |
| 26 | i=0; \ |
| 27 | while read -r ko; do \ |
| 28 | i=$((i + 1)); \ |
| 29 | gunzip -c "$ko" > "/out/modules/$(printf %02d $i)-$(basename "$ko" .gz)"; \ |
| 30 | done < /tmp/modules; \ |
| 31 | cp /boot/vmlinuz-virt /out/vmlinuz |
| 32 | |
| 33 | FROM ${ALPINE} AS initramfs |
| 34 | RUN apk add --no-cache cpio |
| 35 | COPY --from=guest / /rootfs/ |
| 36 | COPY --from=kernel /out/modules/ /rootfs/lib/hf-modules/ |
| 37 | RUN set -eu; \ |
| 38 | cd /rootfs; \ |
| 39 | mkdir -p proc sys dev tmp run var/lib/containers; \ |
| 40 | find . -print0 | cpio --null --quiet -o -H newc | gzip -1 > /initramfs.gz |
| 41 | |
| 42 | FROM ${ALPINE} |
| 43 | RUN apk add --no-cache "qemu-system-$(apk --print-arch)" tar |
| 44 | COPY --from=kernel /out/vmlinuz /vm/vmlinuz |
| 45 | COPY --from=initramfs /initramfs.gz /vm/initramfs.gz |
| 46 | COPY run-vm /usr/local/bin/run-vm |
| 47 | RUN chmod 755 /usr/local/bin/run-vm && mkdir -p /in/context /out /work |
| 48 | ENTRYPOINT ["/usr/local/bin/run-vm"] |
| 49 |