Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Mar 2025 15:17:49 GMT
From:      Doug Rabson <dfr@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: e8a5b9fd73f4 - main - release: build OCI images with shell scripts
Message-ID:  <202503021517.522FHnWk009616@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by dfr:

URL: https://cgit.FreeBSD.org/src/commit/?id=e8a5b9fd73f4f437a03c85e7644daa55652e224b

commit e8a5b9fd73f4f437a03c85e7644daa55652e224b
Author:     Doug Rabson <dfr@FreeBSD.org>
AuthorDate: 2024-12-12 16:42:00 +0000
Commit:     Doug Rabson <dfr@FreeBSD.org>
CommitDate: 2025-03-02 15:17:13 +0000

    release: build OCI images with shell scripts
    
    This avoids the need for buildah and skopeo for building releases.
    
    Reviewed by:            cpersiva
    MFC after:              1 day
    Differential Revision:  https://reviews.freebsd.org/D48574
---
 release/Makefile.oci                 |   6 +-
 release/release.sh                   |  38 -------------
 release/scripts/make-oci-image.sh    | 105 +++++++++++++++++++++++++++++++----
 release/tools/oci-image-dynamic.conf |   2 +-
 release/tools/oci-image-minimal.conf |   3 +-
 release/tools/oci-image-static.conf  |   3 +-
 6 files changed, 99 insertions(+), 58 deletions(-)

diff --git a/release/Makefile.oci b/release/Makefile.oci
index da35156c5a95..e4b5df580055 100644
--- a/release/Makefile.oci
+++ b/release/Makefile.oci
@@ -26,11 +26,7 @@ OCI_TARGETS+= container-image-${_IMG}.txz
 container-image-${_IMG}.txz: ${OCI_DEPS_${_IMG}}
 	# Adjust PATH so that we run pwd_mkdb from the bootstrap tools
 	env PATH=${OBJTOP}/tmp/legacy/bin:${PATH:Q} \
-	sh ${.CURDIR}/scripts/make-oci-image.sh ${.CURDIR} ${REVISION} ${BRANCH} ${TARGET_ARCH} ${_IMG}
-	skopeo copy \
-		containers-storage:localhost/freebsd${REVISION:R}-${_IMG}:latest \
-		oci-archive:${.OBJDIR}/container-image-${_IMG}.tar:freebsd${REVISION:R}-${_IMG}:${REVISION}-${BRANCH}-${TARGET_ARCH}
-	${XZ_CMD} < ${.OBJDIR}/container-image-${_IMG}.tar > ${.OBJDIR}/container-image-${_IMG}.txz
+	sh ${.CURDIR}/scripts/make-oci-image.sh ${.CURDIR} ${REVISION} ${BRANCH} ${TARGET_ARCH} ${_IMG} container-image-${_IMG}.txz
 .endfor
 
 oci-release: ${OCI_TARGETS}
