mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 19:14:54 +02:00
Build with buildkit (#9628)
* generate multiarch images for non-architecture tags * Update documentation related to multiarch Docker * Remove qemu and switch to build via buildkit * Move to multistage Dockerfile * refactor docker script arg parsing and fix merge bugs * removed unnecessary testing script and fixed function name * improved quoting in shell scripts --------- Co-authored-by: humanoid2050 <humanoid2050@monolith> Co-authored-by: Brad Warren <bmw@users.noreply.github.com> Co-authored-by: humanoid2050 <humanoid2050@katana> Co-authored-by: Brad Warren <bmw@eff.org>
This commit is contained in:
co-authored by
humanoid2050
Brad Warren
humanoid2050
Brad Warren
parent
7a68b29140
commit
9ee1eee219
@@ -4,12 +4,12 @@ jobs:
|
|||||||
vmImage: ubuntu-22.04
|
vmImage: ubuntu-22.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
amd64:
|
|
||||||
DOCKER_ARCH: amd64
|
|
||||||
arm32v6:
|
arm32v6:
|
||||||
DOCKER_ARCH: arm32v6
|
DOCKER_ARCH: arm32v6
|
||||||
arm64v8:
|
arm64v8:
|
||||||
DOCKER_ARCH: arm64v8
|
DOCKER_ARCH: arm64v8
|
||||||
|
amd64:
|
||||||
|
DOCKER_ARCH: amd64
|
||||||
# The default timeout of 60 minutes is a little low for compiling
|
# The default timeout of 60 minutes is a little low for compiling
|
||||||
# cryptography on ARM architectures.
|
# cryptography on ARM architectures.
|
||||||
timeoutInMinutes: 180
|
timeoutInMinutes: 180
|
||||||
@@ -32,24 +32,28 @@ jobs:
|
|||||||
path: $(Build.ArtifactStagingDirectory)
|
path: $(Build.ArtifactStagingDirectory)
|
||||||
artifact: docker_$(DOCKER_ARCH)
|
artifact: docker_$(DOCKER_ARCH)
|
||||||
displayName: Store Docker artifact
|
displayName: Store Docker artifact
|
||||||
- job: docker_run
|
- job: docker_test
|
||||||
dependsOn: docker_build
|
dependsOn: docker_build
|
||||||
pool:
|
pool:
|
||||||
vmImage: ubuntu-22.04
|
vmImage: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arm32v6:
|
||||||
|
DOCKER_ARCH: arm32v6
|
||||||
|
arm64v8:
|
||||||
|
DOCKER_ARCH: arm64v8
|
||||||
|
amd64:
|
||||||
|
DOCKER_ARCH: amd64
|
||||||
steps:
|
steps:
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
inputs:
|
inputs:
|
||||||
artifact: docker_amd64
|
artifact: docker_$(DOCKER_ARCH)
|
||||||
path: $(Build.SourcesDirectory)
|
path: $(Build.SourcesDirectory)
|
||||||
displayName: Retrieve Docker images
|
displayName: Retrieve Docker images
|
||||||
- bash: set -e && docker load --input $(Build.SourcesDirectory)/images.tar
|
- bash: set -e && docker load --input $(Build.SourcesDirectory)/images.tar
|
||||||
displayName: Load Docker images
|
displayName: Load Docker images
|
||||||
- bash: |
|
- bash: |
|
||||||
set -ex
|
set -e && tools/docker/test.sh $(dockerTag) $DOCKER_ARCH
|
||||||
DOCKER_IMAGES=$(docker images --filter reference='*/certbot' --filter reference='*/dns-*' --format '{{.Repository}}:{{.Tag}}')
|
|
||||||
for DOCKER_IMAGE in ${DOCKER_IMAGES}
|
|
||||||
do docker run --rm "${DOCKER_IMAGE}" plugins --prepare
|
|
||||||
done
|
|
||||||
displayName: Run integration tests for Docker images
|
displayName: Run integration tests for Docker images
|
||||||
- job: installer_build
|
- job: installer_build
|
||||||
pool:
|
pool:
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ stages:
|
|||||||
vmImage: ubuntu-22.04
|
vmImage: ubuntu-22.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
amd64:
|
|
||||||
DOCKER_ARCH: amd64
|
|
||||||
arm32v6:
|
arm32v6:
|
||||||
DOCKER_ARCH: arm32v6
|
DOCKER_ARCH: arm32v6
|
||||||
arm64v8:
|
arm64v8:
|
||||||
DOCKER_ARCH: arm64v8
|
DOCKER_ARCH: arm64v8
|
||||||
|
amd64:
|
||||||
|
DOCKER_ARCH: amd64
|
||||||
steps:
|
steps:
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
inputs:
|
inputs:
|
||||||
@@ -51,7 +51,7 @@ stages:
|
|||||||
command: login
|
command: login
|
||||||
containerRegistry: docker-hub
|
containerRegistry: docker-hub
|
||||||
displayName: Login to Docker Hub
|
displayName: Login to Docker Hub
|
||||||
- bash: set -e && tools/docker/deploy_by_arch.sh $(dockerTag) $DOCKER_ARCH
|
- bash: set -e && tools/docker/deploy_images.sh $(dockerTag) $DOCKER_ARCH
|
||||||
displayName: Deploy the Docker images by architecture
|
displayName: Deploy the Docker images by architecture
|
||||||
- job: publish_docker_multiarch
|
- job: publish_docker_multiarch
|
||||||
dependsOn: publish_docker_by_arch
|
dependsOn: publish_docker_by_arch
|
||||||
@@ -63,5 +63,5 @@ stages:
|
|||||||
command: login
|
command: login
|
||||||
containerRegistry: docker-hub
|
containerRegistry: docker-hub
|
||||||
displayName: Login to Docker Hub
|
displayName: Login to Docker Hub
|
||||||
- bash: set -e && tools/docker/deploy_multiarch.sh $(dockerTag)
|
- bash: set -e && tools/docker/deploy_manifests.sh $(dockerTag) all
|
||||||
displayName: Deploy the Docker multiarch manifests
|
displayName: Deploy the Docker multiarch manifests
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
# Docker Arch (amd64, arm32v6, ...)
|
#base image
|
||||||
ARG TARGET_ARCH
|
FROM python:3.10-alpine3.16 as certbot
|
||||||
FROM ${TARGET_ARCH}/python:3.10-alpine3.16
|
|
||||||
|
|
||||||
# Qemu Arch (x86_64, arm, ...)
|
|
||||||
ARG QEMU_ARCH
|
|
||||||
ENV QEMU_ARCH=${QEMU_ARCH}
|
|
||||||
COPY qemu-${QEMU_ARCH}-static /usr/bin/
|
|
||||||
|
|
||||||
ENTRYPOINT [ "certbot" ]
|
ENTRYPOINT [ "certbot" ]
|
||||||
EXPOSE 80 443
|
EXPOSE 80 443
|
||||||
@@ -45,3 +39,10 @@ RUN apk add --no-cache --virtual .build-deps \
|
|||||||
--editable src/certbot \
|
--editable src/certbot \
|
||||||
&& apk del .build-deps \
|
&& apk del .build-deps \
|
||||||
&& rm -rf ${HOME}/.cargo
|
&& rm -rf ${HOME}/.cargo
|
||||||
|
|
||||||
|
#static definition for making a plugin, but beware that
|
||||||
|
#using this layer definition will cause collisions if you make
|
||||||
|
#extensive use of the cache.
|
||||||
|
FROM certbot as certbot-plugin
|
||||||
|
COPY --from=plugin-src . /opt/certbot/src/plugin
|
||||||
|
RUN python tools/pip_install.py --no-cache-dir --editable /opt/certbot/src/plugin
|
||||||
+19
-12
@@ -21,22 +21,29 @@ High-level behavior
|
|||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Running `./build.sh <TAG> all` causes the Docker images to be built for all
|
Running `./build.sh <TAG> all` causes the Docker images to be built for all
|
||||||
supported architectures, where `<TAG>` is the base of the tag that should be
|
supported architectures. The generated images are stored in the local docker image cache.
|
||||||
given to the generated images. The tag should either be `nightly` or a git
|
|
||||||
version tag like `v2.2.0`. The given tag is only the base of the tag because
|
|
||||||
the CPU architecture is also added to the tag. For version tags above `v2.0.0`,
|
|
||||||
Additional tags for `latest` are also generated. The generated images are stored
|
|
||||||
in the local docker image cache.
|
|
||||||
|
|
||||||
Running `./deploy_by_arch.sh <TAG> all && ./deploy_multiarch.sh <TAG>` will
|
Running `./test.sh <TAG> all` loads images from the docker image cache
|
||||||
push the previously generated images to Docker Hub and then generate multi-arch
|
and runs a test command to validate the image contents.
|
||||||
manifests for easy access to the underlying images appropriate for a given
|
|
||||||
architecture.
|
Running `./deploy_images.sh <TAG> all` will push the previously generated images
|
||||||
|
to Docker Hub. The <TAG> argument is an identifier applied to all docker
|
||||||
|
images and manifests. It may be something like `nightly` or `v2.3.2`. If
|
||||||
|
the tag is a version stamp greater than `v2.0.0`, then a `latest` tag will
|
||||||
|
also be generated and pushed to the docker hub repo.
|
||||||
|
|
||||||
|
Running `./deploy_manifests.sh <TAG> all` will add multiarch manifests to
|
||||||
|
Docker Hub. This command assumes that `./deploy_images.sh <TAG> all` has
|
||||||
|
been previously run with the same tag.
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
To run these scripts you need:
|
To run these scripts you need:
|
||||||
|
|
||||||
1. An x86_64 machine with Docker installed and the Docker daemon running. You probably don't want to use the docker snap as these scripts have failed when using that in the past.
|
1. A computer with Docker installed and the Docker daemon running. You probably
|
||||||
2. To be logged into Docker Hub with an account able to push to the Certbot and Certbot DNS Docker images on Docker Hub. Altering the value of `DOCKER_HUB_ORG` in `lib/common` will allow you to push to your own account for testing.
|
don't want to use the docker snap as these scripts have failed when using that
|
||||||
|
in the past.
|
||||||
|
2. To be logged into Docker Hub with an account able to push to the Certbot and
|
||||||
|
Certbot DNS Docker images on Docker Hub. Altering the value of `DOCKER_HUB_ORG`
|
||||||
|
in `lib/common` will allow you to push to your own account for testing.
|
||||||
|
|||||||
+44
-96
@@ -1,108 +1,56 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
IFS=$'\n\t'
|
|
||||||
|
|
||||||
# This script builds certbot docker and certbot dns plugins docker using the
|
# This script builds docker images for certbot and each dns plugin from the
|
||||||
# local Certbot files.
|
# local Certbot source files. Results are stored in the docker image cache
|
||||||
|
|
||||||
# Usage: ./build.sh [TAG] [all|amd64|arm32v6|arm64v8]
|
# Usage:
|
||||||
# with the [TAG] value corresponding the base of the tag to give the Docker
|
# ./build.sh <tag> all
|
||||||
# images and the 2nd value being the architecture to build snaps for.
|
# ./build.sh <tag> <architectures>
|
||||||
# Values for the tag should be something like `v0.34.0` or `nightly`. The
|
# The <tag> argument is used to identify the code version (e.g v2.3.1) or type of build
|
||||||
# given value is only the base of the tag because the things like the CPU
|
# (e.g. nightly). This will be used when saving images to the docker image cache.
|
||||||
# architecture are also added to the full tag.
|
# The argument "all" will build all known architectures. Alternatively, the
|
||||||
|
# user may provide a comma separated list of architectures drawn from the
|
||||||
|
# known architectures. Known architectures include amd64, arm32v6, and arm64v8.
|
||||||
|
|
||||||
WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
source "$(realpath "$(dirname "${BASH_SOURCE[0]}")")/lib/common"
|
||||||
REPO_ROOT="$(dirname "$(dirname "${WORK_DIR}")")"
|
|
||||||
source "$WORK_DIR/lib/common"
|
|
||||||
|
|
||||||
|
ParseArgs "$@"
|
||||||
|
|
||||||
|
#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
|
trap Cleanup EXIT
|
||||||
|
# Create the builder
|
||||||
|
CreateBuilder
|
||||||
|
InstallMultiarchSupport
|
||||||
|
|
||||||
Cleanup() {
|
|
||||||
rm -rf "$REPO_ROOT"/qemu-*-static || true
|
|
||||||
for plugin in "${CERTBOT_PLUGINS[@]}"; do
|
|
||||||
rm -rf "$REPO_ROOT/certbot-$plugin"/qemu-*-static || true
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Returns the translation from Docker to QEMU architecture
|
BuildAndLoadByArch() {
|
||||||
# Usage: GetQemuArch [amd64|arm32v6|arm64v8]
|
TAG_ARCH=$1
|
||||||
GetQemuArch() {
|
docker buildx build --target certbot --builder certbot_builder \
|
||||||
ARCH=$1
|
--platform "$(arch2platform "$TAG_ARCH")" \
|
||||||
|
-f "${WORK_DIR}/Dockerfile" \
|
||||||
case "$ARCH" in
|
-t "${DOCKER_HUB_ORG}/certbot:${TAG_ARCH}-${TAG_VER}" \
|
||||||
"amd64")
|
--load \
|
||||||
echo "x86_64"
|
|
||||||
;;
|
|
||||||
"arm32v6")
|
|
||||||
echo "arm"
|
|
||||||
;;
|
|
||||||
"arm64v8")
|
|
||||||
echo "aarch64"
|
|
||||||
;;
|
|
||||||
"*")
|
|
||||||
echo "Not supported build architecture '$1'." >&2
|
|
||||||
exit 1
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# Downloads QEMU static binary file for architecture
|
|
||||||
# Usage: DownloadQemuStatic [x86_64|arm|aarch64]
|
|
||||||
DownloadQemuStatic() {
|
|
||||||
ARCH=$1
|
|
||||||
|
|
||||||
QEMU_ARCH=$(GetQemuArch "$ARCH")
|
|
||||||
if [ ! -f "qemu-${QEMU_ARCH}-static" ]; then
|
|
||||||
QEMU_DOWNLOAD_URL="https://github.com/multiarch/qemu-user-static/releases/download"
|
|
||||||
QEMU_LATEST_TAG=$(curl -s https://api.github.com/repos/multiarch/qemu-user-static/tags \
|
|
||||||
| grep 'name.*v[0-9]' \
|
|
||||||
| head -n 1 \
|
|
||||||
| cut -d '"' -f 4)
|
|
||||||
curl -SL "${QEMU_DOWNLOAD_URL}/${QEMU_LATEST_TAG}/x86_64_qemu-$QEMU_ARCH-static.tar.gz" \
|
|
||||||
| tar xzv
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
TAG_BASE="$1"
|
|
||||||
if [ -z "$TAG_BASE" ]; then
|
|
||||||
echo "We cannot tag Docker images with an empty string!" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
ParseRequestedArch "${2}"
|
|
||||||
|
|
||||||
# Register QEMU handlers
|
|
||||||
docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
|
||||||
|
|
||||||
# Step 1: Certbot core Docker
|
|
||||||
DOCKER_REPO="${DOCKER_HUB_ORG}/certbot"
|
|
||||||
for TARGET_ARCH in "${ALL_REQUESTED_ARCH[@]}"; do
|
|
||||||
pushd "${REPO_ROOT}"
|
|
||||||
DownloadQemuStatic "${TARGET_ARCH}"
|
|
||||||
QEMU_ARCH=$(GetQemuArch "${TARGET_ARCH}")
|
|
||||||
DOCKER_BUILDKIT=0 docker build \
|
|
||||||
--build-arg TARGET_ARCH="${TARGET_ARCH}" \
|
|
||||||
--build-arg QEMU_ARCH="${QEMU_ARCH}" \
|
|
||||||
-f "${WORK_DIR}/core/Dockerfile" \
|
|
||||||
-t "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" \
|
|
||||||
.
|
.
|
||||||
popd
|
for plugin in "${CERTBOT_PLUGINS[@]}"; do
|
||||||
done
|
docker buildx build --target certbot-plugin --builder certbot_builder \
|
||||||
|
--platform "$(arch2platform "$TAG_ARCH")" \
|
||||||
# Step 2: Certbot DNS plugins Docker images
|
--build-context plugin-src="${REPO_ROOT}/certbot-${plugin}" \
|
||||||
for plugin in "${CERTBOT_PLUGINS[@]}"; do
|
-f "${WORK_DIR}/Dockerfile" \
|
||||||
DOCKER_REPO="${DOCKER_HUB_ORG}/${plugin}"
|
-t "${DOCKER_HUB_ORG}/${plugin}:${TAG_ARCH}-${TAG_VER}" \
|
||||||
pushd "${REPO_ROOT}/certbot-${plugin}"
|
--load \
|
||||||
# Copy QEMU static binaries downloaded when building the core Certbot image
|
|
||||||
cp ../qemu-*-static .
|
|
||||||
for TARGET_ARCH in "${ALL_REQUESTED_ARCH[@]}"; do
|
|
||||||
QEMU_ARCH=$(GetQemuArch "${TARGET_ARCH}")
|
|
||||||
BASE_IMAGE="${DOCKER_HUB_ORG}/certbot:${TARGET_ARCH}-${TAG_BASE}"
|
|
||||||
DOCKER_BUILDKIT=0 docker build \
|
|
||||||
--build-arg BASE_IMAGE="${BASE_IMAGE}" \
|
|
||||||
--build-arg QEMU_ARCH="${QEMU_ARCH}" \
|
|
||||||
-f "${WORK_DIR}/plugin/Dockerfile" \
|
|
||||||
-t "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" \
|
|
||||||
.
|
.
|
||||||
done
|
done
|
||||||
popd
|
}
|
||||||
done
|
|
||||||
|
# In principle, there is a better way to do with by using `docker buildx bake`
|
||||||
|
# instead of a for-loop. However, issues have been found in the results
|
||||||
|
# of such a build. See the branch buildx-bake and
|
||||||
|
# https://github.com/certbot/certbot/issues/9587.
|
||||||
|
|
||||||
|
for ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
|
||||||
|
BuildAndLoadByArch "$ARCH"
|
||||||
|
done
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -euxo pipefail
|
|
||||||
IFS=$'\n\t'
|
|
||||||
|
|
||||||
# This script deploys new versions of Certbot and Certbot plugin docker images.
|
|
||||||
|
|
||||||
# Usage: ./deploy_by_arch.sh [TAG] [all|amd64|arm32v6|arm64v8]
|
|
||||||
# with the [TAG] value corresponding the base of the tag to give the Docker
|
|
||||||
# images and the 2nd value being the architecture to build snaps for.
|
|
||||||
# Values should be something like `v0.34.0` or `nightly`. The given value is
|
|
||||||
# only the base of the tag because the things like the CPU architecture are
|
|
||||||
# also added to the full tag.
|
|
||||||
|
|
||||||
WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
|
||||||
|
|
||||||
TAG_BASE="$1" # Eg. v0.35.0 or nightly
|
|
||||||
if [ -z "$TAG_BASE" ]; then
|
|
||||||
echo "We cannot tag Docker images with an empty string!" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
source "$WORK_DIR/lib/common"
|
|
||||||
ParseRequestedArch "${2}"
|
|
||||||
|
|
||||||
# Creates and pushes all Docker images aliases for the requested architectures
|
|
||||||
# set in the environment variable ALL_REQUESTED_ARCH. If the value of the
|
|
||||||
# global variable TAG_BASE is a 2.0.0 or greater version tag such as v2.1.0,
|
|
||||||
# tags for "latest" are also created. Tags such as "nightly" do not recieve
|
|
||||||
# "latest" tags.
|
|
||||||
# As an example, for the tag v2.2.0 and the default set of all target
|
|
||||||
# architectures as of writing this, the following tags would be created:
|
|
||||||
# - certbot/certbot:amd64-v2.2.0 <- image
|
|
||||||
# - certbot/certbot:arm32v6-v2.2.0 <- image
|
|
||||||
# - certbot/certbot:arm64v8-v2.2.0 <- image
|
|
||||||
# - certbot/certbot:amd64-latest <- image
|
|
||||||
# - certbot/certbot:arm32v6-latest <- image
|
|
||||||
# - certbot/certbot:arm64v8-latest <- image
|
|
||||||
# Usage: TagAndPushForAllRequestedArch [IMAGE NAME]
|
|
||||||
# where [IMAGE NAME] is the name of the Docker image in the Docker repository
|
|
||||||
# such as "certbot" or "dns-cloudflare".
|
|
||||||
# Read globals:
|
|
||||||
# * TAG_BASE
|
|
||||||
# * ALL_REQUESTED_ARCH
|
|
||||||
TagAndPushForAllRequestedArch() {
|
|
||||||
DOCKER_REPO="${DOCKER_HUB_ORG}/${1}"
|
|
||||||
for TARGET_ARCH in "${ALL_REQUESTED_ARCH[@]}"; do
|
|
||||||
# NOTE: In early 2022, we were experiencing regular "docker push"
|
|
||||||
# timeouts, so we added these "--debug" flags to learn more. Since we
|
|
||||||
# added them, we haven't had another timeout, so until we experience
|
|
||||||
# another timeout & can get the deubg logs, we're leaving them in.
|
|
||||||
docker --debug push "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}"
|
|
||||||
if [[ "${TAG_BASE}" =~ ^v([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+$ ]]; then
|
|
||||||
docker tag "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" "${DOCKER_REPO}:${TARGET_ARCH}-latest"
|
|
||||||
docker --debug push "${DOCKER_REPO}:${TARGET_ARCH}-latest"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Step 1: Certbot core Docker
|
|
||||||
TagAndPushForAllRequestedArch "certbot"
|
|
||||||
|
|
||||||
# Step 2: Certbot DNS plugins Docker images
|
|
||||||
for plugin in "${CERTBOT_PLUGINS[@]}"; do
|
|
||||||
TagAndPushForAllRequestedArch "${plugin}"
|
|
||||||
done
|
|
||||||
Executable
+46
@@ -0,0 +1,46 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
# This script takes docker images in the local docker cache and pushes them to
|
||||||
|
# Docker Hub.
|
||||||
|
|
||||||
|
# Usage:
|
||||||
|
# ./deploy_images.sh <TAG> all
|
||||||
|
# ./deploy_images.sh <TAG> <architectures>
|
||||||
|
# The <TAG> argument is an identifier applied to all docker images and manifests.
|
||||||
|
# It may be something like `nightly` or `v2.3.2`. If the tag is a version
|
||||||
|
# stamp greater than v2.0.0, then a `latest` tag will also be generated and
|
||||||
|
# pushed to the docker hub repo.
|
||||||
|
# The argument "all" will push all known architectures. Alternatively, the
|
||||||
|
# user may provide a comma separated list of architectures drawn from the
|
||||||
|
# known architectures. Known architectures include amd64, arm32v6, and arm64v8.
|
||||||
|
|
||||||
|
source "$(realpath $(dirname "${BASH_SOURCE[0]}"))/lib/common"
|
||||||
|
|
||||||
|
ParseArgs "$@"
|
||||||
|
|
||||||
|
#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 popd EXIT
|
||||||
|
|
||||||
|
REGISTRY_SPEC="${DOCKER_HUB_ORG}/"
|
||||||
|
|
||||||
|
DeployImage() {
|
||||||
|
IMAGE_NAME=$1
|
||||||
|
TAG_ARCH=$2
|
||||||
|
docker push "${REGISTRY_SPEC}${IMAGE_NAME}:${TAG_ARCH}-${TAG_VER}"
|
||||||
|
if [[ "${TAG_VER}" =~ ^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}:${TAG_ARCH}-latest"
|
||||||
|
docker push "${REGISTRY_SPEC}${IMAGE_NAME}:${TAG_ARCH}-latest"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for TAG_ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
|
||||||
|
DeployImage certbot "$TAG_ARCH"
|
||||||
|
for PLUGIN in "${CERTBOT_PLUGINS[@]}"; do
|
||||||
|
DeployImage "$PLUGIN" "$TAG_ARCH"
|
||||||
|
done
|
||||||
|
done
|
||||||
Executable
+48
@@ -0,0 +1,48 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
# This script generates multi-arch manifests for images previously pushed to
|
||||||
|
# Docker Hub via deploy_images.sh
|
||||||
|
|
||||||
|
# Usage:
|
||||||
|
# ./deploy_manifest.sh <TAG> all
|
||||||
|
# ./deploy_manifest.sh <TAG> <architectures>
|
||||||
|
# The <TAG> argument is an identifier applied to all docker images and manifests.
|
||||||
|
# It may be something like `nightly` or `v2.3.2`. If the tag is a version
|
||||||
|
# stamp greater than v2.0.0, then a `latest` tag will also be generated and
|
||||||
|
# pushed to the docker hub repo.
|
||||||
|
# The argument "all" will push 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"
|
||||||
|
|
||||||
|
ParseArgs "$@"
|
||||||
|
|
||||||
|
#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 popd EXIT
|
||||||
|
|
||||||
|
REGISTRY_SPEC="${DOCKER_HUB_ORG}/"
|
||||||
|
|
||||||
|
DeployManifest() {
|
||||||
|
IMAGE_NAME=$1
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if [[ "${TAG_VER}" =~ ^v([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
|
docker buildx imagetools create -t "${REGISTRY_SPEC}${IMAGE_NAME}:latest" $SRC_IMAGES
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
DeployManifest certbot
|
||||||
|
for PLUGIN in "${CERTBOT_PLUGINS[@]}"; do
|
||||||
|
DeployManifest "$PLUGIN"
|
||||||
|
done
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -euxo pipefail
|
|
||||||
IFS=$'\n\t'
|
|
||||||
|
|
||||||
WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
|
||||||
|
|
||||||
TAG_BASE="$1" # Eg. v0.35.0 or nightly
|
|
||||||
if [ -z "$TAG_BASE" ]; then
|
|
||||||
echo "We cannot tag Docker images with an empty string!" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
source "$WORK_DIR/lib/common"
|
|
||||||
|
|
||||||
# Creates multiarch manifests for TAG_BASE, and 'latest' if TAG_BASE > 2.0.0
|
|
||||||
# - certbot/certbot:v2.2.0 <- multiarch manifest
|
|
||||||
# - certbot/certbot:latest <- multiarch manifest
|
|
||||||
MakeMultiarchManifestForAllTargetArch() {
|
|
||||||
DOCKER_REPO="${DOCKER_HUB_ORG}/${1}"
|
|
||||||
SRC_IMAGES=()
|
|
||||||
for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do
|
|
||||||
SRC_IMAGES+=("${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}")
|
|
||||||
done
|
|
||||||
docker buildx imagetools create -t ${DOCKER_REPO}:${TAG_BASE} "${SRC_IMAGES[@]}"
|
|
||||||
if [[ "${TAG_BASE}" =~ ^v([2-9]|[1-9][0-9]+)\.[0-9]+\.[0-9]+$ ]]; then
|
|
||||||
docker buildx imagetools create -t ${DOCKER_REPO}:latest "${SRC_IMAGES[@]}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Step 1: Certbot core Docker
|
|
||||||
MakeMultiarchManifestForAllTargetArch "certbot"
|
|
||||||
|
|
||||||
# Step 2: Certbot DNS plugins Docker images
|
|
||||||
for plugin in "${CERTBOT_PLUGINS[@]}"; do
|
|
||||||
MakeMultiarchManifestForAllTargetArch "${plugin}"
|
|
||||||
done
|
|
||||||
+76
-18
@@ -1,12 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -ex
|
set -euxo pipefail
|
||||||
|
|
||||||
# Current supported architectures
|
# Current supported architectures
|
||||||
export ALL_TARGET_ARCH=(amd64 arm32v6 arm64v8)
|
export ALL_TARGET_ARCH=(amd64 arm32v6 arm64v8)
|
||||||
|
|
||||||
# Architecture used in tags with no architecture specified (certbot/certbot:latest, certbot/certbot:v0.35.0, ...)
|
|
||||||
export DEFAULT_ARCH=amd64
|
|
||||||
|
|
||||||
# Name of the Certbot Docker organizaation on GitHub. After creating
|
# Name of the Certbot Docker organizaation on GitHub. After creating
|
||||||
# repositories with the same names (e.g. "certbot", "dns-dnsmadeeasy", etc.)
|
# repositories with the same names (e.g. "certbot", "dns-dnsmadeeasy", etc.)
|
||||||
# using a different account on Docker Hub, you can change this value to have
|
# using a different account on Docker Hub, you can change this value to have
|
||||||
@@ -31,22 +28,83 @@ export CERTBOT_PLUGINS=(
|
|||||||
"dns-sakuracloud"
|
"dns-sakuracloud"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Parses the requested architecture string and sets ALL_REQUESTED_ARCH to
|
# WORK_DIR is two levels above this file
|
||||||
# result.
|
export WORK_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")/..")"
|
||||||
# Usage: ParseRequestedArch [all|amd64|arm32v6|arm64v8]
|
# REPO_ROOT is two levels above that
|
||||||
ParseRequestedArch() {
|
export REPO_ROOT="$(realpath "${WORK_DIR}/../..")"
|
||||||
|
|
||||||
|
# Converts input architecture identifier to the platform specification
|
||||||
|
# understood by `docker build buildx --platform <specification>`.
|
||||||
|
# Usage: arch2platform [arm64|arm32v6|arm64v8]
|
||||||
|
# If the input is not recognized, an error is returned
|
||||||
|
arch2platform() {
|
||||||
REQUESTED_ARCH="${1}"
|
REQUESTED_ARCH="${1}"
|
||||||
if [[ "${REQUESTED_ARCH}" == "all" ]]; then
|
case $REQUESTED_ARCH in
|
||||||
ALL_REQUESTED_ARCH=("${ALL_TARGET_ARCH[@]}")
|
amd64)
|
||||||
return 0
|
echo "linux/amd64"
|
||||||
|
;;
|
||||||
|
arm32v6)
|
||||||
|
echo "linux/arm/v6"
|
||||||
|
;;
|
||||||
|
arm64v8)
|
||||||
|
echo "linux/arm64"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseArgs() {
|
||||||
|
export TAG_VER="$1"
|
||||||
|
if [ -z "$TAG_VER" ]; then
|
||||||
|
echo "We cannot tag Docker images with an empty string!" >&2
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do
|
ARCH_LIST="$2"
|
||||||
if [[ "${TARGET_ARCH}" == "${REQUESTED_ARCH}" ]]; then
|
if [ -z "$ARCH_LIST" ]; then
|
||||||
ALL_REQUESTED_ARCH=("${REQUESTED_ARCH}")
|
echo "Architectures must be specified!" >&2
|
||||||
return 0
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local IFS=","
|
||||||
|
# Handle the special value "all"
|
||||||
|
if [[ "${ARCH_LIST}" == "all" ]]; then
|
||||||
|
# Replace with comma separated
|
||||||
|
ARCH_LIST="${ALL_TARGET_ARCH[*]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Turn arch list into an array
|
||||||
|
read -ra REQUESTED_ARCH_ARRAY <<< "$ARCH_LIST"
|
||||||
|
# And make sure all individual elements are in the list of all known architectures
|
||||||
|
for REQUESTED_ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
|
||||||
|
local IFS=" "
|
||||||
|
if [[ ! " ${ALL_TARGET_ARCH[*]} " =~ " ${REQUESTED_ARCH} " ]]; then
|
||||||
|
echo "unknown architecture identifier: ${REQUESTED_ARCH}" >&2
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
# If we didn't return above, REQUESTED_ARCH has an unexpected value.
|
export REQUESTED_ARCH_ARRAY
|
||||||
echo "Unexpected target architecture \"${REQUESTED_ARCH}\"". >&2
|
|
||||||
exit 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Function for use with trap in the primary scripts to remove the
|
||||||
|
# docker builder and restore the original directory
|
||||||
|
Cleanup() {
|
||||||
|
docker buildx rm certbot_builder || true
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
# add binfmt tools to the docker environment, with integration into the new builder instance
|
||||||
|
InstallMultiarchSupport() {
|
||||||
|
docker run --privileged --rm tonistiigi/binfmt --install all
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to create a docker builder using the buildkit docker-container
|
||||||
|
# driver
|
||||||
|
CreateBuilder() {
|
||||||
|
# just incase the env is not perfectly clean, remove any old instance of the builder
|
||||||
|
docker buildx rm certbot_builder || true
|
||||||
|
# create the builder instance
|
||||||
|
docker buildx create --name certbot_builder --driver docker-container --driver-opt=network=host --bootstrap
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Certbot image to build on (e.g. certbot/certbot:amd64-v0.35.0)
|
|
||||||
ARG BASE_IMAGE
|
|
||||||
FROM ${BASE_IMAGE}
|
|
||||||
|
|
||||||
# Qemu Arch (x86_64, arm, ...)
|
|
||||||
ARG QEMU_ARCH
|
|
||||||
ENV QEMU_ARCH=${QEMU_ARCH}
|
|
||||||
COPY qemu-${QEMU_ARCH}-static /usr/bin/
|
|
||||||
|
|
||||||
# Copy Certbot DNS plugin code
|
|
||||||
COPY . /opt/certbot/src/plugin
|
|
||||||
|
|
||||||
# Install the DNS plugin
|
|
||||||
RUN python tools/pip_install.py --no-cache-dir --editable /opt/certbot/src/plugin
|
|
||||||
Executable
+43
@@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
# This script tests certbot docker and certbot dns plugin images.
|
||||||
|
|
||||||
|
# Usage:
|
||||||
|
# ./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. Known architectures include amd64, arm32v6, and arm64v8.
|
||||||
|
|
||||||
|
source "$(realpath $(dirname "${BASH_SOURCE[0]}"))/lib/common"
|
||||||
|
|
||||||
|
ParseArgs "$@"
|
||||||
|
|
||||||
|
#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 popd EXIT
|
||||||
|
|
||||||
|
InstallMultiarchSupport
|
||||||
|
|
||||||
|
|
||||||
|
REGISTRY_SPEC="${DOCKER_HUB_ORG}/"
|
||||||
|
|
||||||
|
TestImage() {
|
||||||
|
IMAGE_NAME=$1
|
||||||
|
TAG_ARCH=$2
|
||||||
|
TAG_VER=$3
|
||||||
|
docker run --rm "${REGISTRY_SPEC}${IMAGE_NAME}:${TAG_ARCH}-${TAG_VER}" plugins --prepare
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for TAG_ARCH in "${REQUESTED_ARCH_ARRAY[@]}"; do
|
||||||
|
TestImage certbot "$TAG_ARCH" "$TAG_VER"
|
||||||
|
for PLUGIN in "${CERTBOT_PLUGINS[@]}"; do
|
||||||
|
TestImage "$PLUGIN" "$TAG_ARCH" "$TAG_VER"
|
||||||
|
done
|
||||||
|
done
|
||||||
Reference in New Issue
Block a user