Simplify build (#31)

* 1st Attempt at self-contained Dockerfile

* Fix build

* bulk change

* fixes

* 0.17.1 -> 0.17.2

* Only build 0.17

* Only build 0.16

* build all

* (Hopefully) fix 0.16

* simplify test workflow

* Try building 0.18 w/o emoji patch

* REALLY FUCKING FIXED

* Moved something to somewhere... goodnight...

* minor workflows improvements

* simplify & consistency++ of qemu perf script

* simplify qemu reference;  better GH release

* qemu-perf & qemu consistency++

* reverts brainfart

* consistency changes

* Comment style

* Add v0.18.1 fix to make tests pass

* Move APP to be a workflow-level variable

* simplify GPG

* Update actions/github-script version

* merge annotations into a single step

* bettermore

* morebettermore

* Add helper script to create new releases

* Enable Docker experimental with less lines
This commit is contained in:
Damian Mee 2020-03-13 23:25:46 +08:00 committed by GitHub
parent 72c9be9a5c
commit 1feef9f6ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1061 additions and 539 deletions

View File

@ -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<N>
# \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<N>"
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/*

View File

@ -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

View File

@ -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',

View File

@ -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"

27
.github/workflows/update-readme.yml vendored Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

56
scripts/new-release.sh Executable file
View File

@ -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"