diff --git a/release/release.sh b/release/release.sh
index d6752e016994..5a6de297f7a1 100755
--- a/release/release.sh
+++ b/release/release.sh
@@ -292,44 +292,6 @@ extra_chroot_setup() {
 		fi
 	fi
 
-	if [ ! -z "${WITH_OCIIMAGES}" ]; then
-		# Install buildah and skopeo from ports if the ports tree is available;
-		# otherwise install the pkg.
-		if [ -d ${CHROOTDIR}/usr/ports ]; then
-			# Trick the ports 'run-autotools-fixup' target to do the right
-			# thing.
-			_OSVERSION=$(chroot ${CHROOTDIR} /usr/bin/uname -U)
-			REVISION=$(chroot ${CHROOTDIR} make -C /usr/src/release -V REVISION)
-			BRANCH=$(chroot ${CHROOTDIR} make -C /usr/src/release -V BRANCH)
-			UNAME_r=${REVISION}-${BRANCH}
-			GITUNSETOPTS="CONTRIB CURL CVS GITWEB GUI HTMLDOCS"
-			GITUNSETOPTS="${GITUNSETOPTS} ICONV NLS P4 PERL"
-			GITUNSETOPTS="${GITUNSETOPTS} SEND_EMAIL SUBTREE SVN"
-			GITUNSETOPTS="${GITUNSETOPTS} PCRE PCRE2"
-			PBUILD_FLAGS="OSVERSION=${_OSVERSION} BATCH=yes"
-			PBUILD_FLAGS="${PBUILD_FLAGS} UNAME_r=${UNAME_r}"
-			PBUILD_FLAGS="${PBUILD_FLAGS} OSREL=${REVISION}"
-			PBUILD_FLAGS="${PBUILD_FLAGS} WRKDIRPREFIX=/tmp/ports"
-			PBUILD_FLAGS="${PBUILD_FLAGS} DISTDIR=/tmp/distfiles"
-			for _PORT in sysutils/buildah sysutils/skopeo; do
-				eval chroot ${CHROOTDIR} env ${PBUILD_FLAGS} make -C \
-				     /usr/ports/${_PORT} \
-				     FORCE_PKG_REGISTER=1 deinstall install clean distclean
-			done
-		else
-			eval chroot ${CHROOTDIR} env ASSUME_ALWAYS_YES=yes \
-				pkg install -y sysutils/buildah sysutils/skopeo
-			eval chroot ${CHROOTDIR} env ASSUME_ALWAYS_YES=yes \
-				pkg clean -y
-		fi
-		# Use the vfs storage driver so that this works whether or not
-		# the build directory is on ZFS. The images are small so the
-		# performance difference is negligible.
-		eval chroot ${CHROOTDIR} sed -I .bak -e '/^driver/s/zfs/vfs/' /usr/local/etc/containers/storage.conf
-		# Remove any stray images from previous builds
-		eval chroot ${CHROOTDIR} buildah rmi -af
-	fi
-
 	if [ ! -z "${EMBEDDEDPORTS}" ]; then
 		_OSVERSION=$(chroot ${CHROOTDIR} /usr/bin/uname -U)
 		REVISION=$(chroot ${CHROOTDIR} make -C /usr/src/release -V REVISION)
diff --git a/release/scripts/make-oci-image.sh b/release/scripts/make-oci-image.sh
index 6180ed9d53b4..0fd64602b403 100644
--- a/release/scripts/make-oci-image.sh
+++ b/release/scripts/make-oci-image.sh
@@ -7,21 +7,23 @@ rev=$1; shift
 branch=$1; shift
 arch=$1; shift
 image=$1; shift
+output=$1; shift
 
 major=${rev%.*}
 minor=${rev#*.}
 
 abi=FreeBSD:${major}:${arch}
+ver=${rev}-${branch}-${arch}
 
 echo "Building OCI freebsd${major}-${image} image for ${abi}"
 
 . ${curdir}/tools/oci-image-${image}.conf
 
-init_workdir() {
+init_repo() {
+	local workdir=$1; shift
 	local abi=$1; shift
-	local workdir=$(mktemp -d -t oci-images)
 
-	mkdir ${workdir}/repos
+	mkdir -p ${workdir}/repos
 	cat > ${workdir}/repos/base.conf <<EOF
 FreeBSD-base: {
   url: "file:///usr/obj/usr/src/repo/${abi}/latest"
@@ -30,13 +32,13 @@ FreeBSD-base: {
 }
 EOF
 	cp /etc/pkg/FreeBSD.conf ${workdir}/repos
-	echo ${workdir}
 }
 
+# Install packages using pkg(8) into a container with rootfs at $3
 install_packages() {
 	local abi=$1; shift
 	local workdir=$1; shift
-	local rootdir=$1; shift
+	local rootdir=${workdir}/rootfs
 	if [ ! -d ${rootdir}/usr/share/keys/pkg/trusted ]; then
 		mkdir -p ${rootdir}/usr/share/keys/pkg/trusted
 	fi
@@ -49,15 +51,94 @@ install_packages() {
 	rm -rf ${rootdir}/var/db/pkg/repos
 }
 
-workdir=$(init_workdir ${abi})
+set_cmd() {
+	local workdir=$1; shift
+	oci_cmd="$@"
+}
+
+# Convert FreeBSD architecture to OCI-style. See
+# https://github.com/containerd/platforms/blob/main/platforms.go for details
+normalize_arch() {
+	local arch=$1; shift
+	case ${arch} in
+		i386)
+		       arch=386
+		       ;;
+		aarch64)
+		       arch=arm64
+		       ;;
+		amd64) ;;
+		riscv64) ;;
+		*)
+			echo "Architecture ${arch} not supported for container images"
+			;;
+	esac
+	echo ${arch}
+}
+
+create_container() {
+	local workdir=$1; shift
+	local base_workdir=$1; shift
+	oci_cmd=
+	if [ -d ${workdir}/rootfs ]; then
+		chflags -R 0 ${workdir}/rootfs
+		rm -rf ${workdir}/rootfs
+	fi
+	mkdir -p ${workdir}/rootfs
+	if [ "${base_workdir}" != "" ]; then
+		tar -C ${workdir}/rootfs -xf ${base_workdir}/rootfs.tar.gz
+	fi
+}
+
+commit_container() {
+	local workdir=$1; shift
+	local image=$1; shift
+	local output=$1; shift
+
+	# Note: the diff_id (needed for image config) is the hash of the uncompressed tar
+	tar -C ${workdir}/rootfs --strip-components 1 -cf ${workdir}/rootfs.tar .
+	local diff_id=$(sha256 -q < ${workdir}/rootfs.tar)
+	gzip -f ${workdir}/rootfs.tar
+	local create_time=$(date -u +%Y-%m-%dT%TZ)
+	local root_hash=$(sha256 -q < ${workdir}/rootfs.tar.gz)
+	local root_size=$(stat -f %z ${workdir}/rootfs.tar.gz)
+
+	oci_arch=$(normalize_arch ${arch})
+
+	config=
+	if [ -n "${oci_cmd}" ]; then
+		config=",\"config\":{\"cmd\":[\"${oci_cmd}\"]}"
+	fi
+	echo "{\"created\":\"${create_time}\",\"architecture\":\"${oci_arch}\",\"os\":\"freebsd\"${config},\"rootfs\":{\"type\":\"layers\",\"diff_ids\":[\"sha256:${diff_id}\"]},\"history\":[{\"created\":\"${create_time}\",\"created_by\":\"make-oci-image.sh\"}]}" > ${workdir}/config.json
+	local config_hash=$(sha256 -q < ${workdir}/config.json)
+	local config_size=$(stat -f %z ${workdir}/config.json)
+
+	echo "{\"schemaVersion\":2,\"mediaType\":\"application/vnd.oci.image.manifest.v1+json\",\"config\":{\"mediaType\":\"application/vnd.oci.image.config.v1+json\",\"digest\":\"sha256:${config_hash}\",\"size\":${config_size}},\"layers\":[{\"mediaType\":\"application/vnd.oci.image.layer.v1.tar+gzip\",\"digest\":\"sha256:${root_hash}\",\"size\":${root_size}}],\"annotations\":{}}" > ${workdir}/manifest.json
+	local manifest_hash=$(sha256 -q < ${workdir}/manifest.json)
+	local manifest_size=$(stat -f %z ${workdir}/manifest.json)
+
+	mkdir -p ${workdir}/oci/blobs/sha256
+	echo "{\"imageLayoutVersion\": \"1.0.0\"}" > ${workdir}/oci/oci-layout
+	echo "{\"schemaVersion\":2,\"manifests\":[{\"mediaType\":\"application/vnd.oci.image.manifest.v1+json\",\"digest\":\"sha256:${manifest_hash}\",\"size\":${manifest_size},\"annotations\":{\"org.opencontainers.image.ref.name\":\"freebsd-${image}:${ver}\"}}]}" > ${workdir}/oci/index.json
+	ln ${workdir}/rootfs.tar.gz ${workdir}/oci/blobs/sha256/${root_hash}
+	ln ${workdir}/config.json ${workdir}/oci/blobs/sha256/${config_hash}
+	ln ${workdir}/manifest.json ${workdir}/oci/blobs/sha256/${manifest_hash}
+
+	tar -C ${workdir}/oci --xz --strip-components 1 --no-read-sparse -a -cf ${output} .
+}
+
+# Prefix with "container-image-" so that we can create a unique work area under
+# ${.OBJDIR}. We can assume that make has set our working directory to
+# ${.OBJDIR}.
+workdir=${PWD}/container-image-${image}
+init_repo ${workdir} ${abi}
+
 if [ -n "${OCI_BASE_IMAGE}" ]; then
