Skip to content

Commit 699b7ec

Browse files
committed
Split the dockerfiles into separate builder / image definitions
1 parent c07c717 commit 699b7ec

6 files changed

Lines changed: 277 additions & 133 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# will have compiled files and executables
33
debug/
44
target/
5+
build/
56

67
# These are backup files generated by rustfmt
78
**/*.rs.bk
@@ -14,4 +15,4 @@ cb.docker-compose.yml
1415
targets.json
1516
.idea/
1617
logs
17-
.vscode/
18+
.vscode/

build-linux.sh

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#!/bin/bash
2+
3+
# This script will build the Commit-Boost applications and modules for local Linux development.
4+
5+
# =================
6+
# === Functions ===
7+
# =================
8+
9+
# Print a failure message to stderr and exit
10+
fail() {
11+
MESSAGE=$1
12+
RED='\033[0;31m'
13+
RESET='\033[;0m'
14+
>&2 echo -e "\n${RED}**ERROR**\n$MESSAGE${RESET}\n"
15+
exit 1
16+
}
17+
18+
19+
# Builds the CLI binaries for Linux
20+
# NOTE: You must install qemu first; e.g. sudo apt-get install -y qemu qemu-user-static
21+
build_cli() {
22+
echo "Building CLI binaries..."
23+
docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/$VERSION --target output --build-arg TARGET_CRATE=commit-boost-cli . || fail "Error building CLI."
24+
echo "done!"
25+
26+
# Flatten the folder structure for easier referencing
27+
mv build/$VERSION/linux_amd64/commit-boost-cli build/$VERSION/commit-boost-cli-linux-amd64
28+
mv build/$VERSION/linux_arm64/commit-boost-cli build/$VERSION/commit-boost-cli-linux-arm64
29+
30+
# Clean up the empty directories
31+
rmdir build/$VERSION/linux_amd64 build/$VERSION/linux_arm64
32+
echo "done!"
33+
}
34+
35+
36+
# Builds the PBS module binaries for Linux and the Docker image(s)
37+
# NOTE: You must install qemu first; e.g. sudo apt-get install -y qemu qemu-user-static
38+
build_pbs() {
39+
echo "Building PBS binaries..."
40+
docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/$VERSION --target output --build-arg TARGET_CRATE=commit-boost-pbs . || fail "Error building PBS binaries."
41+
echo "done!"
42+
43+
# Flatten the folder structure for easier referencing
44+
mv build/$VERSION/linux_amd64/commit-boost-pbs build/$VERSION/commit-boost-pbs-linux-amd64
45+
mv build/$VERSION/linux_arm64/commit-boost-pbs build/$VERSION/commit-boost-pbs-linux-arm64
46+
47+
# Clean up the empty directories
48+
rmdir build/$VERSION/linux_amd64 build/$VERSION/linux_arm64
49+
50+
echo "Building PBS Docker image..."
51+
# If uploading, make and push a manifest
52+
if [ "$LOCAL_UPLOAD" = true ]; then
53+
if [ -z "$LOCAL_DOCKER_REGISTRY" ]; then
54+
fail "LOCAL_DOCKER_REGISTRY must be set to upload to a local registry."
55+
fi
56+
docker buildx build --rm --platform=linux/amd64,linux/arm64 --build-arg BINARIES_PATH=build/$VERSION -t $LOCAL_DOCKER_REGISTRY/commit-boost/pbs:$VERSION -f provisioning/pbs.Dockerfile --push . || fail "Error building PBS image."
57+
else
58+
docker buildx build --rm --load --build-arg BINARIES_PATH=build/$VERSION -t commit-boost/pbs:$VERSION -f provisioning/pbs.Dockerfile . || fail "Error building PBS image."
59+
fi
60+
echo "done!"
61+
}
62+
63+
64+
# Builds the Signer module binaries for Linux and the Docker image(s)
65+
# NOTE: You must install qemu first; e.g. sudo apt-get install -y qemu qemu-user-static
66+
build_signer() {
67+
echo "Building Signer binaries..."
68+
docker buildx build --rm --platform=linux/amd64,linux/arm64 -f provisioning/build.Dockerfile --output build/$VERSION --target output --build-arg TARGET_CRATE=commit-boost-signer . || fail "Error building Signer binaries."
69+
echo "done!"
70+
71+
# Flatten the folder structure for easier referencing
72+
mv build/$VERSION/linux_amd64/commit-boost-signer build/$VERSION/commit-boost-signer-linux-amd64
73+
mv build/$VERSION/linux_arm64/commit-boost-signer build/$VERSION/commit-boost-signer-linux-arm64
74+
75+
# Clean up the empty directories
76+
rmdir build/$VERSION/linux_amd64 build/$VERSION/linux_arm64
77+
78+
echo "Building Signer Docker image..."
79+
# If uploading, make and push a manifest
80+
if [ "$LOCAL_UPLOAD" = true ]; then
81+
if [ -z "$LOCAL_DOCKER_REGISTRY" ]; then
82+
fail "LOCAL_DOCKER_REGISTRY must be set to upload to a local registry."
83+
fi
84+
docker buildx build --rm --platform=linux/amd64,linux/arm64 --build-arg BINARIES_PATH=build/$VERSION -t $LOCAL_DOCKER_REGISTRY/commit-boost/signer:$VERSION -f provisioning/signer.Dockerfile --push . || fail "Error building Signer image."
85+
else
86+
docker buildx build --rm --load --build-arg BINARIES_PATH=build/$VERSION -t commit-boost/signer:$VERSION -f provisioning/signer.Dockerfile . || fail "Error building Signer image."
87+
fi
88+
echo "done!"
89+
}
90+
91+
92+
# Print usage
93+
usage() {
94+
echo "Usage: build.sh [options] -v <version number>"
95+
echo "This script assumes it is in the commit-boost-client repository directory."
96+
echo "Options:"
97+
echo $'\t-a\tBuild all of the artifacts (CLI, PBS, and Signer, along with Docker images)'
98+
echo $'\t-c\tBuild the Commit-Boost CLI binaries'
99+
echo $'\t-p\tBuild the PBS module binary and its Docker container'
100+
echo $'\t-s\tBuild the Signer module binary and its Docker container'
101+
echo $'\t-o\tWhen passed with a build, upload the resulting image tags to a local Docker registry specified in $LOCAL_DOCKER_REGISTRY'
102+
exit 0
103+
}
104+
105+
106+
# =================
107+
# === Main Body ===
108+
# =================
109+
110+
# Parse arguments
111+
while getopts "acpsov:" FLAG; do
112+
case "$FLAG" in
113+
a) CLI=true PBS=true SIGNER=true ;;
114+
c) CLI=true ;;
115+
p) PBS=true ;;
116+
s) SIGNER=true ;;
117+
o) LOCAL_UPLOAD=true ;;
118+
v) VERSION="$OPTARG" ;;
119+
*) usage ;;
120+
esac
121+
done
122+
if [ -z "$VERSION" ]; then
123+
usage
124+
fi
125+
126+
# Cleanup old artifacts
127+
rm -rf build/$VERSION/*
128+
mkdir -p build/$VERSION
129+
130+
# Make a multiarch builder, ignore if it's already there
131+
docker buildx create --name multiarch-builder --driver docker-container --use > /dev/null 2>&1
132+
# NOTE: if using a local repo with a private CA, you will have to follow these steps to add the CA to the builder:
133+
# https://stackoverflow.com/a/73585243
134+
135+
# Build the artifacts
136+
if [ "$CLI" = true ]; then
137+
build_cli
138+
fi
139+
if [ "$PBS" = true ]; then
140+
build_pbs
141+
fi
142+
if [ "$SIGNER" = true ]; then
143+
build_signer
144+
fi

provisioning/build.Dockerfile

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# This will be the main build image
2+
FROM --platform=${BUILDPLATFORM} lukemathwalker/cargo-chef:latest-rust-1.83 AS chef
3+
ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED TARGET_CRATE
4+
WORKDIR /app
5+
6+
FROM --platform=${BUILDPLATFORM} chef AS planner
7+
ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED TARGET_CRATE
8+
COPY . .
9+
RUN cargo chef prepare --recipe-path recipe.json
10+
11+
FROM --platform=${BUILDPLATFORM} chef AS builder
12+
ARG TARGETOS TARGETARCH BUILDPLATFORM OPENSSL_VENDORED TARGET_CRATE
13+
RUN test -n "$TARGET_CRATE" || (echo "TARGET_CRATE must be set to the service / binary you want to build" && false)
14+
ENV BUILD_VAR_SCRIPT=/tmp/env.sh
15+
COPY --from=planner /app/recipe.json recipe.json
16+
17+
# Get the latest Protoc since the one in the Debian repo is incredibly old
18+
RUN apt update && apt install -y unzip curl ca-certificates && \
19+
PROTOC_VERSION=$(curl -s "https://api.github.com/repos/protocolbuffers/protobuf/releases/latest" | grep -Po '"tag_name": "v\K[0-9.]+') && \
20+
if [ "$BUILDPLATFORM" = "linux/amd64" ]; then \
21+
PROTOC_ARCH=x86_64; \
22+
elif [ "$BUILDPLATFORM" = "linux/arm64" ]; then \
23+
PROTOC_ARCH=aarch_64; \
24+
else \
25+
echo "${BUILDPLATFORM} is not supported."; \
26+
exit 1; \
27+
fi && \
28+
curl -Lo protoc.zip https://github.com/protocolbuffers/protobuf/releases/latest/download/protoc-$PROTOC_VERSION-linux-$PROTOC_ARCH.zip && \
29+
unzip -q protoc.zip bin/protoc -d /usr && \
30+
unzip -q protoc.zip "include/google/*" -d /usr && \
31+
chmod a+x /usr/bin/protoc && \
32+
rm -rf protoc.zip
33+
34+
# Set up the build environment for cross-compilation if needed
35+
RUN if [ "$BUILDPLATFORM" = "linux/amd64" -a "$TARGETARCH" = "arm64" ]; then \
36+
# We're on x64, cross-compiling for arm64
37+
rustup target add aarch64-unknown-linux-gnu && \
38+
apt update && \
39+
apt install -y gcc-aarch64-linux-gnu && \
40+
echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \
41+
echo "export TARGET=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \
42+
echo "export TARGET_FLAG=--target=aarch64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \
43+
echo "export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/aarch64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \
44+
echo "export RUSTFLAGS=\"-L /usr/aarch64-linux-gnu/lib -L $(dirname $(aarch64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \
45+
if [ "$OPENSSL_VENDORED" != "true" ]; then \
46+
# If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation
47+
dpkg --add-architecture arm64 && \
48+
apt update && \
49+
apt install -y libssl-dev:arm64 zlib1g-dev:arm64 && \
50+
echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \
51+
echo "export PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \
52+
echo "export OPENSSL_INCLUDE_DIR=/usr/include/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \
53+
echo "export OPENSSL_LIB_DIR=/usr/lib/aarch64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \
54+
fi; \
55+
elif [ "$BUILDPLATFORM" = "linux/arm64" -a "$TARGETARCH" = "amd64" ]; then \
56+
# We're on arm64, cross-compiling for x64
57+
rustup target add x86_64-unknown-linux-gnu && \
58+
apt update && \
59+
apt install -y gcc-x86-64-linux-gnu && \
60+
echo "#!/bin/sh" > ${BUILD_VAR_SCRIPT} && \
61+
echo "export TARGET=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \
62+
echo "export TARGET_FLAG=--target=x86_64-unknown-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \
63+
echo "export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/usr/bin/x86_64-linux-gnu-gcc" >> ${BUILD_VAR_SCRIPT} && \
64+
echo "export RUSTFLAGS=\"-L /usr/x86_64-linux-gnu/lib -L $(dirname $(x86_64-linux-gnu-gcc -print-libgcc-file-name))\"" >> ${BUILD_VAR_SCRIPT} && \
65+
if [ "$OPENSSL_VENDORED" != "true" ]; then \
66+
# If we're linking to OpenSSL dynamically, we have to set it up for cross-compilation
67+
dpkg --add-architecture amd64 && \
68+
apt update && \
69+
apt install -y libssl-dev:amd64 zlib1g-dev:amd64 && \
70+
echo "export PKG_CONFIG_ALLOW_CROSS=true" >> ${BUILD_VAR_SCRIPT} && \
71+
echo "export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig" >> ${BUILD_VAR_SCRIPT} && \
72+
echo "export OPENSSL_INCLUDE_DIR=/usr/include/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT} && \
73+
echo "export OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu" >> ${BUILD_VAR_SCRIPT}; \
74+
fi; \
75+
fi
76+
77+
# Run cook to prep the build
78+
RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \
79+
. ${BUILD_VAR_SCRIPT} && \
80+
echo "Cross-compilation environment set up for ${TARGET}"; \
81+
else \
82+
echo "No cross-compilation needed"; \
83+
fi && \
84+
if [ "$OPENSSL_VENDORED" = "true" ]; then \
85+
echo "Using vendored OpenSSL" && \
86+
FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \
87+
else \
88+
echo "Using system OpenSSL"; \
89+
fi && \
90+
export GIT_HASH=$(git rev-parse HEAD) && \
91+
cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json ${FEATURE_OPENSSL_VENDORED}
92+
93+
# Now we can copy the source files - chef cook wants to run before this step
94+
COPY . .
95+
96+
# Build the application
97+
RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \
98+
chmod +x ${BUILD_VAR_SCRIPT} && \
99+
. ${BUILD_VAR_SCRIPT} && \
100+
echo "Cross-compilation environment set up for ${TARGET}"; \
101+
else \
102+
echo "No cross-compilation needed"; \
103+
fi && \
104+
if [ "$OPENSSL_VENDORED" = "true" ]; then \
105+
echo "Using vendored OpenSSL" && \
106+
FEATURE_OPENSSL_VENDORED='--features openssl-vendored'; \
107+
else \
108+
echo "Using system OpenSSL"; \
109+
fi && \
110+
export GIT_HASH=$(git rev-parse HEAD) && \
111+
cargo build ${TARGET_FLAG} --release --bin ${TARGET_CRATE} ${FEATURE_OPENSSL_VENDORED} && \
112+
if [ ! -z "$TARGET" ]; then \
113+
# If we're cross-compiling, we need to move the binary out of the target dir
114+
mv target/${TARGET}/release/${TARGET_CRATE} target/release/${TARGET_CRATE}; \
115+
fi
116+
117+
# Copy the output
118+
FROM scratch AS output
119+
ARG TARGET_CRATE
120+
COPY --from=builder /app/target/release/${TARGET_CRATE} /${TARGET_CRATE}

provisioning/cli.Dockerfile

Whitespace-only changes.

0 commit comments

Comments
 (0)