live-metal/blend_helpers-docker

471 lines
12 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env zsh
## debuerreotype sequence
## docker run --cap-add SYS_ADMIN --cap-drop SETFCAP --tmpfs /tmp:dev,exec,suid,noatime ...
# bootstrapping a new architecture?
# ./scripts/debuerreotype-init /tmp/docker-rootfs bullseye now
# ./scripts/debuerreotype-minimizing-config /tmp/docker-rootfs
# ./scripts/debuerreotype-debian-sources-list /tmp/docker-rootfs bullseye
# ./scripts/debuerreotype-tar /tmp/docker-rootfs - | docker import - debian:bullseye-slim
# alternate:
# debootstrap --variant=minbase bullseye /tmp/docker-rootfs
# tar -cC /tmp/docker-rootfs . | docker import - debian:bullseye-slim
# (or your own favorite set of "debootstrap" commands to create a base image for building this one FROM)
##
build_docker_dist() {
fn build_docker_dist
req=(workdir strapdir os arch size imageformat parted_type)
ckreq || return 1
notice "Building complete docker image(s)"
act "obtain apt/dpkg versions."
apt_version=apt-version
dpkg_version=dpkg-version
act "create and populate the rootfs."
bootstrap_complete_base-wrapper || { zerr; return 1; }
blend_preinst || { zerr; return 1; }
blend_postinst || { zerr; return 1; }
notice "import, tag and push them image."
docker-init-policy || { zerr; return 1; }
# docker-hostname || { zerr; return 1; }
# docker-resolvconf || { zerr; return 1; }
act "apt related fixups move to sysconf-docker."
docker-apt-speedup || { zerr; return 1; }
docker-apt-autoremove-suggests || { zerr; return 1; }
docker-apt-clean || { zerr; return 1; }
docker-apt-gzip-indexes || { zerr; return 1; }
docker-apt-no-languages || { zerr; return 1; }
act "import, tag and push the image."
docker-import || { zerr; return 1; }
docker-push || { zerr; return 1; }
act "slimify the rootfs."
docker-purge_slimify_package || { zerr; return 1; }
docker-slimify || { zerr; return 1; }
act "import, tag and push the slim image."
docker-import --slim || { zerr; return 1; }
docker-push --slim || { zerr; return 1; }
clean_strapdir || { zerr; return 1; }
}
docker-push() {
fn docker-push
req=(R strapdir release registry_url registry_user registry_token registry_tag)
ckreq || return 1
notice "beginning the push procedure."
act "registry login"
docker login -u ${registry_user} -p ${registry_token} ${registry_url}
#${registry_tag} # date, $CI_COMMIT_SHA, $CI_COMMIT_REF_SLUG
if [[ -n $1 ]]; then
case $1 in
-s|--slim)
release=${release}-slim
act "setting release to ${release}."
shift
;;
*)
echo "Unknown parameter passed: $1"
exit 1
;;
esac
fi
docker tag ${registry_url}/${release}:${registry_tag} ${registry_url}:${release}
docker push ${registry_url}/${release}
docker logout ${registry_url}
}
docker-import() {
fn docker-import
req=(R strapdir release apt_version)
ckreq || return 1
notice "tar-ing the \$strapdir before importing for docker."
act "adding additional excludes for apt versions older than 0.8"
if dpkg --compare-versions "$apt_version" '>=' '0.8~'; then
# if APT is new enough to auto-recreate "partial" directories, let it
# (https://salsa.debian.org/apt-team/apt/commit/1cd1c398d18b78f4aa9d882a5de5385f4538e0be)
excludes+=(
'./var/cache/apt/**'
'./var/lib/apt/lists/**'
'./var/state/apt/lists/**'
)
# (see also the targeted exclusions in "tar-excludes" that these are overriding)
fi
act "calling docker-fixup before tar."
docker-fixup
act "setting arguments for tar."
tarArgs=(
--create
--file "$strapdir"
--auto-compress
--directory "$strapdir"
--exclude-from "${BLENDPATH}/tar-excludes"
)
if [ -z "$includeDev" ]; then
act "excluding the contents of /dev from the archive."
excludes+=( './dev/**' )
fi
for exclude in "${excludes[@]}"; do
tarArgs+=( --exclude "$exclude" )
done
tarArgs+=(
--numeric-owner
--transform 's,^./,,'
--sort name
.
)
if [[ -n $1 ]]; then
case $1 in
-s|--slim)
release=${release}-slim
act "setting release to ${release}."
shift
;;
*)
echo "Unknown parameter passed: $1"
exit 1
;;
esac
fi
act "calling tar."
tar "${tarArgs[@]}" - | docker import - devuan:${release}
}
docker-fixup() {
fn docker-fixup
req=(R strapdir )
ckreq || return 1
notice "removing redundant log and cache files."
pushd "$strapdir" || { zerr; return 1; }
rm -f \
"./var/log/dpkg.log" \
"./var/log/bootstrap.log" \
"./var/log/alternatives.log" \
"./var/cache/ldconfig/aux-cache"
act "removing redundant /run mounts."
# https://github.com/debuerreotype/debuerreotype/pull/32
rm -f "./run/mount/utab"
# (also remove the directory, but only if it's empty)
rmdir "./run/mount" 2>/dev/null || :
# fix ownership/permissions on / (otherwise "debootstrap" leaves them as-is which causes reproducibility issues)
chown 0:0 "./"
chmod 0755 "./"
popd
}
docker-slimify() {
fn docker-slimify
req=(R strapdir )
ckreq || return 1
notice "Removing files specified in the blends config-docker \$slimExcludes variable and adding the paths to the dpkg config."
dest=$strapdir/etc/dpkg/dpkg.cfg.d
dpkgCfgFile="${dest}/docker"
mkdir -p $(dirname "$dpkgCfgFile")
cat > ${dpkgCfgFile} <<-EOF
# This is the "slim" variant of the Devuan base image.
# Many files which are normally unnecessary in containers are excluded,
# and this configuration file keeps them that way.
EOF
act "make a record of the directory structure under /usr/share/man."
extraSpecialDirectories=( "$strapdir"/usr/share/man/man[0-9]/ )
act "processing the includes in \$slimIncludes"
findMatchIncludes=()
for slimInclude in "${slimIncludes[@]}"; do
[ "${#findMatchIncludes[@]}" -eq 0 ] || findMatchIncludes+=( '-o' )
findMatchIncludes+=( -path "$slimInclude" )
done
findMatchIncludes=( '(' "${findMatchIncludes[@]}" ')' )
act "processing the excludes in \$slimIncludes"
for slimExclude in "${slimExcludes[@]}"; do
{
echo
echo "# dpkg -S '$slimExclude'"
if dpkgOutput="$(chroot-script /bin/bash -c " \
dpkg -S "$slimExclude" 2>&1")"; then
echo "$dpkgOutput" | sed 's/: .*//g; s/, /\n/g' | sort -u | xargs
else
echo "$dpkgOutput"
fi | fold -w 76 -s | sed 's/^/# /'
echo "path-exclude $slimExclude"
} >> "$dpkgCfgFile"
notice "remove directories from slimExcludes in two passes."
if [[ "$slimExclude" == *'/*' ]]; then
if [ -d "$strapdir/$(dirname "$slimExclude")" ]; then
# use two passes so that we don't fail trying to remove directories from $slimIncludes
# this is our best effort at implementing https://sources.debian.net/src/dpkg/stretch/src/filters.c/#L96-L97 in shell
act "pass one: delete everything that doesn't match '\$slimIncludes' and isn't a directory or a symlink"
chroot-script /bin/bash -c " \
find "$(dirname "$slimExclude")" \
-depth -mindepth 1 \
-not \( -type d -o -type l \) \
-not "${findMatchIncludes[@]}" \
-exec rm -f '{}' ';'
"
act "pass two: repeatedly delete any dangling symlinks and empty directories until there aren't any"
# (might have a dangling symlink in a directory which then makes it empty, or a symlink to an empty directory)
while [ "$(
chroot-script /bin/bash -c " \
find "$(dirname "$slimExclude")" \
-depth -mindepth 1 \( -empty -o -xtype l \) \
-exec rm -rf '{}' ';' -printf '.' \
| wc -c "
)" -gt 0 ]; do true; done
fi
else
chroot-script bash -c "
rm -f "$slimExclude"
"
fi
done
act "appending includes to the dpkg conf."
{
echo
for slimInclude in "${slimIncludes[@]}"; do
echo "path-include $slimInclude"
done
} >> "$dpkgCfgFile"
chmod 0644 "$dpkgCfgFile"
act "recreate directory structure under /usr/share/man"
if [ "${#extraSpecialDirectories[@]}" -gt 0 ]; then
mkdir -p "${extraSpecialDirectories[@]}"
fi
}
docker-purge_slimify_package() {
fn docker-purge_slimify_packages
req=(strapdir slimify_packages)
ckreq || return 1
cat <<-EOF | sudo tee "$strapdir/purge_slimify_packages" >/dev/null
#!/bin/sh
apt-get --yes --force-yes purge ${purge_packages_option} ${slimify_packages} || exit 1
apt-get --yes --force-yes --purge autoremove || exit 1
apt-get clean
EOF
chroot-script -d purge_slimify_packages || { zerr; return 1; }
}
docker-init-policy() {
fn docker-init-policy
req=(R strapdir)
ckreq || return 1
dest=$strapdir/usr/sbin
cat > ${dest}/policy-rc.d.docker <<EOF
#!/bin/sh
exit 101 # action forbidden by policy
EOF
chmod 0755 "${dest}/policy-rc.d.docker"
cat <<-EOF | sudo tee ${strapdir}/init-policy >/dev/null
#!/bin/sh
update-alternatives --quiet --install /usr/sbin/policy-rc.d \
policy-rc.d /usr/sbin/policy-rc.d.docker 100
case "${release}" in
jessie|ascii)
dpkg-divert --quiet --local --add /sbin/initctl
;;
*)
dpkg-divert --quiet --local --no-rename --add /sbin/initctl
;;
esac
ln -fs /bin/true /sbin/initctl
EOF
chroot-script -d init-policy
}
docker-apt-speedup() {
fn docker-apt-speedup
req=(R strapdir)
ckreq || return 1
dest=$strapdir/etc/dpkg/dpkg.cfg.d
sudo mkdir -p ${dest}
cat <<-EOF | sudo tee ${dest}/docker-apt-speedup" >/dev/null
force-unsafe-io
EOF
chmod 0644 "${dest}/docker-apt-speedup"
}
docker-apt-autoremove-suggests() {
fn docker-apt-autoremove-suggests
req=(R strapdir)
ckreq || return 1
dest=$strapdir/etc/apt/apt.conf.d
sudo mkdir -p ${dest}
cat <<-EOF | sudo tee ${dest}/docker-apt-autoremove-suggests" >/dev/null
Apt::AutoRemove::SuggestsImportant "false";
EOF
chmod 0644 "${dest}/docker-apt-autoremove-suggests"
}
docker-apt-clean() {
fn docker-apt-clean
req=(R strapdir)
ckreq || return 1
dest=$strapdir/etc/apt/apt.conf.d
sudo mkdir -p ${dest}
aptGetClean='"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true";'
cat <<-EOF | sudo tee ${dest}/docker-apt-clean" >/dev/null
APT::Update::Post-Invoke { $aptGetClean };
Dir::Cache::pkgcache "";
Dir::Cache::srcpkgcache "";
EOF
chmod 0644 "${dest}/docker-apt-clean"
}
docker-apt-gzip-indexes() {
fn docker-apt-gzip-indexes
req=(R strapdir)
ckreq || return 1
dest=$strapdir/etc/apt/apt.conf.d
sudo mkdir -p ${dest}
cat <<-EOF | sudo tee ${dest}/docker-apt-gzip-indexes" >/dev/null
Acquire::GzipIndexes "true";
EOF
chmod 0644 "${dest}/docker-apt-gzip-indexes"
}
docker-apt-no-languages() {
fn docker-apt-no-languages
req=(R strapdir)
ckreq || return 1
dest=$strapdir/etc/apt/apt.conf.d
sudo mkdir -p ${dest}
cat <<-EOF | sudo tee ${dest}/docker-apt-no-languages" >/dev/null
Acquire::Languages "none";
EOF
chmod 0644 "${dest}/docker-apt-no-languages"
}
remove-apt-comments() {
fn remove-apt-comments
req=(R strapdir apt_version)
ckreq || return 1
dest=$strapdir/etc/apt/apt.conf.d
if dpkg --compare-versions "$apt_version" '>=' '0.7.22~'; then
exit
fi
sed -ri -e 's!^#!//!' "${dest}"
}
# set in zlibs/sysconf:conf_print_hostname() using $os
# override in $BLENDPATH/sysconf:conf_print_hosts
# a containers hostname defaults to be the containers ID in
# Docker unless overriden at build. So this is less important here.
docker-hostname() {
fn docker-hostname
req=(R strapdir hostname)
ckreq || return 1
pushd
act "setting the hostname."
echo "${hostname}" > "./etc/hostname"
chmod 0644 \
"$strapdir/etc/hostname"
popd
}
# set in zlibs/sysconf:conf_print_resolvconf()
# override in $BLENDPATH/sysconf
docker-resolvconf() {
fn docker-resolvconf
req=(R strapdir)
ckreq || return 1
pushd $strapdir
act "replacing /etc/resolv.conf."
cat <<-EOF | sudo tee ./etc/resolv.conf" >/dev/null
# https://1.1.1.1 (privacy-focused, highly-available DNS service)
nameserver 1.1.1.1
nameserver 1.0.0.1
EOF
chmod 0644 \
"./etc/resolv.conf"
popd
}
# If inside a virtual machine or container environment the
# /etc/machine-id is usually taken from the container UUID
#docker-id() {
# fn docker-id
# req=(R strapdir epoch)
# ckreq || return 1
#
# pushd $strapdir
#act "Initialize the machine ID in /etc/machine-id"
#echo "$epoch" \
# | md5sum \
# | cut -f1 -d' ' \
# > "./etc/machine-id"
# chmod 0644 \
# "./etc/machine-id"
# popd
#}