-	base_image=freebsd${major}-${OCI_BASE_IMAGE}
+	base_workdir=${PWD}/container-image-${OCI_BASE_IMAGE}
 else
-	base_image=scratch
+	base_workdir=
 fi
 
-c=$(buildah from --arch ${arch} ${base_image})
-m=$(buildah mount $c)
+create_container ${workdir} ${base_workdir}
 oci_image_build
-buildah unmount $c
-buildah commit --rm $c freebsd${major}-${image}:latest
+commit_container ${workdir} ${image} ${output}
diff --git a/release/tools/oci-image-dynamic.conf b/release/tools/oci-image-dynamic.conf
index b146ff2cf7c3..61cb90187764 100644
--- a/release/tools/oci-image-dynamic.conf
+++ b/release/tools/oci-image-dynamic.conf
@@ -7,5 +7,5 @@
 OCI_BASE_IMAGE=static
 
 oci_image_build() {
-	install_packages ${abi} ${workdir} $m FreeBSD-clibs FreeBSD-openssl-lib
+	install_packages ${abi} ${workdir} FreeBSD-clibs FreeBSD-openssl-lib
 }
diff --git a/release/tools/oci-image-minimal.conf b/release/tools/oci-image-minimal.conf
index 82e2ce6a1bd3..93aad1e39250 100644
--- a/release/tools/oci-image-minimal.conf
+++ b/release/tools/oci-image-minimal.conf
@@ -8,7 +8,8 @@
 OCI_BASE_IMAGE=dynamic
 
 oci_image_build() {
-	install_packages ${abi} ${workdir} $m \
+	set_cmd ${workdir} /bin/sh
+	install_packages ${abi} ${workdir} \
 			 FreeBSD-runtime \
 			 FreeBSD-certctl \
 			 FreeBSD-kerberos-lib \
diff --git a/release/tools/oci-image-static.conf b/release/tools/oci-image-static.conf
index 552328e66f3c..753a03af653b 100644
--- a/release/tools/oci-image-static.conf
+++ b/release/tools/oci-image-static.conf
@@ -8,12 +8,13 @@ OCI_BASE_IMAGE=
 
 oci_image_build() {
 	local srcdir=${curdir}/..
+	local m=${workdir}/rootfs
 	mtree -deU -p $m/ -f ${srcdir}/etc/mtree/BSD.root.dist > /dev/null
 	mtree -deU -p $m/var -f ${srcdir}/etc/mtree/BSD.var.dist > /dev/null
 	mtree -deU -p $m/usr -f ${srcdir}/etc/mtree/BSD.usr.dist > /dev/null
 	mtree -deU -p $m/usr/include -f ${srcdir}/etc/mtree/BSD.include.dist > /dev/null
 	mtree -deU -p $m/usr/lib -f ${srcdir}/etc/mtree/BSD.debug.dist > /dev/null
-	install_packages ${abi} ${workdir} $m FreeBSD-caroot FreeBSD-zoneinfo
+	install_packages ${abi} ${workdir} FreeBSD-caroot FreeBSD-zoneinfo
 	cp ${srcdir}/etc/master.passwd $m/etc
 	pwd_mkdb -p -d $m/etc $m/etc/master.passwd || return $?
 	cp ${srcdir}/etc/group $m/etc || return $?



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202503021517.522FHnWk009616>