Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/release/scripts/make-oci-image.sh
102426 views
1
#! /bin/sh
2
3
# Build an Open Container Initiative (OCI) container image
4
5
curdir=$1; shift
6
rev=$1; shift
7
branch=$1; shift
8
arch=$1; shift
9
image=$1; shift
10
output=$1; shift
11
12
major=${rev%.*}
13
minor=${rev#*.}
14
15
abi=FreeBSD:${major}:${arch}
16
ver=${rev}-${branch}-${arch}
17
18
echo "Building OCI freebsd${major}-${image} image for ${abi}"
19
20
. ${curdir}/tools/oci-image-${image}.conf
21
22
init_repo() {
23
local workdir=$1; shift
24
local abi=$1; shift
25
local srcdir=$(realpath ${curdir}/..)
26
27
mkdir -p ${workdir}/repos
28
cat > ${workdir}/repos/base.conf <<EOF
29
FreeBSD-base: {
30
url: "file:///usr/obj${srcdir}/repo/${abi}/latest"
31
signature_type: "none"
32
fingerprints: "none"
33
}
34
EOF
35
}
36
37
# Install packages using pkg(8) into a container with rootfs at $3
38
install_packages() {
39
local abi=$1; shift
40
local workdir=$1; shift
41
local rootdir=${workdir}/rootfs
42
43
# Make sure we have the keys needed for verifying package integrity if
44
# not already added by a parent image.
45
if [ ! -d ${rootdir}/usr/share/keys/pkg/trusted ]; then
46
mkdir -p ${rootdir}/usr/share/keys/pkg/trusted
47
fi
48
for i in ${curdir}/../share/keys/pkg/trusted/pkg.*; do
49
if [ ! -f ${rootdir}/usr/share/keys/pkg/trusted/$(basename $i) ]; then
50
cp $i ${rootdir}/usr/share/keys/pkg/trusted
51
fi
52
done
53
54
# We install the packages and then remove repository metadata (keeping the
55
# metadata for what was installed). This trims more than 40Mb from the
56
# resulting image.
57
env IGNORE_OSVERSION=yes ABI=${abi} pkg --rootdir ${rootdir} --repo-conf-dir ${workdir}/repos \
58
install -yq -g "$@" || exit $?
59
rm -rf ${rootdir}/var/db/pkg/repos
60
}
61
62
set_cmd() {
63
local workdir=$1; shift
64
oci_cmd="$@"
65
}
66
67
# Convert FreeBSD architecture to OCI-style. See
68
# https://github.com/containerd/platforms/blob/main/platforms.go for details
69
normalize_arch() {
70
local arch=$1; shift
71
case ${arch} in
72
i386)
73
arch=386
74
;;
75
aarch64)
76
arch=arm64
77
;;
78
amd64) ;;
79
riscv64) ;;
80
*)
81
echo "Architecture ${arch} not supported for container images"
82
;;
83
esac
84
echo ${arch}
85
}
86
87
create_container() {
88
local workdir=$1; shift
89
local base_workdir=$1; shift
90
oci_cmd=
91
if [ -d ${workdir}/rootfs ]; then
92
chflags -R 0 ${workdir}/rootfs
93
rm -rf ${workdir}/rootfs
94
fi
95
mkdir -p ${workdir}/rootfs
96
if [ "${base_workdir}" != "" ]; then
97
tar -C ${workdir}/rootfs -xf ${base_workdir}/rootfs.tar.gz
98
fi
99
}
100
101
commit_container() {
102
local workdir=$1; shift
103
local image=$1; shift
104
local output=$1; shift
105
106
# Note: the diff_id (needed for image config) is the hash of the
107
# uncompressed tar.
108
#
109
# For compatibility with Podman, we must disable sparse-file
110
# handling. See https://github.com/containers/podman/issues/25270 for
111
# more details.
112
tar -C ${workdir}/rootfs --strip-components 1 --no-read-sparse -cf ${workdir}/rootfs.tar .
113
local diff_id=$(sha256 -q < ${workdir}/rootfs.tar)
114
gzip -f ${workdir}/rootfs.tar
115
local create_time=$(date -u +%Y-%m-%dT%TZ)
116
local root_hash=$(sha256 -q < ${workdir}/rootfs.tar.gz)
117
local root_size=$(stat -f %z ${workdir}/rootfs.tar.gz)
118
119
oci_arch=$(normalize_arch ${arch})
120
121
config=
122
if [ -n "${oci_cmd}" ]; then
123
config=",\"config\":{\"cmd\":[\"${oci_cmd}\"]}"
124
fi
125
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
126
local config_hash=$(sha256 -q < ${workdir}/config.json)
127
local config_size=$(stat -f %z ${workdir}/config.json)
128
129
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
130
local manifest_hash=$(sha256 -q < ${workdir}/manifest.json)
131
local manifest_size=$(stat -f %z ${workdir}/manifest.json)
132
133
mkdir -p ${workdir}/oci/blobs/sha256
134
echo "{\"imageLayoutVersion\": \"1.0.0\"}" > ${workdir}/oci/oci-layout
135
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
136
ln ${workdir}/rootfs.tar.gz ${workdir}/oci/blobs/sha256/${root_hash}
137
ln ${workdir}/config.json ${workdir}/oci/blobs/sha256/${config_hash}
138
ln ${workdir}/manifest.json ${workdir}/oci/blobs/sha256/${manifest_hash}
139
140
tar -C ${workdir}/oci --xz --strip-components 1 --no-read-sparse -a -cf ${output} .
141
}
142
143
# Prefix with "container-image-" so that we can create a unique work area under
144
# ${.OBJDIR}. We can assume that make has set our working directory to
145
# ${.OBJDIR}.
146
workdir=${PWD}/container-image-${image}
147
init_repo ${workdir} ${abi}
148
149
if [ -n "${OCI_BASE_IMAGE}" ]; then
150
base_workdir=${PWD}/container-image-${OCI_BASE_IMAGE}
151
else
152
base_workdir=
153
fi
154
155
create_container ${workdir} ${base_workdir}
156
oci_image_build
157
commit_container ${workdir} ${image} ${output}
158
159