diff --git a/.github/workflows/on-tag.yml b/.github/workflows/on-tag.yml index 9f5ea6c..39216f7 100644 --- a/.github/workflows/on-tag.yml +++ b/.github/workflows/on-tag.yml @@ -1,162 +1,204 @@ -name: Build & deploy Bitcoind +name: Build & deploy on git tag push + +env: + APP: bitcoind + + # Capture groups within $TAG_FMT: + # \1 => TAG vX.Y.Z[.P]+build + # \2 => VERSION vX.Y.Z[.P] + # \3 => ignore (captures dot, and last number-group in version) + # \4 => BUILD N + TAG_FMT: '^refs/tags/((v(.?[0-9]+){3,4})\+build([0-9]+))$' + on: push: - tags: - - '*' + tags: [ '*' ] jobs: build: - name: Build Bitcoind + name: Build bitcoind runs-on: ubuntu-18.04 + strategy: + matrix: + arch: + - amd64 + - arm32v7 + - arm64v8 + env: QEMU_VERSION: v4.2.0 DOCKER_BUILDKIT: 1 - strategy: - matrix: - arch: - - arm32v7 - - arm64 - - amd64 - steps: - - uses: actions/checkout@v1.0.0 + - uses: actions/checkout@v2 - name: Setup environment run: | - VERSION="$(echo "${GITHUB_REF}" | awk -F/ '{print $NF}' | tr -d v)" + if ! echo "$GITHUB_REF" | grep -qE "$TAG_FMT"; then + echo "ERR: TAG must be in format: vX.Y.Z[.P]+build" + exit 1 + fi - echo ::set-env name=VERSION::"${VERSION}" - echo ::set-env name=DIR::"$(echo "${VERSION}" | cut -d. -f-2)" + DIR="$(echo "${VERSION#v}" | cut -d. -f-2)" + + VERSION="$(echo "$GITHUB_REF" | sed -E "s|$TAG_FMT|\2|")" + if ! grep -q "^ARG VERSION=${VERSION#v}$" "$DIR/Dockerfile"; then + echo "ERR: $DIR/Dockerfile must contain VERSION=$VERSION" + exit 1 + fi + + echo ::set-env name=DIR::"$DIR" + + echo ::set-env name=TAG::"$(echo "$GITHUB_REF" | sed -E "s|$TAG_FMT|\1|")" + echo ::set-env name=BUILD::"$(echo "$GITHUB_REF" | sed -E "s|$TAG_FMT|\4|")" + + - name: Print ENV VARs set above + run: | + printf " APP: %s\n" "$APP" + printf " ARCH: %s\n" "${{ matrix.arch }}" + printf " TAG: %s\n" "$TAG" + printf " DIR: %s\n" "$DIR" + printf " BUILD: %s\n" "$BUILD" - name: Register self-compiled qemu if: matrix.arch != 'amd64' - run: docker run --rm --privileged "meedamian/simple-qemu:${QEMU_VERSION}-${{matrix.arch}}" -p yes + run: docker run --rm --privileged "meedamian/simple-qemu:$QEMU_VERSION-${{ matrix.arch }}" -p yes - # Alter `Dockerfile` to reference used architecture/image combos explicitly. Places changed are: - # * all `FROM` statements (ex. `FROM alpine…` -> `FROM arm64v8/alpine…`) - # * BerkeleyDB `COPY` statement (`COPY --from=lncm/berkeleydb:db-4.8.30.NC` gets suffixed with ex. `-arm64`) - # `sed` `--expression`s change it in the following way: - # 1st: Matches all occurrences of `FROM alpine`, and injects arch prefix before `alpine`, ex: `arm64v8/alpine` - # 2nd: Matches BDB version, and appends "-${{matrix.arch}}" to it (note that `&` represents match). - - name: Change Dockerfile to use arch-specific base images - if: matrix.arch != 'amd64' + - name: Build ${{ env.APP }} + run: > + docker build --no-cache "$DIR/" + --build-arg "ARCH=${{ matrix.arch }}" + --label "arch=${{ matrix.arch }}" + --label "commit=${{ github.sha }}" + --label "git-tag=$TAG" + --label "guilty=${{ github.actor }}" + --label "repo-url=${{ github.repositoryUrl }}" + --tag "$APP" + + - name: Show built image details + run: docker images "$APP" + + - name: Run sanity checks + env: + DIR: /usr/local/bin + MINOR: ${{ env.DIR }} run: | - CPU="${{matrix.arch}}" - if [[ "${CPU}" == "arm64" ]]; then - CPU="arm64v8" + run() { + ENTRYPOINT="${1:-$APP}"; shift + ARGS=${*:-"--version"} + + printf "\n$ %s %s\n" "$ENTRYPOINT" "$ARGS" + docker run --rm --entrypoint "$ENTRYPOINT" "$APP" $ARGS + } + + docker inspect "$APP" | jq '.' + printf "\n" + + run bitcoind | head -n 1 + run bitcoin-cli + run bitcoin-tx --help | head -n 1 + + # If version higher, or equal than v0.18.0, also run `bitcoin-wallet` binary + if [ "${MINOR#0.}" -ge "18" ]; then + run bitcoin-wallet --help | head -n 1 fi - sed -i ${DIR}/Dockerfile \ - -e "s|^FROM alpine|FROM $CPU/alpine|g" \ - -e "s|db-4.8.30.NC|&-${{matrix.arch}}|g" - - - name: Build Bitcoind - run: > - docker build ${DIR}/ - --build-arg "VERSION=${VERSION}" - --tag bitcoind - - - name: Print OS info - run: docker run --rm --entrypoint=uname bitcoind -a - - - name: Print Bitcoind version - run: docker run --rm bitcoind --version + run uname -a + run cat /etc/os-release + run sha256sum "$DIR/bitcoind" "$DIR/bitcoin-cli" - name: Save built image into a .tgz file run: | mkdir -p images/ - docker tag bitcoind "bitcoind:${{matrix.arch}}" - docker save "bitcoind:${{matrix.arch}}" | gzip > "images/bitcoind-${{matrix.arch}}.tgz" + docker tag "$APP" "$APP:${{ matrix.arch }}" + docker save "$APP:${{ matrix.arch }}" | gzip > "images/docker-$APP-$TAG-${{ matrix.arch }}.tgz" - name: Print sha256sum of built image run: sha256sum images/* - - name: Upload built image + - name: Upload docker image as build artifact uses: actions/upload-artifact@v1.0.0 with: - name: images + name: docker-images path: images/ - docker-hub-push: - name: Tag & deploy to Docker Hub. Only after successful build and on a git-tag push + deploy: + name: Deploy to Docker Hub & Github Releases. Only after successful build. runs-on: ubuntu-18.04 needs: build - steps: - - uses: actions/checkout@v1.0.0 + env: + DOCKER_CLI_EXPERIMENTAL: enabled + + steps: - name: Setup environment run: | - echo ::set-env name=DOCKER_USER::"${GITHUB_ACTOR,,}" echo ::set-env name=SLUG::"$(echo ${GITHUB_REPOSITORY,,} | sed 's/docker-//')" - echo ::set-env name=VERSION::"$(echo "${GITHUB_REF}" | awk -F/ '{print $NF}')" - - - name: Enable manifests - run: | - mkdir -p ~/.docker - - echo '{ "experimental": "enabled" }' > ~/.docker/config.json - sudo systemctl restart docker - docker version - - - name: Login to Docker Hub - run: | - echo "Logging in as ${DOCKER_USER}…" - echo "${{secrets.DOCKER_TOKEN}}" | docker login -u="${DOCKER_USER}" --password-stdin + echo ::set-env name=VERSION::"$(echo "$GITHUB_REF" | sed -E "s|$TAG_FMT|\2|")" + echo ::set-env name=BUILD::"$(echo "$GITHUB_REF" | sed -E "s|$TAG_FMT|\4|")" - name: Download all build artifacts uses: actions/download-artifact@v1.0.0 with: - name: images + name: docker-images - - name: Print sha256sum of all images - run: sha256sum images/* + - name: Print sha256sum of downloaded images + run: sha256sum docker-images/* - name: Load images locally - run: ls images/ | xargs -I % docker load -i "images/%" + run: find docker-images -exec docker load -i "{}" \; - # No short tags. IMO bitcoind version should always be specified exactly, and explicitly. + # No short tags. - name: Version-tag all images - run: docker images bitcoind --format "{{.Tag}}" | xargs -I % docker tag "bitcoind:%" "${SLUG}:${VERSION}-%" + run: | + for arch in $(docker images "$APP" --format "{{.Tag}}"); do + docker tag "$APP:$arch" "$SLUG:$VERSION-$arch-build$BUILD" + docker tag "$APP:$arch" "$SLUG:$VERSION-$arch" + done - name: List all tagged images - run: docker images "${SLUG}" + run: docker images "$SLUG" + + - name: Login to Docker Hub + env: + DOCKER_USER: meedamian + run: | + echo "Logging in as ${DOCKER_USER}…" + echo "${{ secrets.DOCKER_TOKEN }}" | docker login -u="$DOCKER_USER" --password-stdin - name: Push all images - run: docker images "${SLUG}" --format "{{.Repository}}:{{.Tag}}" | xargs -I % docker push % + run: docker images "$SLUG" --format "{{.Repository}}:{{.Tag}}" | xargs -I % docker push % - name: Create manifest run: > - docker -D manifest create "${SLUG}:${VERSION}" \ - "${SLUG}:${VERSION}-amd64" \ - "${SLUG}:${VERSION}-arm64" \ - "${SLUG}:${VERSION}-arm32v7" + docker -D manifest create "$SLUG:$VERSION" \ + "$SLUG:$VERSION-amd64" \ + "$SLUG:$VERSION-arm32v7" \ + "$SLUG:$VERSION-arm64v8" - - name: Annotate arm32v7 - run: docker manifest annotate "${SLUG}:${VERSION}" "${SLUG}:${VERSION}-arm32v7" --os linux --arch arm --variant v7 + - name: Annotate images for manifest + run: | + docker manifest annotate "$SLUG:$VERSION" "$SLUG:$VERSION-arm32v7" --os linux --arch arm --variant v7 + docker manifest annotate "$SLUG:$VERSION" "$SLUG:$VERSION-arm64v8" --os linux --arch arm64 --variant v8 - - name: Annotate arm64v8 - run: docker manifest annotate "${SLUG}:${VERSION}" "${SLUG}:${VERSION}-arm64" --os linux --arch arm64 --variant v8 + - name: Print manifest details + run: docker manifest inspect "$SLUG:$VERSION" | jq '.' - name: Push manifest - run: docker manifest push "${SLUG}:${VERSION}" + run: docker manifest push "$SLUG:$VERSION" - - name: Sync README.md and Description to Docker Hub - uses: meeDamian/sync-readme@v1.0.5 - with: - pass: ${{secrets.DOCKER_TOKEN}} - slug: lncm/bitcoind - description: true - name: Upload images to Github Release uses: meeDamian/github-release@v1.0.1 with: - token: ${{secrets.GITHUB_TOKEN}} + token: ${{ secrets.GITHUB_TOKEN }} + name: ${{ env.VERSION }} + body: "This release packages `bitcoind` to be on par with https://github.com/bitcoin/bitcoin/releases/tag/${{ env.VERSION }}" gzip: false files: images/* diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml deleted file mode 100644 index 953441b..0000000 --- a/.github/workflows/pull-request.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Build bitcoind on pull request - -on: pull_request - -jobs: - build: - name: Build Bitcoind - runs-on: ubuntu-18.04 - - env: - DOCKER_BUILDKIT: 1 - - strategy: - fail-fast: false - matrix: - subver: - - '0.16' - - '0.17' - - '0.18' - - '0.19' - - steps: - - uses: actions/checkout@v1.0.0 - - - name: Build Bitcoind - run: docker build -t bitcoind ${{matrix.subver}}/ - - - name: Print Bitcoind version - run: | - docker run --rm --entrypoint=uname bitcoind -a - docker run --rm bitcoind --version diff --git a/.github/workflows/qemu-perf.yml b/.github/workflows/qemu-perf.yml index 4619ea6..35ff8c9 100644 --- a/.github/workflows/qemu-perf.yml +++ b/.github/workflows/qemu-perf.yml @@ -1,21 +1,22 @@ name: Perf-check qemu versions +env: + APP: bitcoind + on: + push: + branches: [ 'perf' ] schedule: - cron: '2 1 * * *' - push: - branches: - - 'perf' - jobs: build: - name: Build + name: Build & measure time runs-on: ubuntu-18.04 env: DOCKER_BUILDKIT: 1 - SUBVER: 0.19 + MINOR: 0.19 strategy: fail-fast: false @@ -24,47 +25,49 @@ jobs: - v3.1.0 - v3.1.1 - v4.0.0 + - v4.0.1 - v4.1.0 - v4.1.1 - v4.2.0 arch: - arm32v7 - - arm64 + - arm64v8 steps: - - uses: actions/checkout@v1.0.0 + - uses: actions/checkout@v2 - name: Log start time run: touch /tmp/start - name: Register self-compiled qemu - run: docker run --rm --privileged meedamian/simple-qemu:${{matrix.qemu}}-${{matrix.arch}} -p yes - - # Alter `Dockerfile` to reference used architecture/image combos explicitly. Places changed are: - # * all `FROM` statements (ex. `FROM alpine…` -> `FROM arm64v8/alpine…`) - # * BerkeleyDB `COPY` statement (`COPY --from=lncm/berkeleydb:db-4.8.30.NC` gets suffixed with ex. `-arm64`) - # `sed` `--expression`s change it in the following way: - # 1st: Matches all occurrences of `FROM alpine`, and injects arch prefix before `alpine`, ex: `arm64v8/alpine` - # 2nd: Matches BDB version, and appends "-${{matrix.arch}}" to it (note that `&` represents match). - - name: Change Dockerfile to use arch-specific base images - run: | - CPU=${{matrix.arch}} - if [[ "${CPU}" == "arm64" ]]; then - CPU="arm64v8" - fi - - sed -i ${SUBVER}/Dockerfile \ - -e "s|^FROM alpine|FROM $CPU/alpine|g" \ - -e "s|db-4.8.30.NC|&-${{matrix.arch}}|g" + run: docker run --rm --privileged "meedamian/simple-qemu:${{ matrix.qemu }}-${{ matrix.arch }}" -p yes - name: Build container - run: docker build -t bitcoind ${SUBVER}/ + run: > + docker build "$MINOR/" + --build-arg "ARCH=${{ matrix.arch }}" + --tag "$APP" - - name: Print Bitcoind version + - name: Make sure binaries can be run run: | - docker run --rm --entrypoint=uname bitcoind -a - docker run --rm bitcoind --version + run() { + ENTRYPOINT="${1:-$APP}"; shift + ARGS=${*:-"--version"} + + printf "\n$ %s %s\n" "$ENTRYPOINT" "$ARGS" + docker run --rm --entrypoint "$ENTRYPOINT" "$APP" $ARGS + } + + run uname -a + run bitcoind + run bitcoin-cli + run bitcoin-tx --help | head -n 1 + + # If version higher, or equal than v0.18.0, also run `bitcoin-wallet` binary + if [ "${MINOR#0.}" -ge "18" ]; then + run bitcoin-wallet --help | head -n 1 + fi - name: Calculate execution time run: | @@ -84,16 +87,16 @@ jobs: days=$(( DIFF / DAY )) OUT="" - if [[ "${days}" -ne "0" ]]; then + if [[ "$days" -ne "0" ]]; then # Days-long jobs shouldn't happen, but 🤷🏻‍♂️ OUT="${days}d " fi - OUT="${OUT}${hours}h:${mins}m:${secs}s" + OUT="$OUT${hours}h:${mins}m:${secs}s" mkdir -p stat - echo "${OUT}" > stat/${{matrix.qemu}}-${{matrix.arch}} + echo "$OUT" > stat/${{ matrix.qemu }}-${{ matrix.arch }} - name: Save execution time as an artifact uses: actions/upload-artifact@v1.0.0 @@ -103,8 +106,10 @@ jobs: comment: name: Report result + needs: build runs-on: ubuntu-18.04 + steps: - name: Download perf stats uses: actions/download-artifact@v1.0.0 @@ -115,25 +120,25 @@ jobs: run: | touch ./all-stats - echo "| version | arm32v7 | arm64" >> ./all-stats - echo "|:-------:|--------:|-----:" >> ./all-stats + echo "| version | arm32v7 | arm64v8" >> ./all-stats + echo "|:-------:|--------:|--------:" >> ./all-stats for ver in $(ls ./stats/* | awk -F/ '{print $NF}' | cut -d- -f1 | uniq); do line="| **${ver}**" - line="${line} | $(cat ./stats/${ver}-arm32v7 | tr -d '\n')" - line="${line} | $(cat ./stats/${ver}-arm64 | tr -d '\n')" + line="$line | $(cat "./stats/$ver-arm32v7" | tr -d '\n')" + line="$line | $(cat "./stats/$ver-arm64v8" | tr -d '\n')" - echo "${line}" >> ./all-stats + echo "$line" >> ./all-stats done cat ./all-stats echo ::set-env name=RESULTS::"$(cat ./all-stats | sed -z 's/\n/\\n/g')" - - uses: actions/github-script@0.4.0 + - uses: actions/github-script@0.8.0 with: - github-token: ${{secrets.GITHUB_TOKEN_NOEXPIRE}} + github-token: ${{ secrets.GITHUB_TOKEN_NOEXPIRE }} script: | github.issues.createComment({ owner: 'lncm', diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2d200c4..a232adc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,66 +1,78 @@ -name: Build bitcoind on master push +name: Build bitcoind on push, or PR to master + +env: + APP: bitcoind on: push: - branches: - - master + branches: [ 'master' ] + pull_request: + branches: [ 'master' ] jobs: build: - name: Build Bitcoind + name: Build bitcoind runs-on: ubuntu-18.04 - env: - QEMU_VERSION: v4.2.0 - DOCKER_BUILDKIT: 1 - strategy: fail-fast: false matrix: subver: - - '0.16' - - '0.17' - - '0.18' - - '0.19' + - 0.16 + - 0.17 + - 0.18 + - 0.19 arch: - - arm32v7 - - arm64 - amd64 + - arm32v7 + - arm64v8 + + env: + QEMU_VERSION: v4.2.0 + DOCKER_BUILDKIT: 1 steps: - - uses: actions/checkout@v1.0.0 + - uses: actions/checkout@v2 - name: Register self-compiled qemu if: matrix.arch != 'amd64' - run: docker run --rm --privileged meedamian/simple-qemu:${QEMU_VERSION}-${{matrix.arch}} -p yes + run: docker run --rm --privileged "meedamian/simple-qemu:$QEMU_VERSION-${{ matrix.arch }}" -p yes - # Alter `Dockerfile` to reference used architecture/image combos explicitly. Places changed are: - # * all `FROM` statements (ex. `FROM alpine…` -> `FROM arm64v8/alpine…`) - # * BerkeleyDB `COPY` statement (`COPY --from=lncm/berkeleydb:db-4.8.30.NC` gets suffixed with ex. `-arm64`) - # `sed` `--expression`s change it in the following way: - # 1st: Matches all occurrences of `FROM alpine`, and injects arch prefix before `alpine`, ex: `arm64v8/alpine` - # 2nd: Matches BDB version, and appends "-${{matrix.arch}}" to it (note that `&` represents match). - - name: Change Dockerfile to use arch-specific base images - if: matrix.arch != 'amd64' + - name: Build ${{ env.APP }} + run: > + docker build "${{ matrix.subver }}/" + --build-arg "ARCH=${{ matrix.arch }}" + --tag "$APP" + + - name: Show built image details + run: docker images "$APP" + + - name: Run sanity checks + env: + DIR: /usr/local/bin + MINOR: ${{ matrix.subver }} run: | - CPU=${{matrix.arch}} - if [[ "${CPU}" == "arm64" ]]; then - CPU="arm64v8" + run() { + ENTRYPOINT="${1:-$APP}"; shift + ARGS=${*:-"--version"} + + printf "\n$ %s %s\n" "$ENTRYPOINT" "$ARGS" + docker run --rm --entrypoint "$ENTRYPOINT" "$APP" $ARGS + } + + docker inspect "$APP" | jq '.' + printf "\n" + + run bitcoind | head -n 1 + run bitcoin-cli + run bitcoin-tx --help | head -n 1 + + # If version higher, or equal than v0.18.0, also run `bitcoin-wallet` binary + if [ "${MINOR#0.}" -ge "18" ]; then + run bitcoin-wallet --help | head -n 1 fi - sed -i ${{matrix.subver}}/Dockerfile \ - -e "s|^FROM alpine|FROM $CPU/alpine|g" \ - -e "s|db-4.8.30.NC|&-${{matrix.arch}}|g" - - # NOTE: Don't build 32-bit version of 0.17.1, as it's broken & non-essential: - # https://github.com/bitcoin/bitcoin/pull/15950 - - name: Build Bitcoind - if: matrix.subver != '0.17' || matrix.arch != 'arm32v7' - run: docker build -t bitcoind ${{matrix.subver}}/ - - - name: Print Bitcoind version - if: matrix.subver != '0.17' || matrix.arch != 'arm32v7' - run: | - docker run --rm --entrypoint=uname bitcoind -a - docker run --rm bitcoind --version + run uname -a + run cat /etc/os-release + run sha256sum "$DIR/bitcoind" "$DIR/bitcoin-cli" diff --git a/.github/workflows/update-readme.yml b/.github/workflows/update-readme.yml new file mode 100644 index 0000000..cc97a2f --- /dev/null +++ b/.github/workflows/update-readme.yml @@ -0,0 +1,27 @@ +name: Update Docker Hub README everytime it changes on master + +on: + push: + branches: [ 'master' ] + paths: + - README.md + - '.github/workflows/update-readme.yml' + +jobs: + sync: + name: Update README to Docker Hub + runs-on: ubuntu-18.04 + + steps: + - uses: actions/checkout@v2 + + - name: Setup Environment + run: echo ::set-env name=SLUG::"$(echo ${GITHUB_REPOSITORY,,} | sed 's/docker-//')" + + - name: Sync README.md and Description to Docker Hub + uses: meeDamian/sync-readme@v1.0.6 + with: + user: ${{ secrets.DOCKER_USER }} + pass: ${{ secrets.DOCKER_PASS }} + slug: ${{ env.SLUG }} + description: true diff --git a/0.16/Dockerfile b/0.16/Dockerfile index 08f9189..f543199 100644 --- a/0.16/Dockerfile +++ b/0.16/Dockerfile @@ -1,15 +1,139 @@ -FROM alpine:3.10 AS bitcoin-core +# This Dockerfile builds Bitcoin Core and packages it into a minimal `final` image + +# VERSION of Bitcoin Core to be build +# NOTE: Unlike our other images this one is NOT prefixed with `v`, +# as many things (like download URLs) use this form instead. +ARG VERSION=0.16.3 + +# CPU archtecture to build binaries for +ARG ARCH + +# Define default versions so that they don't have to be repreated throughout the file +ARG VER_ALPINE=3.11 + +# $USER name, and data $DIR to be used in the `final` image +ARG USER=bitcoind +ARG DIR=/data + +# Choose where to get bitcoind sources from, options: release, git +# NOTE: Only `SOURCE=git` can be used for RC releases +ARG SOURCE=release + +# Choose where to get BerkeleyDB from, options: prebuilt, compile +# NOTE: When compiled here total execution time exceeds allowed CI limits, so pre-built one is used by default +ARG BDB_SOURCE=prebuilt + + + +# +## `preparer-base` installs dependencies needed by both ways of fetching the source, +# as well as imports GPG keys needed to verify authenticity of the source. +# +FROM alpine:${VER_ALPINE} AS preparer-base + +# Make sure APKs are downloaded over SSL. See: https://github.com/gliderlabs/docker-alpine/issues/184 +RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +RUN apk add --no-cache gnupg + +ENV KEYS 01EA5486DE18A882D4C2684590C8019E36C2E964 +RUN timeout 16s gpg --keyserver keyserver.ubuntu.com --recv-keys $KEYS + +# Print imported keys, but also ensure there's no other keys in the system +RUN gpg --list-keys | tail -n +3 | tee /tmp/keys.txt && \ + gpg --list-keys $KEYS | diff - /tmp/keys.txt + + + +# +## Option #1: [default] Fetch bitcoind source from release tarballs +# +FROM preparer-base AS preparer-release + +ARG VERSION + +# Download checksums +ADD https://bitcoincore.org/bin/bitcoin-core-$VERSION/SHA256SUMS.asc ./ + +# Download source code (intentionally different website than checksums) +ADD https://bitcoin.org/bin/bitcoin-core-$VERSION/bitcoin-$VERSION.tar.gz ./ + +# Verify that hashes are signed with the previously imported key +RUN gpg --verify SHA256SUMS.asc + +# Verify that downloaded source-code archive matches exactly the hash that's provided +RUN grep " bitcoin-$VERSION.tar.gz\$" SHA256SUMS.asc | sha256sum -c - + +# Extract +RUN tar -xzf "bitcoin-$VERSION.tar.gz" && \ + rm -f "bitcoin-$VERSION.tar.gz" + + + +# +## Option #2: Fetch bitcoind source from GitHub +# +FROM preparer-base AS preparer-git + +ARG VERSION + +RUN apk add --no-cache git + +# Fetch the source code at a specific TAG +RUN git clone -b "v$VERSION" --depth=1 https://github.com/bitcoin/bitcoin.git "/bitcoin-$VERSION/" + +# Verify tag, and copy source code to predetermined location on success +RUN cd "/bitcoin-$VERSION/" && \ + git verify-tag "v$VERSION" + + + +# +## Alias to go around `COPY` not accepting ARGs in value passed to `--from=` +# +FROM preparer-${SOURCE} AS preparer + + + +# +## `berkeleydb-prebuilt` downloads a pre-built BerkeleyDB to make sure +# the overall build time of this Dockerfile fits within CI limits. +# +FROM lncm/berkeleydb:v4.8.30.NC${ARCH:+-${ARCH}} AS berkeleydb-prebuilt + +# +## `berkeleydb-compile` builds BerkeleyDB from source using script provided in bitcoind repo. +# +FROM alpine:${VER_ALPINE} AS berkeleydb-compile +# TODO: implement ^^ +RUN echo "Not implemented" && exit 1 + + +FROM berkeleydb-${BDB_SOURCE} AS berkeleydb + + + +# +## `builder` builds Bitcoin Core regardless on how the source, and BDB code were obtained. +# +# NOTE: this stage is emulated using QEMU +# NOTE: `${ARCH:+${ARCH}/}` - if ARCH is set, append `/` to it, leave it empty otherwise +FROM ${ARCH:+${ARCH}/}alpine:${VER_ALPINE} AS builder + +ARG VERSION +ARG SOURCE # Use APK repos over HTTPS. See: https://github.com/gliderlabs/docker-alpine/issues/184 -RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories && \ - apk add --no-cache \ +RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +# TODO: Check which dependencies are not necessary here +RUN apk add --no-cache \ autoconf \ automake \ boost-dev \ build-base \ chrpath \ file \ - gnupg \ libevent-dev \ libressl \ libressl-dev \ @@ -18,110 +142,95 @@ RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net protobuf-dev \ zeromq-dev -# Fetch already built berkeleydb -COPY --from=lncm/berkeleydb:db-4.8.30.NC /opt/ /opt/ - -ENV KEY 01EA5486DE18A882D4C2684590C8019E36C2E964 - -# Try to fetch key from keyservers listed below. On first success terminate with `exit 0`. If loop is not interrupted, -# it means all attempts failed, and `exit 1` is called. -RUN for SRV in hkp://p80.pool.sks-keyservers.net:80 ha.pool.sks-keyservers.net keyserver.pgp.com pgp.mit.edu; do \ - timeout 9s gpg --keyserver "${SRV}" --recv-keys "${KEY}" >/dev/null 2<&1 && \ - { echo "OK: ${SRV}" && exit 0; } || \ - { echo "ERR: ${SRV} fail=$?"; } ; \ - done && exit 1 - -RUN gpg --list-keys - -ARG VERSION=0.16.3 -ENV BITCOIN_VERSION=${VERSION} -RUN echo "Building Bitcoin version: ${BITCOIN_VERSION}" - -# Download checksums -RUN wget "https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/SHA256SUMS.asc" - -# Download source code (intentionally different website than checksums) -RUN wget "https://bitcoin.org/bin/bitcoin-core-${BITCOIN_VERSION}/bitcoin-${BITCOIN_VERSION}.tar.gz" - -# Verify that hashes are signed with the previously imported key -RUN gpg --verify SHA256SUMS.asc - -# Verify that downloaded source-code archive has exactly the hash that's provided -RUN grep " bitcoin-${BITCOIN_VERSION}.tar.gz\$" SHA256SUMS.asc | sha256sum -c - - -# Extract -RUN tar -xzf "bitcoin-${BITCOIN_VERSION}.tar.gz" && \ - rm -f "bitcoin-${BITCOIN_VERSION}.tar.gz" +# Fetch pre-built berkeleydb +COPY --from=berkeleydb /opt/ /opt/ # Change to the extracted directory -WORKDIR /bitcoin-${BITCOIN_VERSION} +WORKDIR /bitcoin-$VERSION/ -# ??? +# Copy bitcoin source (downloaded & verified in previous stages) +COPY --from=preparer /bitcoin-$VERSION/ ./ + +ENV BITCOIN_PREFIX /opt/bitcoin-$VERSION + +# NOTE: no idea what these do, but they seem necessary +# taken from: https://github.com/ruimarinho/docker-bitcoin-core/blob/master/0.16/alpine/Dockerfile#L67-L69 RUN sed -i '/AC_PREREQ/a\AR_FLAGS=cr' src/univalue/configure.ac -# ??? RUN sed -i '/AX_PROG_CC_FOR_BUILD/a\AR_FLAGS=cr' src/secp256k1/configure.ac -# ??? RUN sed -i s:sys/fcntl.h:fcntl.h: src/compat.h -ENV BITCOIN_PREFIX="/opt/bitcoin-${BITCOIN_VERSION}" - RUN ./autogen.sh + +# TODO: Try to optimize on passed params RUN ./configure LDFLAGS=-L/opt/db4/lib/ CPPFLAGS=-I/opt/db4/include/ \ - --prefix="${BITCOIN_PREFIX}" \ - --mandir=/usr/share/man \ + --prefix="$BITCOIN_PREFIX" \ + --disable-man \ + --disable-shared \ --disable-ccache \ - --with-gui=no \ + --enable-static \ + --enable-reduce-exports \ + --without-gui \ + --without-libs \ --with-utils \ - --with-libs \ --with-daemon -RUN make -j$(($(nproc) + 1)) check +RUN make -j$(( $(nproc) + 1 )) check RUN make install -# Already taken advantage of before by `make check`. No need to have them installed, as they're very big (~500 MB). -RUN rm ${BITCOIN_PREFIX}/bin/bench_bitcoin ${BITCOIN_PREFIX}/bin/test_bitcoin +# List installed binaries pre-strip & strip them +RUN ls -lh "$BITCOIN_PREFIX/bin/" +RUN strip -v "$BITCOIN_PREFIX/bin/bitcoin"* -# List installed libs, and binaries pre-strip -RUN ls -lh ${BITCOIN_PREFIX}/bin/ ${BITCOIN_PREFIX}/lib/ - -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-cli -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-tx -RUN strip ${BITCOIN_PREFIX}/bin/bitcoind -RUN strip ${BITCOIN_PREFIX}/lib/libbitcoinconsensus.a -RUN strip ${BITCOIN_PREFIX}/lib/libbitcoinconsensus.so.0.0.0 - -# List installed libs, and binaries after stripping -RUN ls -lh ${BITCOIN_PREFIX}/bin/ ${BITCOIN_PREFIX}/lib/ - -# Print sha256 hashes of final binaries -RUN find -L ${BITCOIN_PREFIX}/ -type f -exec sha256sum {} \; | sort -t ' ' -k 2 +# List installed binaries post-strip & print their checksums +RUN ls -lh "$BITCOIN_PREFIX/bin/" +RUN sha256sum "$BITCOIN_PREFIX/bin/bitcoin"* -# Build stage for compiled artifacts -FROM alpine:3.10 AS final +# +## `final` aggregates build results from previous stages into a necessary minimum +# ready to be used, and published to Docker Hub. +# +# NOTE: this stage is emulated using QEMU +# NOTE: `${ARCH:+${ARCH}/}` - if ARCH is set, append `/` to it, leave it empty otherwise +FROM ${ARCH:+${ARCH}/}alpine:${VER_ALPINE} AS final + +ARG VERSION +ARG USER +ARG DIR LABEL maintainer="Damian Mee (@meeDamian)" # Use APK repos over HTTPS. See: https://github.com/gliderlabs/docker-alpine/issues/184 RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +# TODO: Check which dependencies are not necessary here RUN apk add --no-cache \ - boost \ - boost-program_options \ - libevent \ - libressl \ - libzmq \ - su-exec + boost-chrono \ + boost-filesystem \ + boost-program_options \ + boost-thread \ + libevent \ + libressl \ + libsodium \ + libstdc++ \ + libzmq -ARG VERSION=0.16.3 -ENV BITCOIN_VERSION=${VERSION} +COPY --from=builder /opt/bitcoin-$VERSION/bin/ /usr/local/bin/ -ENV BITCOIN_PREFIX="/opt/bitcoin-${BITCOIN_VERSION}" -ENV PATH="${BITCOIN_PREFIX}/bin:$PATH" +# NOTE: Default GID == UID == 1000 +RUN adduser --disabled-password \ + --home "$DIR/" \ + --gecos "" \ + "$USER" -VOLUME /root/.bitcoin +USER $USER -COPY --from=bitcoin-core /opt /opt +# Prevents `VOLUME $DIR/.bitcoind/` being created as owned by `root` +RUN mkdir -p "$DIR/.bitcoin/" + +# Expose volume containing all `bitcoind` data +VOLUME $DIR/.bitcoin/ # REST interface EXPOSE 8080 diff --git a/0.17/Dockerfile b/0.17/Dockerfile index 87d0783..aec9733 100644 --- a/0.17/Dockerfile +++ b/0.17/Dockerfile @@ -1,15 +1,139 @@ -FROM alpine:3.10 AS bitcoin-core +# This Dockerfile builds Bitcoin Core and packages it into a minimal `final` image + +# VERSION of Bitcoin Core to be build +# NOTE: Unlike our other images this one is NOT prefixed with `v`, +# as many things (like download URLs) use this form instead. +ARG VERSION=0.17.2 + +# CPU archtecture to build binaries for +ARG ARCH + +# Define default versions so that they don't have to be repreated throughout the file +ARG VER_ALPINE=3.11 + +# $USER name, and data $DIR to be used in the `final` image +ARG USER=bitcoind +ARG DIR=/data + +# Choose where to get bitcoind sources from, options: release, git +# NOTE: Only `SOURCE=git` can be used for RC releases +ARG SOURCE=release + +# Choose where to get BerkeleyDB from, options: prebuilt, compile +# NOTE: When compiled here total execution time exceeds allowed CI limits, so pre-built one is used by default +ARG BDB_SOURCE=prebuilt + + + +# +## `preparer-base` installs dependencies needed by both ways of fetching the source, +# as well as imports GPG keys needed to verify authenticity of the source. +# +FROM alpine:${VER_ALPINE} AS preparer-base + +# Make sure APKs are downloaded over SSL. See: https://github.com/gliderlabs/docker-alpine/issues/184 +RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +RUN apk add --no-cache gnupg + +ENV KEYS 01EA5486DE18A882D4C2684590C8019E36C2E964 +RUN timeout 16s gpg --keyserver keyserver.ubuntu.com --recv-keys $KEYS + +# Print imported keys, but also ensure there's no other keys in the system +RUN gpg --list-keys | tail -n +3 | tee /tmp/keys.txt && \ + gpg --list-keys $KEYS | diff - /tmp/keys.txt + + + +# +## Option #1: [default] Fetch bitcoind source from release tarballs +# +FROM preparer-base AS preparer-release + +ARG VERSION + +# Download checksums +ADD https://bitcoincore.org/bin/bitcoin-core-$VERSION/SHA256SUMS.asc ./ + +# Download source code (intentionally different website than checksums) +ADD https://bitcoin.org/bin/bitcoin-core-$VERSION/bitcoin-$VERSION.tar.gz ./ + +# Verify that hashes are signed with the previously imported key +RUN gpg --verify SHA256SUMS.asc + +# Verify that downloaded source-code archive matches exactly the hash that's provided +RUN grep " bitcoin-$VERSION.tar.gz\$" SHA256SUMS.asc | sha256sum -c - + +# Extract +RUN tar -xzf "bitcoin-$VERSION.tar.gz" && \ + rm -f "bitcoin-$VERSION.tar.gz" + + + +# +## Option #2: Fetch bitcoind source from GitHub +# +FROM preparer-base AS preparer-git + +ARG VERSION + +RUN apk add --no-cache git + +# Fetch the source code at a specific TAG +RUN git clone -b "v$VERSION" --depth=1 https://github.com/bitcoin/bitcoin.git "/bitcoin-$VERSION/" + +# Verify tag, and copy source code to predetermined location on success +RUN cd "/bitcoin-$VERSION/" && \ + git verify-tag "v$VERSION" + + + +# +## Alias to go around `COPY` not accepting ARGs in value passed to `--from=` +# +FROM preparer-${SOURCE} AS preparer + + + +# +## `berkeleydb-prebuilt` downloads a pre-built BerkeleyDB to make sure +# the overall build time of this Dockerfile fits within CI limits. +# +FROM lncm/berkeleydb:v4.8.30.NC${ARCH:+-${ARCH}} AS berkeleydb-prebuilt + +# +## `berkeleydb-compile` builds BerkeleyDB from source using script provided in bitcoind repo. +# +FROM alpine:${VER_ALPINE} AS berkeleydb-compile +# TODO: implement ^^ +RUN echo "Not implemented" && exit 1 + + +FROM berkeleydb-${BDB_SOURCE} AS berkeleydb + + + +# +## `builder` builds Bitcoin Core regardless on how the source, and BDB code were obtained. +# +# NOTE: this stage is emulated using QEMU +# NOTE: `${ARCH:+${ARCH}/}` - if ARCH is set, append `/` to it, leave it empty otherwise +FROM ${ARCH:+${ARCH}/}alpine:${VER_ALPINE} AS builder + +ARG VERSION +ARG SOURCE # Use APK repos over HTTPS. See: https://github.com/gliderlabs/docker-alpine/issues/184 -RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories && \ - apk add --no-cache \ +RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +# TODO: Check which dependencies are not necessary here +RUN apk add --no-cache \ autoconf \ automake \ boost-dev \ build-base \ chrpath \ file \ - gnupg \ libevent-dev \ libressl \ libressl-dev \ @@ -18,110 +142,94 @@ RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net protobuf-dev \ zeromq-dev -# Fetch already built berkeleydb -COPY --from=lncm/berkeleydb:db-4.8.30.NC /opt/ /opt/ - -ENV KEY 01EA5486DE18A882D4C2684590C8019E36C2E964 - -# Try to fetch key from keyservers listed below. On first success terminate with `exit 0`. If loop is not interrupted, -# it means all attempts failed, and `exit 1` is called. -RUN for SRV in hkp://p80.pool.sks-keyservers.net:80 ha.pool.sks-keyservers.net keyserver.pgp.com pgp.mit.edu; do \ - timeout 9s gpg --keyserver "${SRV}" --recv-keys "${KEY}" >/dev/null 2<&1 && \ - { echo "OK: ${SRV}" && exit 0; } || \ - { echo "ERR: ${SRV} fail=$?"; } ; \ - done && exit 1 - -RUN gpg --list-keys - -ARG VERSION=0.17.1 -ENV BITCOIN_VERSION=${VERSION} -RUN echo "Building Bitcoin version: ${BITCOIN_VERSION}" - -# Download checksums -RUN wget "https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/SHA256SUMS.asc" - -# Download source code (intentionally different website than checksums) -RUN wget "https://bitcoin.org/bin/bitcoin-core-${BITCOIN_VERSION}/bitcoin-${BITCOIN_VERSION}.tar.gz" - -# Verify that hashes are signed with the previously imported key -RUN gpg --verify SHA256SUMS.asc - -# Verify that downloaded source-code archive has exactly the hash that's provided -RUN grep " bitcoin-${BITCOIN_VERSION}.tar.gz\$" SHA256SUMS.asc | sha256sum -c - - -# Extract -RUN tar -xzf "bitcoin-${BITCOIN_VERSION}.tar.gz" && \ - rm -f "bitcoin-${BITCOIN_VERSION}.tar.gz" +# Fetch pre-built berkeleydb +COPY --from=berkeleydb /opt/ /opt/ # Change to the extracted directory -WORKDIR /bitcoin-${BITCOIN_VERSION} +WORKDIR /bitcoin-$VERSION/ -# ??? +# Copy bitcoin source (downloaded & verified in previous stages) +COPY --from=preparer /bitcoin-$VERSION/ ./ + +ENV BITCOIN_PREFIX /opt/bitcoin-$VERSION + +# NOTE: no idea what these do, but they seem necessary +# taken from: https://github.com/ruimarinho/docker-bitcoin-core/blob/master/0.17/alpine/Dockerfile#L67-L69 RUN sed -i '/AC_PREREQ/a\AR_FLAGS=cr' src/univalue/configure.ac -# ??? RUN sed -i '/AX_PROG_CC_FOR_BUILD/a\AR_FLAGS=cr' src/secp256k1/configure.ac -# ??? RUN sed -i s:sys/fcntl.h:fcntl.h: src/compat.h -ENV BITCOIN_PREFIX="/opt/bitcoin-${BITCOIN_VERSION}" - RUN ./autogen.sh + +# TODO: Try to optimize on passed params RUN ./configure LDFLAGS=-L/opt/db4/lib/ CPPFLAGS=-I/opt/db4/include/ \ - --prefix="${BITCOIN_PREFIX}" \ - --mandir=/usr/share/man \ + --prefix="$BITCOIN_PREFIX" \ + --disable-man \ + --disable-shared \ --disable-ccache \ - --with-gui=no \ + --enable-static \ + --enable-reduce-exports \ + --without-gui \ + --without-libs \ --with-utils \ - --with-libs \ --with-daemon -RUN make -j$(($(nproc) + 1)) check +RUN make -j$(( $(nproc) + 1 )) check RUN make install -# Already taken advantage of before by `make check`. No need to have them installed, as they're very big (~500 MB). -RUN rm ${BITCOIN_PREFIX}/bin/bench_bitcoin ${BITCOIN_PREFIX}/bin/test_bitcoin +# List installed binaries pre-strip & strip them +RUN ls -lh "$BITCOIN_PREFIX/bin/" +RUN strip -v "$BITCOIN_PREFIX/bin/bitcoin"* -# List installed libs, and binaries pre-strip -RUN ls -lh ${BITCOIN_PREFIX}/bin/ ${BITCOIN_PREFIX}/lib/ - -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-cli -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-tx -RUN strip ${BITCOIN_PREFIX}/bin/bitcoind -RUN strip ${BITCOIN_PREFIX}/lib/libbitcoinconsensus.a -RUN strip ${BITCOIN_PREFIX}/lib/libbitcoinconsensus.so.0.0.0 - -# List installed libs, and binaries after stripping -RUN ls -lh ${BITCOIN_PREFIX}/bin/ ${BITCOIN_PREFIX}/lib/ - -# Print sha256 hashes of final binaries -RUN find -L ${BITCOIN_PREFIX}/ -type f -exec sha256sum {} \; | sort -t ' ' -k 2 +# List installed binaries post-strip & print their checksums +RUN ls -lh "$BITCOIN_PREFIX/bin/" +RUN sha256sum "$BITCOIN_PREFIX/bin/bitcoin"* -# Build stage for compiled artifacts -FROM alpine:3.10 AS final +# +## `final` aggregates build results from previous stages into a necessary minimum +# ready to be used, and published to Docker Hub. +# +# NOTE: this stage is emulated using QEMU +# NOTE: `${ARCH:+${ARCH}/}` - if ARCH is set, append `/` to it, leave it empty otherwise +FROM ${ARCH:+${ARCH}/}alpine:${VER_ALPINE} AS final + +ARG VERSION +ARG USER +ARG DIR LABEL maintainer="Damian Mee (@meeDamian)" # Use APK repos over HTTPS. See: https://github.com/gliderlabs/docker-alpine/issues/184 RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +# TODO: Check which dependencies are not necessary here RUN apk add --no-cache \ - boost \ - boost-program_options \ - libevent \ - libressl \ - libzmq \ - su-exec + boost-chrono \ + boost-filesystem \ + boost-thread \ + libevent \ + libressl \ + libsodium \ + libstdc++ \ + libzmq -ARG VERSION=0.17.1 -ENV BITCOIN_VERSION=${VERSION} +COPY --from=builder /opt/bitcoin-$VERSION/bin/ /usr/local/bin/ -ENV BITCOIN_PREFIX="/opt/bitcoin-${BITCOIN_VERSION}" -ENV PATH="${BITCOIN_PREFIX}/bin:$PATH" +# NOTE: Default GID == UID == 1000 +RUN adduser --disabled-password \ + --home "$DIR/" \ + --gecos "" \ + "$USER" -VOLUME /root/.bitcoin +USER $USER -COPY --from=bitcoin-core /opt /opt +# Prevents `VOLUME $DIR/.bitcoind/` being created as owned by `root` +RUN mkdir -p "$DIR/.bitcoin/" + +# Expose volume containing all `bitcoind` data +VOLUME $DIR/.bitcoin/ # REST interface EXPOSE 8080 diff --git a/0.18/Dockerfile b/0.18/Dockerfile index 987c450..be258f1 100644 --- a/0.18/Dockerfile +++ b/0.18/Dockerfile @@ -1,15 +1,139 @@ -FROM alpine:3.10 AS bitcoin-core +# This Dockerfile builds Bitcoin Core and packages it into a minimal `final` image + +# VERSION of Bitcoin Core to be build +# NOTE: Unlike our other images this one is NOT prefixed with `v`, +# as many things (like download URLs) use this form instead. +ARG VERSION=0.18.1 + +# CPU archtecture to build binaries for +ARG ARCH + +# Define default versions so that they don't have to be repreated throughout the file +ARG VER_ALPINE=3.11 + +# $USER name, and data $DIR to be used in the `final` image +ARG USER=bitcoind +ARG DIR=/data + +# Choose where to get bitcoind sources from, options: release, git +# NOTE: Only `SOURCE=git` can be used for RC releases +ARG SOURCE=release + +# Choose where to get BerkeleyDB from, options: prebuilt, compile +# NOTE: When compiled here total execution time exceeds allowed CI limits, so pre-built one is used by default +ARG BDB_SOURCE=prebuilt + + + +# +## `preparer-base` installs dependencies needed by both ways of fetching the source, +# as well as imports GPG keys needed to verify authenticity of the source. +# +FROM alpine:${VER_ALPINE} AS preparer-base + +# Make sure APKs are downloaded over SSL. See: https://github.com/gliderlabs/docker-alpine/issues/184 +RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +RUN apk add --no-cache gnupg + +ENV KEYS 01EA5486DE18A882D4C2684590C8019E36C2E964 +RUN timeout 16s gpg --keyserver keyserver.ubuntu.com --recv-keys $KEYS + +# Print imported keys, but also ensure there's no other keys in the system +RUN gpg --list-keys | tail -n +3 | tee /tmp/keys.txt && \ + gpg --list-keys $KEYS | diff - /tmp/keys.txt + + + +# +## Option #1: [default] Fetch bitcoind source from release tarballs +# +FROM preparer-base AS preparer-release + +ARG VERSION + +# Download checksums +ADD https://bitcoincore.org/bin/bitcoin-core-$VERSION/SHA256SUMS.asc ./ + +# Download source code (intentionally different website than checksums) +ADD https://bitcoin.org/bin/bitcoin-core-$VERSION/bitcoin-$VERSION.tar.gz ./ + +# Verify that hashes are signed with the previously imported key +RUN gpg --verify SHA256SUMS.asc + +# Verify that downloaded source-code archive matches exactly the hash that's provided +RUN grep " bitcoin-$VERSION.tar.gz\$" SHA256SUMS.asc | sha256sum -c - + +# Extract +RUN tar -xzf "bitcoin-$VERSION.tar.gz" && \ + rm -f "bitcoin-$VERSION.tar.gz" + + + +# +## Option #2: Fetch bitcoind source from GitHub +# +FROM preparer-base AS preparer-git + +ARG VERSION + +RUN apk add --no-cache git + +# Fetch the source code at a specific TAG +RUN git clone -b "v$VERSION" --depth=1 https://github.com/bitcoin/bitcoin.git "/bitcoin-$VERSION/" + +# Verify tag, and copy source code to predetermined location on success +RUN cd "/bitcoin-$VERSION/" && \ + git verify-tag "v$VERSION" + + + +# +## Alias to go around `COPY` not accepting ARGs in value passed to `--from=` +# +FROM preparer-${SOURCE} AS preparer + + + +# +## `berkeleydb-prebuilt` downloads a pre-built BerkeleyDB to make sure +# the overall build time of this Dockerfile fits within CI limits. +# +FROM lncm/berkeleydb:v4.8.30.NC${ARCH:+-${ARCH}} AS berkeleydb-prebuilt + +# +## `berkeleydb-compile` builds BerkeleyDB from source using script provided in bitcoind repo. +# +FROM alpine:${VER_ALPINE} AS berkeleydb-compile +# TODO: implement ^^ +RUN echo "Not implemented" && exit 1 + + +FROM berkeleydb-${BDB_SOURCE} AS berkeleydb + + + +# +## `builder` builds Bitcoin Core regardless on how the source, and BDB code were obtained. +# +# NOTE: this stage is emulated using QEMU +# NOTE: `${ARCH:+${ARCH}/}` - if ARCH is set, append `/` to it, leave it empty otherwise +FROM ${ARCH:+${ARCH}/}alpine:${VER_ALPINE} AS builder + +ARG VERSION +ARG SOURCE # Use APK repos over HTTPS. See: https://github.com/gliderlabs/docker-alpine/issues/184 -RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories && \ - apk add --no-cache \ +RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +# TODO: Check which dependencies are not necessary here +RUN apk add --no-cache \ autoconf \ automake \ boost-dev \ build-base \ chrpath \ file \ - gnupg \ libevent-dev \ libressl \ libressl-dev \ @@ -18,116 +142,100 @@ RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net protobuf-dev \ zeromq-dev -# Fetch already built berkeleydb -COPY --from=lncm/berkeleydb:db-4.8.30.NC /opt/ /opt/ - -ENV KEY 01EA5486DE18A882D4C2684590C8019E36C2E964 - -# Try to fetch key from keyservers listed below. On first success terminate with `exit 0`. If loop is not interrupted, -# it means all attempts failed, and `exit 1` is called. -RUN for SRV in hkp://p80.pool.sks-keyservers.net:80 ha.pool.sks-keyservers.net keyserver.pgp.com pgp.mit.edu; do \ - timeout 9s gpg --keyserver "${SRV}" --recv-keys "${KEY}" >/dev/null 2<&1 && \ - { echo "OK: ${SRV}" && exit 0; } || \ - { echo "ERR: ${SRV} fail=$?"; } ; \ - done && exit 1 - -RUN gpg --list-keys - -ARG VERSION=0.18.1 -ENV BITCOIN_VERSION=${VERSION} -RUN echo "Building Bitcoin version: ${BITCOIN_VERSION}" - -# Download checksums -RUN wget "https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/SHA256SUMS.asc" - -# Download source code (intentionally different website than checksums) -RUN wget "https://bitcoin.org/bin/bitcoin-core-${BITCOIN_VERSION}/bitcoin-${BITCOIN_VERSION}.tar.gz" - -# Verify that hashes are signed with the previously imported key -RUN gpg --verify SHA256SUMS.asc - -# Verify that downloaded source-code archive has exactly the hash that's provided -RUN grep " bitcoin-${BITCOIN_VERSION}.tar.gz\$" SHA256SUMS.asc | sha256sum -c - - -# Extract -RUN tar -xzf "bitcoin-${BITCOIN_VERSION}.tar.gz" && \ - rm -f "bitcoin-${BITCOIN_VERSION}.tar.gz" +# Fetch pre-built berkeleydb +COPY --from=berkeleydb /opt/ /opt/ # Change to the extracted directory -WORKDIR /bitcoin-${BITCOIN_VERSION} +WORKDIR /bitcoin-$VERSION/ -# Disable emoji test that fails on Alpine for unrelated reasons: missing locale. Not important. +# Copy bitcoin source (downloaded & verified in previous stages) +COPY --from=preparer /bitcoin-$VERSION/ ./ + +ENV BITCOIN_PREFIX /opt/bitcoin-$VERSION + +# Disable emoji test failing on Alpine for unrelated reasons: "missing locale". Not important. # https://github.com/bitcoin/bitcoin/issues/14948 COPY skip-fs-test-of-utf8.patch . RUN patch -p0 < skip-fs-test-of-utf8.patch -# ??? +# NOTE: no idea what these do, but they seem necessary +# taken from: https://github.com/ruimarinho/docker-bitcoin-core/blob/master/0.18/alpine/Dockerfile#L67-L69 RUN sed -i '/AC_PREREQ/a\AR_FLAGS=cr' src/univalue/configure.ac -# ??? RUN sed -i '/AX_PROG_CC_FOR_BUILD/a\AR_FLAGS=cr' src/secp256k1/configure.ac -# ??? RUN sed -i s:sys/fcntl.h:fcntl.h: src/compat.h -ENV BITCOIN_PREFIX="/opt/bitcoin-${BITCOIN_VERSION}" - RUN ./autogen.sh + +# TODO: Try to optimize on passed params RUN ./configure LDFLAGS=-L/opt/db4/lib/ CPPFLAGS=-I/opt/db4/include/ \ - --prefix="${BITCOIN_PREFIX}" \ - --mandir=/usr/share/man \ + --prefix="$BITCOIN_PREFIX" \ + --disable-man \ + --disable-shared \ --disable-ccache \ - --with-gui=no \ - --with-utils \ + --enable-static \ + --enable-reduce-exports \ + --without-gui \ + # --without-libs \ # NOTE: Fix necessary for v0.18.1 --with-libs \ + --with-utils \ --with-daemon -RUN make -j$(($(nproc) + 1)) check +RUN make -j$(( $(nproc) + 1 )) check RUN make install -# Already taken advantage of before by `make check`. No need to have them installed, as they're very big (~500 MB). -RUN rm ${BITCOIN_PREFIX}/bin/bench_bitcoin ${BITCOIN_PREFIX}/bin/test_bitcoin +# List installed binaries pre-strip & strip them +RUN ls -lh "$BITCOIN_PREFIX/bin/" +RUN strip -v "$BITCOIN_PREFIX/bin/bitcoin"* -# List installed libs, and binaries pre-strip -RUN ls -lh ${BITCOIN_PREFIX}/bin/ ${BITCOIN_PREFIX}/lib/ - -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-cli -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-tx -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-wallet -RUN strip ${BITCOIN_PREFIX}/bin/bitcoind -RUN strip ${BITCOIN_PREFIX}/lib/libbitcoinconsensus.a -RUN strip ${BITCOIN_PREFIX}/lib/libbitcoinconsensus.so.0.0.0 - -# List installed libs, and binaries after stripping -RUN ls -lh ${BITCOIN_PREFIX}/bin/ ${BITCOIN_PREFIX}/lib/ - -# Print sha256 hashes of final binaries -RUN find -L ${BITCOIN_PREFIX}/ -type f -exec sha256sum {} \; | sort -t ' ' -k 2 +# List installed binaries post-strip & print their checksums +RUN ls -lh "$BITCOIN_PREFIX/bin/" +RUN sha256sum "$BITCOIN_PREFIX/bin/bitcoin"* -# Build stage for compiled artifacts -FROM alpine:3.10 AS final +# +## `final` aggregates build results from previous stages into a necessary minimum +# ready to be used, and published to Docker Hub. +# +# NOTE: this stage is emulated using QEMU +# NOTE: `${ARCH:+${ARCH}/}` - if ARCH is set, append `/` to it, leave it empty otherwise +FROM ${ARCH:+${ARCH}/}alpine:${VER_ALPINE} AS final + +ARG VERSION +ARG USER +ARG DIR LABEL maintainer="Damian Mee (@meeDamian)" # Use APK repos over HTTPS. See: https://github.com/gliderlabs/docker-alpine/issues/184 RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +# TODO: Check which dependencies are not necessary here RUN apk add --no-cache \ - boost \ - boost-program_options \ - libevent \ - libressl \ - libzmq \ - su-exec + boost-chrono \ + boost-filesystem \ + boost-thread \ + libevent \ + libressl \ + libsodium \ + libstdc++ \ + libzmq -ARG VERSION=0.18.1 -ENV BITCOIN_VERSION=${VERSION} +COPY --from=builder /opt/bitcoin-$VERSION/bin/ /usr/local/bin/ -ENV BITCOIN_PREFIX="/opt/bitcoin-${BITCOIN_VERSION}" -ENV PATH="${BITCOIN_PREFIX}/bin:$PATH" +# NOTE: Default GID == UID == 1000 +RUN adduser --disabled-password \ + --home "$DIR/" \ + --gecos "" \ + "$USER" -VOLUME /root/.bitcoin +USER $USER -COPY --from=bitcoin-core /opt /opt +# Prevents `VOLUME $DIR/.bitcoind/` being created as owned by `root` +RUN mkdir -p "$DIR/.bitcoin/" + +# Expose volume containing all `bitcoind` data +VOLUME $DIR/.bitcoin/ # REST interface EXPOSE 8080 diff --git a/0.19/Dockerfile b/0.19/Dockerfile index ae081a7..07a8bc8 100644 --- a/0.19/Dockerfile +++ b/0.19/Dockerfile @@ -1,17 +1,139 @@ +# This Dockerfile builds Bitcoin Core and packages it into a minimal `final` image + +# VERSION of Bitcoin Core to be build +# NOTE: Unlike our other images this one is NOT prefixed with `v`, +# as many things (like download URLs) use this form instead. +ARG VERSION=0.19.0.1 + +# CPU archtecture to build binaries for +ARG ARCH + +# Define default versions so that they don't have to be repreated throughout the file +ARG VER_ALPINE=3.11 + +# $USER name, and data $DIR to be used in the `final` image +ARG USER=bitcoind +ARG DIR=/data + +# Choose where to get bitcoind sources from, options: release, git +# NOTE: Only `SOURCE=git` can be used for RC releases ARG SOURCE=release -FROM alpine:3.10 AS bitcoin-base +# Choose where to get BerkeleyDB from, options: prebuilt, compile +# NOTE: When compiled here total execution time exceeds allowed CI limits, so pre-built one is used by default +ARG BDB_SOURCE=prebuilt + + + +# +## `preparer-base` installs dependencies needed by both ways of fetching the source, +# as well as imports GPG keys needed to verify authenticity of the source. +# +FROM alpine:${VER_ALPINE} AS preparer-base + +# Make sure APKs are downloaded over SSL. See: https://github.com/gliderlabs/docker-alpine/issues/184 +RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +RUN apk add --no-cache gnupg + +ENV KEYS 71A3B16735405025D447E8F274810B012346C9A6 01EA5486DE18A882D4C2684590C8019E36C2E964 +RUN timeout 16s gpg --keyserver keyserver.ubuntu.com --recv-keys $KEYS + +# Print imported keys, but also ensure there's no other keys in the system +RUN gpg --list-keys | tail -n +3 | tee /tmp/keys.txt && \ + gpg --list-keys $KEYS | diff - /tmp/keys.txt + + + +# +## Option #1: [default] Fetch bitcoind source from release tarballs +# +FROM preparer-base AS preparer-release + +ARG VERSION + +# Download checksums +ADD https://bitcoincore.org/bin/bitcoin-core-$VERSION/SHA256SUMS.asc ./ + +# Download source code (intentionally different website than checksums) +ADD https://bitcoin.org/bin/bitcoin-core-$VERSION/bitcoin-$VERSION.tar.gz ./ + +# Verify that hashes are signed with the previously imported key +RUN gpg --verify SHA256SUMS.asc + +# Verify that downloaded source-code archive matches exactly the hash that's provided +RUN grep " bitcoin-$VERSION.tar.gz\$" SHA256SUMS.asc | sha256sum -c - + +# Extract +RUN tar -xzf "bitcoin-$VERSION.tar.gz" && \ + rm -f "bitcoin-$VERSION.tar.gz" + + + +# +## Option #2: Fetch bitcoind source from GitHub +# +FROM preparer-base AS preparer-git + +ARG VERSION + +RUN apk add --no-cache git + +# Fetch the source code at a specific TAG +RUN git clone -b "v$VERSION" --depth=1 https://github.com/bitcoin/bitcoin.git "/bitcoin-$VERSION/" + +# Verify tag, and copy source code to predetermined location on success +RUN cd "/bitcoin-$VERSION/" && \ + git verify-tag "v$VERSION" + + + +# +## Alias to go around `COPY` not accepting ARGs in value passed to `--from=` +# +FROM preparer-${SOURCE} AS preparer + + + +# +## `berkeleydb-prebuilt` downloads a pre-built BerkeleyDB to make sure +# the overall build time of this Dockerfile fits within CI limits. +# +FROM lncm/berkeleydb:v4.8.30.NC${ARCH:+-${ARCH}} AS berkeleydb-prebuilt + +# +## `berkeleydb-compile` builds BerkeleyDB from source using script provided in bitcoind repo. +# +FROM alpine:${VER_ALPINE} AS berkeleydb-compile +# TODO: implement ^^ +RUN echo "Not implemented" && exit 1 + + +FROM berkeleydb-${BDB_SOURCE} AS berkeleydb + + + +# +## `builder` builds Bitcoin Core regardless on how the source, and BDB code were obtained. +# +# NOTE: this stage is emulated using QEMU +# NOTE: `${ARCH:+${ARCH}/}` - if ARCH is set, append `/` to it, leave it empty otherwise +FROM ${ARCH:+${ARCH}/}alpine:${VER_ALPINE} AS builder + +ARG VERSION +ARG SOURCE # Use APK repos over HTTPS. See: https://github.com/gliderlabs/docker-alpine/issues/184 -RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories && \ - apk add --no-cache \ +RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories + +# TODO: Check which dependencies are not necessary here +RUN apk add --no-cache \ autoconf \ automake \ boost-dev \ build-base \ chrpath \ file \ - gnupg \ libevent-dev \ libressl \ libressl-dev \ @@ -20,124 +142,88 @@ RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net protobuf-dev \ zeromq-dev -# Fetch already built berkeleydb -COPY --from=lncm/berkeleydb:db-4.8.30.NC /opt/ /opt/ - -ENV KEYS 71A3B16735405025D447E8F274810B012346C9A6 01EA5486DE18A882D4C2684590C8019E36C2E964 - -# Try to fetch keys from keyservers listed below. On first success terminate with `exit 0`. If loop is not interrupted, -# it means all attempts failed, and `exit 1` is called. -RUN for SRV in keyserver.ubuntu.com hkp://p80.pool.sks-keyservers.net:80 ha.pool.sks-keyservers.net keyserver.pgp.com pgp.mit.edu; do \ - timeout 9s gpg --keyserver "${SRV}" --recv-keys ${KEYS} >/dev/null 2<&1 && \ - { echo "OK: ${SRV}" && exit 0; } || \ - { echo "ERR: ${SRV} fail=$?"; } ; \ - done && exit 1 - -RUN gpg --list-keys && \ - gpg --list-key ${KEYS} - - - -# Fetch bitcoind from release tarballs -# -FROM bitcoin-base AS from-release - -ARG VERSION=0.19.0.1 -ENV BITCOIN_VERSION=${VERSION} -RUN echo "Building Bitcoin version (from release): ${BITCOIN_VERSION}" - -# Download checksums -RUN wget "https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/SHA256SUMS.asc" - -# Download source code (intentionally different website than checksums) -RUN wget "https://bitcoin.org/bin/bitcoin-core-${BITCOIN_VERSION}/bitcoin-${BITCOIN_VERSION}.tar.gz" - -# Verify that hashes are signed with the previously imported key -RUN gpg --verify SHA256SUMS.asc - -# Verify that downloaded source-code archive has exactly the hash that's provided -RUN grep " bitcoin-${BITCOIN_VERSION}.tar.gz\$" SHA256SUMS.asc | sha256sum -c - - -# Extract -RUN tar -xzf "bitcoin-${BITCOIN_VERSION}.tar.gz" && \ - rm -f "bitcoin-${BITCOIN_VERSION}.tar.gz" - - - -# Fetch bitcoind from Github repository -# -FROM bitcoin-base AS from-git - -RUN apk add git - -ARG VERSION=0.19.0.1 -ENV BITCOIN_VERSION=${VERSION} -RUN echo "Building Bitcoin version (from git): ${BITCOIN_VERSION}" - -# Fetch the source code at a specific TAG -RUN git clone -b "v${VERSION}" --depth=1 https://github.com/bitcoin/bitcoin.git - -# Verify tag, and copy source code to predetermined location on success -RUN (cd bitcoin && git verify-tag "v${VERSION}") && \ - mv bitcoin/ /bitcoin-${BITCOIN_VERSION} - - - -# Build bitcoind (regardless on how the source code was obtained) -# -FROM from-${SOURCE} AS bitcoin-core +# Fetch pre-built berkeleydb +COPY --from=berkeleydb /opt/ /opt/ # Change to the extracted directory -WORKDIR /bitcoin-${BITCOIN_VERSION} +WORKDIR /bitcoin-$VERSION/ -ENV BITCOIN_PREFIX="/opt/bitcoin-${BITCOIN_VERSION}" +# Copy bitcoin source (downloaded & verified in previous stages) +COPY --from=preparer /bitcoin-$VERSION/ ./ + +ENV BITCOIN_PREFIX /opt/bitcoin-$VERSION RUN ./autogen.sh + +# TODO: Try to optimize on passed params RUN ./configure LDFLAGS=-L/opt/db4/lib/ CPPFLAGS=-I/opt/db4/include/ \ - --prefix="${BITCOIN_PREFIX}" \ - --mandir=/usr/share/man \ + --prefix="$BITCOIN_PREFIX" \ + --disable-man \ + --disable-shared \ --disable-ccache \ - --with-gui=no \ + --enable-static \ + --enable-reduce-exports \ + --without-gui \ + --without-libs \ --with-utils \ - --with-libs \ --with-daemon -RUN make -j$(($(nproc) + 1)) check +RUN make -j$(( $(nproc) + 1 )) check RUN make install -# List installed libs, and binaries pre-strip -RUN ls -lh ${BITCOIN_PREFIX}/bin/ ${BITCOIN_PREFIX}/lib/ +# List installed binaries pre-strip & strip them +RUN ls -lh "$BITCOIN_PREFIX/bin/" +RUN strip -v "$BITCOIN_PREFIX/bin/bitcoin"* -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-cli -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-tx -RUN strip ${BITCOIN_PREFIX}/bin/bitcoin-wallet -RUN strip ${BITCOIN_PREFIX}/bin/bitcoind - -# List installed libs, and binaries after stripping -RUN ls -lh ${BITCOIN_PREFIX}/bin/ ${BITCOIN_PREFIX}/lib/ - -# Print sha256 hashes of final binaries -RUN find -L ${BITCOIN_PREFIX}/ -type f -exec sha256sum {} \; | sort -t ' ' -k 2 +# List installed binaries post-strip & print their checksums +RUN ls -lh "$BITCOIN_PREFIX/bin/" +RUN sha256sum "$BITCOIN_PREFIX/bin/bitcoin"* -# Build stage for compiled artifacts -FROM alpine:3.10 AS final +# +## `final` aggregates build results from previous stages into a necessary minimum +# ready to be used, and published to Docker Hub. +# +# NOTE: this stage is emulated using QEMU +# NOTE: `${ARCH:+${ARCH}/}` - if ARCH is set, append `/` to it, leave it empty otherwise +FROM ${ARCH:+${ARCH}/}alpine:${VER_ALPINE} AS final + +ARG VERSION +ARG USER +ARG DIR LABEL maintainer="Damian Mee (@meeDamian)" # Use APK repos over HTTPS. See: https://github.com/gliderlabs/docker-alpine/issues/184 -RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories && \ - apk add --no-cache libressl libstdc++ boost-thread boost-chrono boost-filesystem libevent libsodium libzmq +RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://alpine.global.ssl.fastly.net|g' /etc/apk/repositories -ARG VERSION=0.19.0.1 -ENV BITCOIN_VERSION=${VERSION} +# TODO: Check which dependencies are not necessary here +RUN apk add --no-cache \ + boost-chrono \ + boost-filesystem \ + boost-thread \ + libevent \ + libressl \ + libsodium \ + libstdc++ \ + libzmq -ENV BITCOIN_PREFIX="/opt/bitcoin-${BITCOIN_VERSION}" +COPY --from=builder /opt/bitcoin-$VERSION/bin/ /usr/local/bin/ -VOLUME /root/.bitcoin +# NOTE: Default GID == UID == 1000 +RUN adduser --disabled-password \ + --home "$DIR/" \ + --gecos "" \ + "$USER" -COPY --from=bitcoin-core "${BITCOIN_PREFIX}/bin/" /usr/local/bin/ +USER $USER + +# Prevents `VOLUME $DIR/.bitcoind/` being created as owned by `root` +RUN mkdir -p "$DIR/.bitcoin/" + +# Expose volume containing all `bitcoind` data +VOLUME $DIR/.bitcoin/ # REST interface EXPOSE 8080 diff --git a/scripts/new-release.sh b/scripts/new-release.sh new file mode 100755 index 0000000..c65bf88 --- /dev/null +++ b/scripts/new-release.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +set -eo pipefail + +# +## Given version, this script creates & pushes a relevant git-tag. +# + +# required version +VERSION=$1 + +# Verify version to-be-released is provided +if [[ -z "$VERSION" ]]; then + >&2 printf "\nERR: version missing: version needs to be passed as the first argument. Try:\n" + >&2 printf "\t./%s %s\n\n" "$(basename "$0")" "v0.19.1" + exit 1 +fi + +# Get directory +DIR="$(echo "${VERSION#v}" | cut -d. -f-2)" + +# Verify there's no uncommitted changes in the working dir +if [[ -n "$(git status --untracked-files=no --porcelain)" ]]; then + >&2 printf "\nERR: working directory not clean. Commit, or stash changes to continue.\n\n" + exit 1 +fi + +if ! grep -q "${VERSION#v}" "$DIR/Dockerfile" ; then + >&2 printf "\nERR: Requested version not present in Dockerfile. Make sure that's what you want to do.\n\n" + exit 1 +fi + +git fetch --tags + +# Get last build number +LAST="$(git tag | grep '+build' | sed 's|^.*build||' | sort -h | tail -n 1)" +LAST="${LAST:-0}" + +# Increment it +((LAST++)) + + +TAG="$VERSION+build$LAST" + +printf "Creating tag: %s…\t" "$TAG" + +git tag -sa "$TAG" -m "$TAG" + +echo "done" + + +printf "Pushing tag: %s…\t" "$TAG" + +git push origin "$TAG" + +echo "All done"