diff --git a/tools/docker/README.md b/tools/docker/README.md index 42b47286d..e346218da 100644 --- a/tools/docker/README.md +++ b/tools/docker/README.md @@ -1 +1,60 @@ -Coming soon: The repository for the [official Certbot images on Docker Hub](https://hub.docker.com/u/certbot) +Certbot-Docker project +====================== + +Goal +---- + +This project is used to publish on DockerHub a new version of the official Certbot Docker, and related Certbot DNS plugins Dockers, upon release of a new version of Certbot. +It leverages the AutoBuild features of DockerHub to coordinate this publication through a continous integration/deployment approach. + +High-level behavior +------------------- + +When a new version tag (eg. v0.35.0) is pushed to this repository, it triggers a new build in each DockerHub project, to construct and publish the new version of the Docker, +containing the Certbot version corresponding to the pushed tag. With the example of the v0.35.0, the DockerHub projects will contain after few minutes a new tag v0.35.0, +whose the Docker contains Certbot v0.35.0. + +Configuration +------------- + +To setup the publication process, the target DockerHub project must be configured appropriately. There are two types of DockerHub projects to take into account: +* the Docker project for Certbot core features (eg. certbot/certbot) +* a Docker project for Certbot DNS plugins (eg. certbot/dns-rfc2136) + +1) Define a GitHub user with push rights to the current GIT repository. +2) Create the DockerHub project if necessary. +3) Activate the AutoBuild feature, using the current GIT repository as source (eg. https.//github.com/certbot/certbot-docker.git) and the user defined in 1). +4) Define a unique tag build rule in AutoBuild configuration: + + _For a Certbot core Docker_ -> Source: `/^(v[0-9.]+).*$/`, Tag: `{\1}`, Dockerfile: `Dockerfile`, Build context: `/core` + + _For a Certbot DNS plugin Docker_ -> Source: `/^(v[0-9.]+).*$/`, Tag: `{\1}`, Dockerfile: `Dockerfile`, Build context: `/plugin` + +Publication worfklow +-------------------- + +Assuming the version to publish is `v0.35.0` + +1) Clone this repository locally, checkout branch `master` and ensure to have a clean workspace. +2) (Optional) Execute `./build.sh v0.35.0` to test the Dockers builds. +3) Execute `./deploy.sh v0.35.0` to trigger the publication of all Dockers with `v0.35.0` version. + +Scripts usage +------------- + +``` +./build.sh [VERSION] +``` + +This script will build locally all Dockers for the given version using the same runtime than DockerHub. +This can be used to test the build process before invoking the actual publication workflow. + +``` +./deploy [VERSION] +``` + +This script will trigger the publication on DockerHub of all Dockers for the given version. To do so, this script: +- update the relevant `README.md` files that will be used as description in the DockerHub repositories, +- commit locally the modifications, +- tag this commit with the given version, +- push this tag and the updated `master` branch. diff --git a/tools/docker/build.sh b/tools/docker/build.sh new file mode 100755 index 000000000..bd1b8ec19 --- /dev/null +++ b/tools/docker/build.sh @@ -0,0 +1,72 @@ +#!/bin/bash +set -euo pipefail +IFS=$'\n\t' + +# This script builds certbot docker and certbot dns plugins docker against a given release version of certbot. +# The build is done following the environment used by Dockerhub to handle its autobuild feature, and so can be +# used as a pre-deployment validation test. + +# Usage: ./build.sh [VERSION] +# with [VERSION] corresponding to a released version of certbot, like `v0.34.0` + +trap Cleanup 1 2 3 6 + +Cleanup() { + if [ ! -z "$WORK_DIR" ]; then + rm -rf "$WORK_DIR/plugin/certbot" || true + rm -rf "$WORK_DIR/core/certbot" || true + fi + popd 2> /dev/null || true +} + +WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +DOCKER_TAG="$1" +SOURCE_BRANCH="$DOCKER_TAG" + +Cleanup + +# Step 1: Certbot core Docker + +DOCKER_REPO="certbot/certbot" +CONTEXT_PATH="$WORK_DIR/core" +DOCKERFILE_PATH="$CONTEXT_PATH/Dockerfile" +IMAGE_NAME="$DOCKER_REPO:$DOCKER_TAG" + +pushd "$CONTEXT_PATH" + DOCKER_TAG="$DOCKER_TAG" DOCKER_REPO="$DOCKER_REPO" DOCKERFILE_PATH="$DOCKERFILE_PATH" IMAGE_NAME="$IMAGE_NAME" bash hooks/build +popd + +Cleanup + +# Step 2: Certbot dns plugins Dockers + +CERTBOT_PLUGINS_DOCKER_REPOS=( + "certbot/dns-dnsmadeeasy" + "certbot/dns-dnsimple" + "certbot/dns-ovh" + "certbot/dns-cloudflare" + "certbot/dns-cloudxns" + "certbot/dns-digitalocean" + "certbot/dns-google" + "certbot/dns-luadns" + "certbot/dns-nsone" + "certbot/dns-rfc2136" + "certbot/dns-route53" + "certbot/dns-gehirn" + "certbot/dns-linode" + "certbot/dns-sakuracloud" +) + +for DOCKER_REPO in ${CERTBOT_PLUGINS_DOCKER_REPOS[@]}; do + CONTEXT_PATH="$WORK_DIR/plugin" + DOCKERFILE_PATH="$CONTEXT_PATH/Dockerfile" + IMAGE_NAME="$DOCKER_REPO:$DOCKER_TAG" + + pushd "$CONTEXT_PATH" + DOCKER_TAG="$DOCKER_TAG" DOCKER_REPO="$DOCKER_REPO" DOCKERFILE_PATH="$DOCKERFILE_PATH" IMAGE_NAME="$IMAGE_NAME" bash hooks/pre_build + DOCKER_TAG="$DOCKER_TAG" DOCKER_REPO="$DOCKER_REPO" DOCKERFILE_PATH="$DOCKERFILE_PATH" IMAGE_NAME="$IMAGE_NAME" bash hooks/build + popd + + Cleanup +done diff --git a/tools/docker/core/Dockerfile b/tools/docker/core/Dockerfile new file mode 100644 index 000000000..044202bda --- /dev/null +++ b/tools/docker/core/Dockerfile @@ -0,0 +1,45 @@ +FROM python:2-alpine3.9 + +ARG CERTBOT_VERSION +ENV CERTBOT_VERSION=${CERTBOT_VERSION} + +ENTRYPOINT [ "certbot" ] +EXPOSE 80 443 +VOLUME /etc/letsencrypt /var/lib/letsencrypt +WORKDIR /opt/certbot + +# Retrieve certbot code +RUN mkdir -p src \ + && wget -O certbot-${CERTBOT_VERSION}.tar.gz https://github.com/certbot/certbot/archive/v${CERTBOT_VERSION}.tar.gz \ + && tar xf certbot-${CERTBOT_VERSION}.tar.gz \ + && cp certbot-${CERTBOT_VERSION}/CHANGELOG.md certbot-${CERTBOT_VERSION}/README.rst certbot-${CERTBOT_VERSION}/setup.py src/ \ + && cp certbot-${CERTBOT_VERSION}/letsencrypt-auto-source/pieces/dependency-requirements.txt . \ + && cp -r certbot-${CERTBOT_VERSION}/tools tools \ + && cp -r certbot-${CERTBOT_VERSION}/acme src/acme \ + && cp -r certbot-${CERTBOT_VERSION}/certbot src/certbot \ + && rm -rf certbot-${CERTBOT_VERSION}.tar.gz certbot-${CERTBOT_VERSION} + +# Generate constraints file to pin dependency versions +RUN cat dependency-requirements.txt | tools/strip_hashes.py > unhashed_requirements.txt \ + && cat tools/dev_constraints.txt unhashed_requirements.txt | tools/merge_requirements.py > docker_constraints.txt + +# Install certbot runtime dependencies +RUN apk add --no-cache --virtual .certbot-deps \ + libffi \ + libssl1.1 \ + openssl \ + ca-certificates \ + binutils + +# Install certbot from sources +RUN apk add --no-cache --virtual .build-deps \ + gcc \ + linux-headers \ + openssl-dev \ + musl-dev \ + libffi-dev \ + && pip install -r dependency-requirements.txt \ + && pip install --no-cache-dir --no-deps \ + --editable src/acme \ + --editable src \ +&& apk del .build-deps diff --git a/tools/docker/core/README.md b/tools/docker/core/README.md new file mode 100644 index 000000000..6c7312951 --- /dev/null +++ b/tools/docker/core/README.md @@ -0,0 +1,26 @@ +# ![](https://certbot.eff.org/images/certbot-logo-1A.svg) +[![](https://img.shields.io/badge/current-v0.34.1-blue.svg)](https://github.com/certbot/certbot.git)   [![](https://travis-ci.com/certbot/certbot.svg?branch=0.34.x)](https://travis-ci.com/certbot/certbot) + +This is the Docker repository for Certbot Core. + +## Certbot DNS plugins + +* [dns-dnsmadeeasy](https://hub.docker.com/r/certbot/dns-dnsmadeeasy) +* [dns-dnsimple](https://hub.docker.com/r/certbot/dns-dnsimple) +* [dns-ovh](https://hub.docker.com/r/certbot/dns-ovh) +* [dns-cloudflare](https://hub.docker.com/r/certbot/dns-cloudflare) +* [dns-cloudxns](https://hub.docker.com/r/certbot/dns-cloudxns) +* [dns-digitalocean](https://hub.docker.com/r/certbot/dns-digitalocean) +* [dns-google](https://hub.docker.com/r/certbot/dns-google) +* [dns-luadns](https://hub.docker.com/r/certbot/dns-luadns) +* [dns-nsone](https://hub.docker.com/r/certbot/dns-nsone) +* [dns-rfc2136](https://hub.docker.com/r/certbot/dns-rfc2136) +* [dns-route53](https://hub.docker.com/r/certbot/dns-route53) +* [dns-gehirn](https://hub.docker.com/r/certbot/dns-gehirn) +* [dns-linode](https://hub.docker.com/r/certbot/dns-linode) +* [dns-sakuracloud](https://hub.docker.com/r/certbot/dns-sakuracloud) + +## Sources: + +* [docker](https://www.github.com/certbot/certbot-docker.git) +* [certbot](https://www.github.com/certbot/certbot.git) diff --git a/tools/docker/core/hooks/build b/tools/docker/core/hooks/build new file mode 100644 index 000000000..e0e4d6571 --- /dev/null +++ b/tools/docker/core/hooks/build @@ -0,0 +1,5 @@ +#!/bin/bash +set -ex + +CERTBOT_VERSION=${DOCKER_TAG//v/} +docker build --build-arg CERTBOT_VERSION=${CERTBOT_VERSION} -f ${DOCKERFILE_PATH} -t ${IMAGE_NAME} . diff --git a/tools/docker/core/hooks/post_push b/tools/docker/core/hooks/post_push new file mode 100644 index 000000000..6b8459521 --- /dev/null +++ b/tools/docker/core/hooks/post_push @@ -0,0 +1,5 @@ +#!/bin/bash +set -ex + +docker tag ${IMAGE_NAME} "${DOCKER_REPO}:latest" +docker push "${DOCKER_REPO}:latest" diff --git a/tools/docker/deploy.sh b/tools/docker/deploy.sh new file mode 100644 index 000000000..e6960f67d --- /dev/null +++ b/tools/docker/deploy.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -euo pipefail +IFS=$'\n\t' + +# This script deploys a new version of certbot dockers (core+plugins) regarding a released version of Certbot. +# The README.md is updated to include the reference of this new version, and a tag version is pushed to the +# Certbot Docker repository, triggering the DockerHub autobuild feature that will take care of the release. + +# Usage: ./deploy.sh [VERSION] +# with [VERSION] corresponding to a released version of certbot, like `v0.34.0` + +trap Cleanup 1 2 3 6 + +Cleanup() { + popd 2> /dev/null || true +} + +WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +CERTBOT_DOCKER_VERSION="$1" # Eg. v0.35.0 or v0.35.0-1 +CERTBOT_VERSION=$(sed -E -e 's|(v[0-9+]\.[0-9]+\.[0-9]+).*|\1|g' <<< $CERTBOT_DOCKER_VERSION) # Eg. v0.35.0 +BRANCH_NAME=$(sed -E -e 's|v(.*)\.[0-9]+|\1.x|g' <<< $CERTBOT_VERSION) # Eg. 0.35.x + +sed -i -e "s|current-.*-blue\.svg|current-$CERTBOT_VERSION-blue.svg|g" core/README.md +sed -i -e "s|branch=.*)\]|branch=$BRANCH_NAME)]|g" core/README.md + +sed -i -e "s|current-.*-blue\.svg|current-$CERTBOT_VERSION-blue.svg|g" plugin/README.md +sed -i -e "s|branch=.*)\]|branch=$BRANCH_NAME)]|g" plugin/README.md + +pushd "$WORK_DIR" + git commit -a -m "Release version $CERTBOT_DOCKER_VERSION" --allow-empty + git tag "$CERTBOT_DOCKER_VERSION" + git push + git push --tags +popd diff --git a/tools/docker/plugin/Dockerfile b/tools/docker/plugin/Dockerfile new file mode 100644 index 000000000..f249a64e6 --- /dev/null +++ b/tools/docker/plugin/Dockerfile @@ -0,0 +1,12 @@ +FROM certbot/certbot + +ARG PLUGIN_NAME + +# Retrieve Certbot DNS plugin code +RUN wget -O certbot-${CERTBOT_VERSION}.tar.gz https://github.com/certbot/certbot/archive/v${CERTBOT_VERSION}.tar.gz \ + && tar xf certbot-${CERTBOT_VERSION}.tar.gz \ + && cp -r certbot-${CERTBOT_VERSION}/certbot-${PLUGIN_NAME} /opt/certbot/src/certbot-${PLUGIN_NAME} \ + && rm -rf certbot-${CERTBOT_VERSION}.tar.gz certbot-${CERTBOT_VERSION} + +# Install the DNS plugin +RUN pip install --constraint /opt/certbot/docker_constraints.txt --no-cache-dir --editable /opt/certbot/src/certbot-${PLUGIN_NAME} diff --git a/tools/docker/plugin/README.md b/tools/docker/plugin/README.md new file mode 100644 index 000000000..362f4a029 --- /dev/null +++ b/tools/docker/plugin/README.md @@ -0,0 +1,13 @@ +# ![](https://certbot.eff.org/images/certbot-logo-1A.svg) +[![](https://img.shields.io/badge/current-v0.34.1-blue.svg)](https://github.com/certbot/certbot.git)   [![](https://travis-ci.com/certbot/certbot.svg?branch=0.34.x)](https://travis-ci.com/certbot/certbot) + +This is one of the Docker repository for the Certbot DNS plugins. + +## Certbot Core + +* [certbot](https://hub.docker.com/r/certbot/certbot) + +## Sources: + +* [docker](https://www.github.com/certbot/certbot-docker.git) +* [certbot](https://www.github.com/certbot/certbot.git) diff --git a/tools/docker/plugin/hooks/build b/tools/docker/plugin/hooks/build new file mode 100644 index 000000000..435b1d42b --- /dev/null +++ b/tools/docker/plugin/hooks/build @@ -0,0 +1,5 @@ +#!/bin/bash +set -ex + +PLUGIN_NAME=${DOCKER_REPO//*\//} +docker build --build-arg PLUGIN_NAME=${PLUGIN_NAME} -f ${DOCKERFILE_PATH} -t ${IMAGE_NAME} . diff --git a/tools/docker/plugin/hooks/post_push b/tools/docker/plugin/hooks/post_push new file mode 100644 index 000000000..6b8459521 --- /dev/null +++ b/tools/docker/plugin/hooks/post_push @@ -0,0 +1,5 @@ +#!/bin/bash +set -ex + +docker tag ${IMAGE_NAME} "${DOCKER_REPO}:latest" +docker push "${DOCKER_REPO}:latest" diff --git a/tools/docker/plugin/hooks/pre_build b/tools/docker/plugin/hooks/pre_build new file mode 100644 index 000000000..22c582758 --- /dev/null +++ b/tools/docker/plugin/hooks/pre_build @@ -0,0 +1,5 @@ +#!/bin/bash +set -ex + +CERTBOT_VERSION=${DOCKER_TAG//v/} +docker build --build-arg CERTBOT_VERSION=${CERTBOT_VERSION} -f ../core/Dockerfile -t certbot/certbot ../core