leverage docker buildkit bake to speed up build times

This commit is contained in:
humanoid2050 2023-03-18 23:25:12 -04:00
parent accee97476
commit c10192b6d8
4 changed files with 251 additions and 87 deletions

View file

@ -6,46 +6,69 @@ set -euxo pipefail
# filesystem
# Usage:
# ./build.sh all
# ./build.sh <architectures>
# ./build.sh <tag> all
# ./build.sh <tag> <architectures>
# The <tag> argument is used to identify the code version (e.g v2.3.1) or type of build
# (e.g. nightly). This will be used when saving images to the docker image cache.
# The argument "all" will build all know architectures. Alternatively, the
# user may provide a comma separated list of architectures drawn from the
# known architectures. Know architectures include amd64, arm32v6, and arm64v8.
source "$(realpath $(dirname ${BASH_SOURCE[0]}))/lib/common"
REQUESTED_ARCH_LIST=$(InterpretArchRequest "$1")
PLATFORM_SPEC=$(archList2platformList "${REQUESTED_ARCH_LIST[@]}")
#used by docker buildx bake, so mark export
export TAG_VER="$1"
if [ -z "$TAG_VER" ]; then
echo "We cannot tag Docker images with an empty string!" >&2
exit 1
fi
ARCH_LIST="$2"
if [ -z "$ARCH_LIST" ]; then
echo "Architectures must be specified!" >&2
exit 1
fi
export REGISTRY_SPEC="${DOCKER_HUB_ORG}/"
#jump to root, matching popd handed by Cleanup on EXIT via trap
pushd "${REPO_ROOT}"
# Set trap here, as the popd won't work as expected if invoked prior to pushd
trap Cleanup EXIT
# Create the builder
CreateBuilder
# Helper function to build certbot image
BuildCertbot() {
docker buildx build \
$(StandardCertbotBuildArgs ${PLATFORM_SPEC}) \
--cache-to=type=local,dest=${DOCKER_CACHE}/certbot \
.
BuildAll() {
docker buildx bake -f ${WORK_DIR}/docker-bake.hcl \
--builder certbot_builder \
--set *.cache-to=type=local,dest=.docker_cache \
build-all
}
# --progress plain
BuildAndCacheByArch() {
export TAG_ARCH=$1
docker buildx bake -f ${WORK_DIR}/docker-bake.hcl \
--builder certbot_builder \
--set *.platform=$(arch2platform ${TAG_ARCH}) \
--set *.cache-from=type=local,src=.docker_cache \
build-all --load
}
# Helper function to build plugin image
BuildPlugin() {
PLUGIN=$1
docker buildx build \
$(StandardPluginBuildArgs ${PLATFORM_SPEC} ${PLUGIN}) \
--cache-to=type=local,dest=${DOCKER_CACHE}/${PLUGIN} \
.
}
# If the request was for all, max out the buildkit parallelization logic
if [ "$ARCH_LIST" = "all" ]; then
BuildAll
fi
# split arch list into an array for per-arch saving of images to the docker image cache
IFS_OLD="$IFS"
IFS=","
read -ra REQUESTED_ARCH_ARRAY <<< $(InterpretArchRequest "$ARCH_LIST")
IFS="$IFS_OLD"
for ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
# If the build was already done by BuildAll, then the existing image is pulled
# from the build cache. Otherwise, it gets built on demand here.
# Either way, images get tagged and loaded to the docker image cache
# for use by test and deploy
BuildAndCacheByArch $ARCH
done
# Step 1: Certbot core Docker
BuildCertbot
# Step 2: Certbot DNS plugins Docker images
for PLUGIN in "${CERTBOT_PLUGINS[@]}"; do
BuildPlugin $PLUGIN
done

View file

@ -41,32 +41,39 @@ LatestTag() {
fi
}
# Helper function to deploy certbot image with version and optional latest tag
DeployCertbot() {
DOCKER_REPO="${DOCKER_HUB_ORG}/certbot"
docker buildx build \
$(StandardCertbotBuildArgs ${PLATFORM_SPEC}) \
-t ${DOCKER_REPO}:${TAG_BASE} $(LatestTag ${TAG_BASE}) \
--push \
.
REGISTRY_SPEC="${DOCKER_HUB_ORG}/"
DeployImage() {
IMAGE_NAME=$1
TAG_ARCH=$2
TAG_VER=$3
docker push "${REGISTRY_SPEC}${IMAGE_NAME}:${TAG_ARCH}-${TAG_VER}"
if [[ "${TAG_BASE}" =~ ^v([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+$ ]]; then
docker tag "${REGISTRY_SPEC}${IMAGE_NAME}:${TAG_ARCH}-${TAG_VER}" "${REGISTRY_SPEC}${IMAGE_NAME}:latest"
fi
}
# Helper function to deploy plugin image with version and optional latest tag
DeployPlugin() {
PLUGIN=$1
DOCKER_REPO="${DOCKER_HUB_ORG}/${PLUGIN}"
docker buildx build \
$(StandardPluginBuildArgs ${PLATFORM_SPEC} ${PLUGIN}) \
-t ${DOCKER_REPO}:${TAG_BASE} $(LatestTag ${TAG_BASE}) \
--push \
.
DeployManifest() {
IMAGE_NAME=$1
local IFS=","
read -ra REQUESTED_ARCH_ARRAY <<< $(InterpretArchRequest "$2")
TAG_VER=$3
SRC_IMAGES=""
for TAG_ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
SRC_IMAGES+="${REGISTRY_SPEC}${IMAGE_NAME}:${TAG_ARCH}-${TAG_VER} "
done
docker buildx imagetools create -t "${REGISTRY_SPEC}${IMAGE_NAME}:${TAG_VER} $SRC_IMAGES"
}
# Step 1: Certbot core Docker
DeployCertbot
# Step 2: Certbot DNS plugins Docker images
for PLUGIN in "${CERTBOT_PLUGINS[@]}"; do
DeployPlugin $PLUGIN
for TAG_ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
DeployImage certbot $TAG_ARCH $TAG_VER
for PLUGIN in "${CERTBOT_PLUGINS[@]}"; do
DeployImage $PLUGIN $TAG_ARCH $TAG_VER
done
done

View file

@ -0,0 +1,146 @@
group "build-all" {
targets = ["certbot",
"dns-dnsmadeeasy",
"dns-dnsimple",
"dns-ovh",
"dns-cloudflare",
"dns-digitalocean",
"dns-google",
"dns-luadns",
"dns-nsone",
"dns-rfc2136",
"dns-route53",
"dns-gehirn",
"dns-linode",
"dns-sakuracloud"]
}
variable "WORK_DIR" {
default = "tools/docker"
}
variable "TAG_VER" {
default = "test"
}
variable "TAG_ARCH" {
default = "auto"
}
variable "REGISTRY_SPEC" {
// if provided, this should include the trailing slash (e.g. "certbot/)
default = ""
}
target "certbot" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot"
tags = ["${REGISTRY_SPEC}certbot:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-dnsmadeeasy" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-dnsmadeeasy"}
tags = ["${REGISTRY_SPEC}dns-dnsmadeeasy:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-dnsimple" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-dnsimple"}
tags = ["${REGISTRY_SPEC}dns-dnsimple:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-ovh" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-ovh"}
tags = ["${REGISTRY_SPEC}dns-ovh:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-cloudflare" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-cloudflare"}
tags = ["${REGISTRY_SPEC}dns-cloudflare:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-digitalocean" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-digitalocean"}
tags = ["${REGISTRY_SPEC}dns-digitalocean:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-google" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-google"}
tags = ["${REGISTRY_SPEC}dns-google:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-luadns" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-luadns"}
tags = ["${REGISTRY_SPEC}dns-luadns:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-nsone" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-nsone"}
tags = ["${REGISTRY_SPEC}dns-nsone:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-rfc2136" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-rfc2136"}
tags = ["${REGISTRY_SPEC}dns-rfc2136:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-route53" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-route53"}
tags = ["${REGISTRY_SPEC}dns-route53:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-gehirn" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-gehirn"}
tags = ["${REGISTRY_SPEC}dns-gehirn:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-linode" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-linode"}
tags = ["${REGISTRY_SPEC}dns-linode:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}
target "dns-sakuracloud" {
dockerfile = "${WORK_DIR}/Dockerfile"
target = "certbot-plugin"
contexts = {plugin-src = "certbot-dns-sakuracloud"}
tags = ["${REGISTRY_SPEC}dns-sakuracloud:${TAG_ARCH}-${TAG_VER}"]
platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v6"]
}

View file

@ -4,15 +4,30 @@ set -euxo pipefail
# This script tests certbot docker and certbot dns plugin images.
# Usage:
# ./test.sh all
# ./test.sh <architectures>
# ./test.sh <tag> all
# ./test.sh <tag> <architectures>
# The <tag> argument is used to identify the code version (e.g v2.3.1) or type of build
# (e.g. nightly). This will be used when saving images to the docker image cache.
# The argument "all" will build all know architectures. Alternatively, the
# user may provide a comma separated list of architectures drawn from the
# known architectures. Know architectures include amd64, arm32v6, and arm64v8.
source "$(realpath $(dirname ${BASH_SOURCE[0]}))/lib/common"
REQUESTED_ARCH_LIST=$(InterpretArchRequest "$1")
TAG_VER="$1"
if [ -z "$TAG_VER" ]; then
echo "We cannot tag Docker images with an empty string!" >&2
exit 1
fi
if [ -z "$2" ]; then
echo "Architectures must be specified!" >&2
exit 1
fi
IFS_OLD="$IFS"
IFS=","
read -ra REQUESTED_ARCH_ARRAY <<< $(InterpretArchRequest "$2")
IFS="$IFS_OLD"
#jump to root, matching popd handed by Cleanup on EXIT via trap
pushd "${REPO_ROOT}"
@ -23,46 +38,19 @@ trap Cleanup EXIT
CreateBuilder
IFS_OLD="$IFS"
IFS=","
read -ra REQUESTED_ARCH_ARRAY <<< "$REQUESTED_ARCH_LIST"
IFS="$IFS_OLD"
REGISTRY_SPEC="${DOCKER_HUB_ORG}/"
# Helper function to load and test certbot image
TestCertbot() {
ARCH=$1
DOCKER_REPO="${DOCKER_HUB_ORG}/certbot"
docker buildx build \
$(StandardCertbotBuildArgs $(arch2platform ${ARCH})) \
-t ${DOCKER_REPO}:${ARCH} \
--load \
.
docker run --rm "${DOCKER_REPO}:${ARCH}" plugins --prepare
docker rmi ${DOCKER_REPO}:${ARCH}
TestImage() {
IMAGE_NAME=$1
TAG_ARCH=$2
TAG_VER=$3
docker run --rm "${REGISTRY_SPEC}${IMAGE_NAME}:${TAG_ARCH}-${TAG_VER}" plugins --prepare
}
# Helper function to load and test plugin image
TestPlugin() {
ARCH=$1
PLUGIN=$2
DOCKER_REPO="${DOCKER_HUB_ORG}/${PLUGIN}"
docker buildx build \
$(StandardPluginBuildArgs $(arch2platform ${ARCH}) ${PLUGIN}) \
-t ${DOCKER_REPO}:${ARCH} \
--load \
.
docker run --rm "${DOCKER_REPO}:${ARCH}" plugins --prepare
docker rmi ${DOCKER_REPO}:${ARCH}
}
# Step 1: Certbot core Docker
for ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
TestCertbot $ARCH
done
# Step 2: Certbot DNS plugins Docker images
for ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
for TAG_ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
TestImage certbot $TAG_ARCH $TAG_VER
for PLUGIN in "${CERTBOT_PLUGINS[@]}"; do
TestPlugin $ARCH $PLUGIN
TestImage $PLUGIN $TAG_ARCH $TAG_VER
done
done