diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 000000000..7e6d2dfe5 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,43 @@ +# This Dockerfile creates a production release image for the project. This +# downloads the release from releases.hashicorp.com and therefore requires that +# the release is published before building the Docker image. +# +# We don't rebuild the software because we want the exact checksums and +# binary signatures to match the software and our builds aren't fully +# reproducible currently. +FROM alpine:3 + +# NAME and VERSION are the name of the software in releases.hashicorp.com +# and the version to download. +ARG NAME=consul-template +ARG VERSION + +# version label is required for build process +LABEL maintainer="John Eikenberry <jae@zhar.net>" +LABEL version=$VERSION + +# UID and GID of consul-template user and group. +# These are the defaults, this makes them explicit and overridable. +ARG UID=100 +ARG GID=1000 + +# Set ARGs as ENV so that they can be used in ENTRYPOINT/CMD +ENV NAME=${NAME} +ENV VERSION=${VERSION} + +# This is the location of the releases. +ENV HASHICORP_RELEASES=https://releases.hashicorp.com + +# Create a user and group first so the IDs get set the same way, +# even as the rest of this may change over time. +RUN addgroup -g ${GID} ${NAME} && adduser -u ${UID} -S -G ${NAME} ${NAME} + +# Set up certificates, base tools, and software. +COPY fetch-n-verify.sh docker-entrypoint.sh / +RUN /fetch-n-verify.sh # removes self when done + +ENTRYPOINT ["/docker-entrypoint.sh"] + +USER ${NAME}:${NAME} +CMD /bin/${NAME} + diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh new file mode 100755 index 000000000..344daf7b7 --- /dev/null +++ b/docker/docker-entrypoint.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# Don't use dumb-init as it isn't required and the end-user has the option +# to set it via the `--init` option. + +set -e + +# If the user is trying to run consul-template directly with some arguments, +# then pass them to consul-template. +# On alpine /bin/sh is busybox which supports this bashism. +if [ "${1:0:1}" = '-' ] +then + set -- /bin/consul-template "$@" +fi + +# MUST exec here for consul-template to replace the shell as PID 1 in order +# to properly propagate signals from the OS to the consul-template process. +exec "$@" diff --git a/docker/fetch-n-verify.sh b/docker/fetch-n-verify.sh new file mode 100755 index 000000000..a200921b7 --- /dev/null +++ b/docker/fetch-n-verify.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# requires environment variables.. +# +# HASHICORP_RELEASES - URL for releases +# NAME - application's name +# VERSION - application version (eg. 1.2.3) + +set -eux +apk add --no-cache ca-certificates gnupg + +BUILD_GPGKEY=C874011F0AB405110D02105534365D9472D7468F +found='' + +for server in \ + hkp://p80.pool.sks-keyservers.net:80 \ + hkp://keyserver.ubuntu.com:80 \ + hkp://pgp.mit.edu:80 \ +; do + echo "Fetching GPG key $BUILD_GPGKEY from $server"; + gpg --keyserver "$server" --recv-keys "$BUILD_GPGKEY" && found=yes && break; +done + +test -z "$found" && echo >&2 "error: failed to fetch GPG key $BUILD_GPGKEY" && exit 1 +mkdir -p /tmp/build && cd /tmp/build + +apkArch="$(apk --print-arch)" +case "${apkArch}" in \ + aarch64) ARCH='arm64' ;; + armhf) ARCH='armhfv6' ;; + x86) ARCH='386' ;; + x86_64) ARCH='amd64' ;; + *) echo >&2 "error: unsupported architecture: ${apkArch} (see ${HASHICORP_RELEASES}/${NAME}/${VERSION}/)" && exit 1 ;; +esac + +wget ${HASHICORP_RELEASES}/${NAME}/${VERSION}/${NAME}_${VERSION}_linux_${ARCH}.zip +wget ${HASHICORP_RELEASES}/${NAME}/${VERSION}/${NAME}_${VERSION}_SHA256SUMS +wget ${HASHICORP_RELEASES}/${NAME}/${VERSION}/${NAME}_${VERSION}_SHA256SUMS.sig +gpg --batch --verify ${NAME}_${VERSION}_SHA256SUMS.sig ${NAME}_${VERSION}_SHA256SUMS +grep ${NAME}_${VERSION}_linux_${ARCH}.zip ${NAME}_${VERSION}_SHA256SUMS | sha256sum -c +unzip -d /bin ${NAME}_${VERSION}_linux_${ARCH}.zip + +apk del gnupg +cd /tmp +rm -rf /tmp/build +rm -rf /root/.gnupg +rm "$0"