From 63ec74276ca52bac474a0ddef457bdc353253bc4 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Tue, 18 Aug 2020 01:51:30 -0700 Subject: [PATCH] Clean up our Docker scripts (#8214) * rewrite build step * rewrite deploy script * fix exit status * clean up comments * fix typo * correct comment --- tools/docker/build.sh | 84 ++++++++++++++---- tools/docker/core/hooks/build | 9 -- tools/docker/core/hooks/post_push | 10 --- tools/docker/core/hooks/pre_build | 10 --- tools/docker/core/hooks/push | 9 -- tools/docker/deploy.sh | 55 +++++++++--- tools/docker/lib/common | 127 ---------------------------- tools/docker/plugin/hooks/build | 9 -- tools/docker/plugin/hooks/post_push | 10 --- tools/docker/plugin/hooks/pre_build | 10 --- tools/docker/plugin/hooks/push | 9 -- 11 files changed, 110 insertions(+), 232 deletions(-) delete mode 100644 tools/docker/core/hooks/build delete mode 100644 tools/docker/core/hooks/post_push delete mode 100755 tools/docker/core/hooks/pre_build delete mode 100644 tools/docker/core/hooks/push delete mode 100644 tools/docker/plugin/hooks/build delete mode 100644 tools/docker/plugin/hooks/post_push delete mode 100644 tools/docker/plugin/hooks/pre_build delete mode 100644 tools/docker/plugin/hooks/push diff --git a/tools/docker/build.sh b/tools/docker/build.sh index 79617ca84..1b18c2c42 100755 --- a/tools/docker/build.sh +++ b/tools/docker/build.sh @@ -3,8 +3,7 @@ set -euxo pipefail IFS=$'\n\t' # This script builds certbot docker and certbot dns plugins docker using the -# local Certbot files. The build is currently done following the environment used by -# Dockerhub since this code previously used Docker Hub's automated build feature. +# local Certbot files. # Usage: ./build.sh [TAG] # with [TAG] corresponding the base of the tag to give the Docker images. @@ -38,26 +37,79 @@ Cleanup() { done } -Build() { - DOCKER_REPO="$1" - TAG_BASE="$2" - CONTEXT_PATH="$3" - DOCKERFILE_DIR="$4" - DOCKERFILE_PATH="$DOCKERFILE_DIR/Dockerfile" - pushd "$CONTEXT_PATH" - DOCKER_TAG="$TAG_BASE" DOCKER_REPO="$DOCKER_REPO" DOCKERFILE_PATH="$DOCKERFILE_PATH" bash "$DOCKERFILE_DIR/hooks/pre_build" - DOCKER_TAG="$TAG_BASE" DOCKER_REPO="$DOCKER_REPO" DOCKERFILE_PATH="$DOCKERFILE_PATH" bash "$DOCKERFILE_DIR/hooks/build" - popd +# Returns the translation from Docker to QEMU architecture +# Usage: GetQemuArch [amd64|arm32v6|arm64v8] +GetQemuArch() { + ARCH=$1 + + case "$ARCH" in + "amd64") + 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" +# Register QEMU handlers +docker run --rm --privileged multiarch/qemu-user-static:register --reset + # Step 1: Certbot core Docker -Build "$DOCKER_HUB_ORG/certbot" "$TAG_BASE" "$REPO_ROOT" "$WORK_DIR/core" +DOCKER_REPO="${DOCKER_HUB_ORG}/certbot" +for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do + pushd "${REPO_ROOT}" + DownloadQemuStatic "${TARGET_ARCH}" + QEMU_ARCH=$(GetQemuArch "${TARGET_ARCH}") + 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 +done # Step 2: Certbot DNS plugins Docker images for plugin in "${CERTBOT_PLUGINS[@]}"; do - Build "$DOCKER_HUB_ORG/$plugin" "$TAG_BASE" "$REPO_ROOT/certbot-$plugin" "$WORK_DIR/plugin" + DOCKER_REPO="${DOCKER_HUB_ORG}/${plugin}" + pushd "${REPO_ROOT}/certbot-${plugin}" + # Copy QEMU static binaries downloaded when building the core Certbot image + cp ../qemu-*-static . + for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do + QEMU_ARCH=$(GetQemuArch "${TARGET_ARCH}") + BASE_IMAGE="${DOCKER_HUB_ORG}/certbot:${TARGET_ARCH}-${TAG_BASE}" + 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 + popd done - -Cleanup diff --git a/tools/docker/core/hooks/build b/tools/docker/core/hooks/build deleted file mode 100644 index 4925dc269..000000000 --- a/tools/docker/core/hooks/build +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -ex - -WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -source "$WORK_DIR/../../lib/common" - -for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do - BuildDockerCoreImage "${TARGET_ARCH}" -done diff --git a/tools/docker/core/hooks/post_push b/tools/docker/core/hooks/post_push deleted file mode 100644 index bc700783e..000000000 --- a/tools/docker/core/hooks/post_push +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -ex - -WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -source "$WORK_DIR/../../lib/common" - -for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do - TagDockerImageAliases "${TARGET_ARCH}" - PushDockerImageAliases "${TARGET_ARCH}" -done diff --git a/tools/docker/core/hooks/pre_build b/tools/docker/core/hooks/pre_build deleted file mode 100755 index 723e35161..000000000 --- a/tools/docker/core/hooks/pre_build +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -ex - -WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -source "$WORK_DIR/../../lib/common" - -RegisterQemuHandlers -for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do - DownloadQemuStatic "${TARGET_ARCH}" -done diff --git a/tools/docker/core/hooks/push b/tools/docker/core/hooks/push deleted file mode 100644 index 0102c5d4d..000000000 --- a/tools/docker/core/hooks/push +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -ex - -WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -source "$WORK_DIR/../../lib/common" - -for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do - PushDockerImage "${TARGET_ARCH}" -done diff --git a/tools/docker/deploy.sh b/tools/docker/deploy.sh index 89802f264..a280e3982 100755 --- a/tools/docker/deploy.sh +++ b/tools/docker/deploy.sh @@ -3,8 +3,6 @@ set -euxo pipefail IFS=$'\n\t' # This script deploys new versions of Certbot and Certbot plugin docker images. -# This process is currently done using a similar approach to Docker Hub since -# this code previously used Docker Hub's automated build feature. # Usage: ./deploy.sh [TAG] # with [TAG] corresponding the base of the tag to give the Docker images. @@ -14,22 +12,53 @@ IFS=$'\n\t' WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -Deploy() { - DOCKER_REPO="$1" - TAG_BASE="$2" - DOCKERFILE_DIR="$3" - DOCKERFILE_PATH="$DOCKERFILE_DIR/Dockerfile" - DOCKER_TAG="$TAG_BASE" DOCKER_REPO="$DOCKER_REPO" DOCKERFILE_PATH="$DOCKERFILE_PATH" bash "$DOCKERFILE_DIR/hooks/push" - DOCKER_TAG="$TAG_BASE" DOCKER_REPO="$DOCKER_REPO" DOCKERFILE_PATH="$DOCKERFILE_PATH" bash "$DOCKERFILE_DIR/hooks/post_push" -} - TAG_BASE="$1" # Eg. v0.35.0 or nightly source "$WORK_DIR/lib/common" +# Creates and pushes all Docker images aliases for all architectures. +# If the value of the global variable TAG_BASE is a version tag such as +# v0.35.0, the "latest" tag is also updated. Tags without the architecture part +# are also created for the default architecture. +# As an example, for amd64 (the default architecture) and the tag v0.35.0, the +# following tags would be created: +# - certbot/certbot:v0.35.0 +# - certbot/certbot:latest +# - certbot/certbot:amd64-latest +# For the architecture arm32v6 and the tag v0.35.0, only the following tag +# would be created: +# - certbot/certbot:arm32v6-latest +# For other tags such as "nightly", aliases are only created for the default +# architecture where the tag "nightly" would be used without an architecture +# part. +# Usage: TagAndPushForAllArch [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 +TagAndPushForAllArch() { + DOCKER_REPO="${DOCKER_HUB_ORG}/${1}" + for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do + docker push "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" + + if [[ "${TAG_BASE}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + docker tag "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" "${DOCKER_REPO}:${TARGET_ARCH}-latest" + docker push "${DOCKER_REPO}:${TARGET_ARCH}-latest" + if [ "${TARGET_ARCH}" == "${DEFAULT_ARCH}" ]; then + docker tag "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" "${DOCKER_REPO}:latest" + docker push "${DOCKER_REPO}:latest" + fi + fi + if [ "${TARGET_ARCH}" == "${DEFAULT_ARCH}" ]; then + docker tag "${DOCKER_REPO}:${TARGET_ARCH}-${TAG_BASE}" "${DOCKER_REPO}:${TAG_BASE}" + docker push "${DOCKER_REPO}:${TAG_BASE}" + fi + done +} + # Step 1: Certbot core Docker -Deploy "$DOCKER_HUB_ORG/certbot" "$TAG_BASE" "$WORK_DIR/core" +TagAndPushForAllArch "certbot" # Step 2: Certbot DNS plugins Docker images for plugin in "${CERTBOT_PLUGINS[@]}"; do - Deploy "$DOCKER_HUB_ORG/$plugin" "$TAG_BASE" "$WORK_DIR/plugin" + TagAndPushForAllArch "${plugin}" done diff --git a/tools/docker/lib/common b/tools/docker/lib/common index 0654da54b..1dd62aff4 100644 --- a/tools/docker/lib/common +++ b/tools/docker/lib/common @@ -31,130 +31,3 @@ export CERTBOT_PLUGINS=( "dns-linode" "dns-sakuracloud" ) - -# Returns the translation from Docker to QEMU architecture -# Usage: GetQemuArch [amd64|arm32v6|arm64v8] -GetQemuArch() { - ARCH=$1 - - case "$ARCH" in - "amd64") - 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 -} - -# Executes the QEMU register script -# Usage: RegisterQemuHandlers -RegisterQemuHandlers() { - docker run --rm --privileged multiarch/qemu-user-static:register --reset -} - -# Builds docker certbot core image for a specific architecture. -# Usage: BuildDockerCoreImage [amd64|arm32v6|arm64v8] -BuildDockerCoreImage() { - ARCH=$1 - - QEMU=$(GetQemuArch "$ARCH") - docker build \ - --build-arg TARGET_ARCH="${ARCH}" \ - --build-arg QEMU_ARCH="${QEMU}" \ - -f "${DOCKERFILE_PATH}" \ - -t "${DOCKER_REPO}:${ARCH}-${DOCKER_TAG}" \ - . -} - -# Builds docker certbot plugin image for a specific architecture and tag. -# Usage: BuildDockerPluginImage [amd64|arm32v6|arm64v8] -BuildDockerPluginImage() { - ARCH=$1 - - QEMU=$(GetQemuArch "$ARCH") - BASE_IMAGE="${DOCKER_HUB_ORG}/certbot:${TARGET_ARCH}-${DOCKER_TAG}" - docker build \ - --build-arg BASE_IMAGE="${BASE_IMAGE}" \ - --build-arg QEMU_ARCH="${QEMU}" \ - -f "${DOCKERFILE_PATH}" \ - -t "${DOCKER_REPO}:${ARCH}-${DOCKER_TAG}" \ - . -} - -# Pushes docker image for a specific architecture. -# Usage: BuildDockerCoreImage [amd64|arm32v6|arm64v8] -PushDockerImage() { - ARCH=$1 - - docker push "${DOCKER_REPO}:${ARCH}-${DOCKER_TAG}" -} - -# Creates any docker images aliases for a given architecture. -# If DOCKER_TAG tag is a version tag such as v0.35.0, the "latest" tag is also -# updated. In the case of the default architecture, tags without the -# architecture part are also created. -# As an example, for amd64 (the default architecture) and the tag v0.35.0, the -# following tags would be created: -# - certbot/certbot:v0.35.0 -# - certbot/certbot:latest -# - certbot/certbot:amd64-latest -# For the architecture arm32v6 and the tag v0.35.0, only the following tag -# would be created: -# - certbot/certbot:arm32v6-latest -# For other tags such as "nightly", aliases are only created for the default -# architecture where the tag "nightly" would be used without an architecture -# part. -# Usage: TagDockerImageAliases [amd64|arm32v6|arm64v8] -TagDockerImageAliases() { - ARCH=$1 - - if [[ "${DOCKER_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - docker tag "${DOCKER_REPO}:${ARCH}-${DOCKER_TAG}" "${DOCKER_REPO}:${ARCH}-latest" - if [ "${ARCH}" == "${DEFAULT_ARCH}" ]; then - docker tag "${DOCKER_REPO}:${ARCH}-${DOCKER_TAG}" "${DOCKER_REPO}:latest" - fi - fi - if [ "${ARCH}" == "${DEFAULT_ARCH}" ]; then - docker tag "${DOCKER_REPO}:${ARCH}-${DOCKER_TAG}" "${DOCKER_REPO}:${DOCKER_TAG}" - fi -} - -# Pushes docker images aliases created by the TagDockerImageAliases function. -# Usage: PushDockerImageAliases [amd64|arm32v6|arm64v8] -PushDockerImageAliases() { - ARCH=$1 - - if [[ "${DOCKER_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - docker push "${DOCKER_REPO}:${ARCH}-latest" - if [ "${ARCH}" == "${DEFAULT_ARCH}" ]; then - docker push "${DOCKER_REPO}:latest" - fi - fi - if [ "${ARCH}" == "${DEFAULT_ARCH}" ]; then - docker push "${DOCKER_REPO}:${DOCKER_TAG}" - fi -} diff --git a/tools/docker/plugin/hooks/build b/tools/docker/plugin/hooks/build deleted file mode 100644 index 684be6951..000000000 --- a/tools/docker/plugin/hooks/build +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -ex - -WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -source "$WORK_DIR/../../lib/common" - -for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do - BuildDockerPluginImage "${TARGET_ARCH}" -done diff --git a/tools/docker/plugin/hooks/post_push b/tools/docker/plugin/hooks/post_push deleted file mode 100644 index bc700783e..000000000 --- a/tools/docker/plugin/hooks/post_push +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -ex - -WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -source "$WORK_DIR/../../lib/common" - -for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do - TagDockerImageAliases "${TARGET_ARCH}" - PushDockerImageAliases "${TARGET_ARCH}" -done diff --git a/tools/docker/plugin/hooks/pre_build b/tools/docker/plugin/hooks/pre_build deleted file mode 100644 index 723e35161..000000000 --- a/tools/docker/plugin/hooks/pre_build +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -ex - -WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -source "$WORK_DIR/../../lib/common" - -RegisterQemuHandlers -for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do - DownloadQemuStatic "${TARGET_ARCH}" -done diff --git a/tools/docker/plugin/hooks/push b/tools/docker/plugin/hooks/push deleted file mode 100644 index 0102c5d4d..000000000 --- a/tools/docker/plugin/hooks/push +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -ex - -WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -source "$WORK_DIR/../../lib/common" - -for TARGET_ARCH in "${ALL_TARGET_ARCH[@]}"; do - PushDockerImage "${TARGET_ARCH}" -done