Skip to content

Commit 8146546

Browse files
committed
build: consolidate reproducible builder scripts into build/shared/
Move pin-packages.sh, config-qemu.sh, and common build functions into a single build/shared/ directory, eliminating divergent copies across gateway, kms, and verifier builders. Key changes: - Create build/shared/build-lib.sh with shared functions (ensure_buildkit, docker_build, extract_packages, sync_shared_scripts, check_clean_tree) - Fix pin-packages.sh: use printf instead of echo for correct newline handling, proper quoting, use HTTP for snapshot.debian.org (APT does its own GPG verification) - Unify snapshot date to 20260317T000000Z across all services - Rewrite all build-image.sh scripts to source shared build-lib.sh - Add DSTACK_SRC_URL ARG to gateway Dockerfile (was hardcoded) - Fix kms GIT_REV handling to use Dockerfile ARG instead of host file - Rename kms-pinned-packages.txt to builder-pinned-packages.txt for consistency across services - Regenerate all pinned-packages.txt files with unified snapshot date - Fix verifier's corrupt builder-pinned-packages.txt (was 435 lines of '=')
1 parent dec6ee3 commit 8146546

24 files changed

Lines changed: 1649 additions & 1621 deletions

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/target
22
/certs
33
/build-config.sh
4-
/build
4+
/build/*
5+
!/build/shared/
56
generated/
67
node_modules/
78
/.cargo

build/shared/build-lib.sh

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/bin/bash
2+
3+
# SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
# Shared build library for reproducible Docker image builds.
8+
#
9+
# Expected variables (set by the sourcing script):
10+
# REPO_ROOT - absolute path to the git repo root
11+
# CONTEXT_DIR - Docker build context directory
12+
# DOCKERFILE - path to the Dockerfile
13+
# GIT_REV - git revision to build
14+
# DSTACK_SRC_URL - git URL for dstack source
15+
16+
set -euo pipefail
17+
18+
BUILDKIT_VERSION="v0.20.2"
19+
BUILDKIT_BUILDER="buildkit_20"
20+
21+
ensure_buildkit() {
22+
if ! docker buildx inspect "$BUILDKIT_BUILDER" &>/dev/null; then
23+
docker buildx create --use --driver-opt "image=moby/buildkit:$BUILDKIT_VERSION" --name "$BUILDKIT_BUILDER"
24+
fi
25+
}
26+
27+
extract_packages() {
28+
local image_name=$1
29+
local pkg_list_file=${2:-}
30+
if [ -z "$pkg_list_file" ]; then
31+
return
32+
fi
33+
docker run --rm --entrypoint bash "$image_name" \
34+
-c "dpkg -l | grep '^ii' | awk '{print \$2\"=\"\$3}' | sort" \
35+
>"$pkg_list_file"
36+
}
37+
38+
docker_build() {
39+
local image_name=$1
40+
local target=${2:-}
41+
local pkg_list_file=${3:-}
42+
43+
local commit_timestamp
44+
commit_timestamp=$(git -C "$REPO_ROOT" show -s --format=%ct "$GIT_REV")
45+
46+
local args=(
47+
--builder "$BUILDKIT_BUILDER"
48+
--progress=plain
49+
--output "type=docker,name=$image_name,rewrite-timestamp=true"
50+
--build-arg "SOURCE_DATE_EPOCH=$commit_timestamp"
51+
--build-arg "DSTACK_REV=$GIT_REV"
52+
--build-arg "DSTACK_SRC_URL=$DSTACK_SRC_URL"
53+
)
54+
55+
if [ -n "${NO_CACHE:-}" ]; then
56+
args+=(--no-cache)
57+
fi
58+
59+
if [ -n "$target" ]; then
60+
args+=(--target "$target")
61+
fi
62+
63+
docker buildx build "${args[@]}" \
64+
--file "$DOCKERFILE" \
65+
"$CONTEXT_DIR"
66+
67+
extract_packages "$image_name" "$pkg_list_file"
68+
}
69+
70+
# Copy shared build scripts into the local shared directory used by Dockerfile COPY.
71+
sync_shared_scripts() {
72+
local dest_dir=$1
73+
local need_qemu=${2:-false}
74+
75+
cp "$REPO_ROOT/build/shared/pin-packages.sh" "$dest_dir/pin-packages.sh"
76+
if [ "$need_qemu" = "true" ]; then
77+
cp "$REPO_ROOT/build/shared/config-qemu.sh" "$dest_dir/config-qemu.sh"
78+
fi
79+
}
80+
81+
# Verify that pinned-packages files haven't changed (idempotency check).
82+
check_clean_tree() {
83+
local check_path=$1
84+
local rel_path
85+
rel_path=$(realpath --relative-to="$REPO_ROOT" "$check_path")
86+
local git_status
87+
git_status=$(git -C "$REPO_ROOT" status --porcelain -- "$rel_path")
88+
if [ -n "$git_status" ]; then
89+
echo "The working tree has updates in $rel_path. Commit or stash before re-running." >&2
90+
exit 1
91+
fi
92+
}
File renamed without changes.

build/shared/pin-packages.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash
2+
3+
# SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
# Pin APT packages to exact versions from a frozen Debian snapshot.
8+
# Usage: pin-packages.sh <pkg-list-file>
9+
#
10+
# This script:
11+
# 1. Points APT at a frozen snapshot.debian.org mirror (reproducible package sources)
12+
# 2. Reads package=version pairs from the given file and creates APT pin preferences
13+
# with priority 1001 to force exact versions
14+
15+
set -e
16+
17+
PKG_LIST=$1
18+
SNAPSHOT_DATE=${SNAPSHOT_DATE:-20260317T000000Z}
19+
20+
if [ -z "$PKG_LIST" ]; then
21+
echo "Usage: $0 <pkg-list-file>" >&2
22+
exit 1
23+
fi
24+
25+
echo "deb [check-valid-until=no] http://snapshot.debian.org/archive/debian/${SNAPSHOT_DATE} bookworm main" > /etc/apt/sources.list
26+
echo "deb [check-valid-until=no] http://snapshot.debian.org/archive/debian-security/${SNAPSHOT_DATE} bookworm-security main" >> /etc/apt/sources.list
27+
echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf.d/10no-check-valid-until
28+
29+
mkdir -p /etc/apt/preferences.d
30+
while IFS= read -r line; do
31+
pkg=$(echo "$line" | cut -d= -f1)
32+
ver=$(echo "$line" | cut -d= -f2)
33+
if [ -n "$pkg" ] && [ -n "$ver" ]; then
34+
printf 'Package: %s\nPin: version %s\nPin-Priority: 1001\n\n' "$pkg" "$ver" >> /etc/apt/preferences.d/pinned-packages
35+
fi
36+
done < "$PKG_LIST"

gateway/dstack-app/builder/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
FROM rust:1.92.0@sha256:48851a839d6a67370c9dbe0e709bedc138e3e404b161c5233aedcf2b717366e4 AS gateway-builder
66
COPY ./shared /build
77
ARG DSTACK_REV
8+
ARG DSTACK_SRC_URL=https://github.com/Dstack-TEE/dstack.git
89
WORKDIR /build
910
RUN ./pin-packages.sh ./builder-pinned-packages.txt
1011
RUN apt-get update && \
@@ -17,7 +18,7 @@ RUN apt-get update && \
1718
libprotobuf-dev \
1819
clang \
1920
libclang-dev
20-
RUN git clone https://github.com/Dstack-TEE/dstack.git && \
21+
RUN git clone ${DSTACK_SRC_URL} && \
2122
cd dstack && \
2223
git checkout ${DSTACK_REV}
2324
RUN rustup target add x86_64-unknown-linux-musl

gateway/dstack-app/builder/build-image.sh

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,34 @@
44
#
55
# SPDX-License-Identifier: Apache-2.0
66

7-
set -e
7+
set -euo pipefail
88

9-
#NO_CACHE=--no-cache
9+
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
10+
REPO_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)
11+
CONTEXT_DIR="$SCRIPT_DIR"
12+
SHARED_DIR="$SCRIPT_DIR/shared"
13+
DOCKERFILE="$SCRIPT_DIR/Dockerfile"
1014

11-
extract-packages() {
12-
local name=$1
13-
local pkg_list_file=$2
14-
if [ -z "$pkg_list_file" ]; then
15-
return
16-
fi
17-
docker run --rm --entrypoint bash $name -c "dpkg -l | grep '^ii' | awk '{print \$2\"=\"\$3}' | sort" > "$pkg_list_file"
18-
}
15+
source "$REPO_ROOT/build/shared/build-lib.sh"
1916

20-
# Function to build Docker image and optionally extract package list
21-
docker-build() {
22-
local name=$1
23-
local target=$2
24-
local pkg_list_file=$3
25-
# Get the commit timestamp for SOURCE_DATE_EPOCH
26-
local commit_timestamp=$(git show -s --format=%ct $GIT_REV)
27-
local build_args="--build-arg SOURCE_DATE_EPOCH=$commit_timestamp --build-arg DSTACK_REV=$GIT_REV"
28-
29-
local args="--builder buildkit_20 $NO_CACHE $build_args"
30-
31-
# Add target if specified
32-
if [ -n "$target" ]; then
33-
args="$args --target $target"
34-
fi
35-
36-
# Build the image
37-
docker buildx build $args --output type=docker,name=$name,rewrite-timestamp=true --progress=plain .
38-
extract-packages $name $pkg_list_file
39-
}
40-
41-
NAME=$1
17+
NAME=${1:-}
4218
if [ -z "$NAME" ]; then
43-
echo "Usage: $0 <name>[:<tag>]"
19+
echo "Usage: $0 <image-name>[:<tag>]" >&2
4420
exit 1
4521
fi
4622

47-
# Check if buildkit_20 already exists before creating it
48-
if ! docker buildx inspect buildkit_20 &>/dev/null; then
49-
docker buildx create --use --driver-opt image=moby/buildkit:v0.20.2 --name buildkit_20
50-
fi
51-
52-
touch shared/builder-pinned-packages.txt
53-
touch shared/pinned-packages.txt
23+
NO_CACHE=${NO_CACHE:-}
5424
GIT_REV=${GIT_REV:-HEAD}
55-
GIT_REV=$(git rev-parse $GIT_REV)
25+
GIT_REV=$(git -C "$REPO_ROOT" rev-parse "$GIT_REV")
26+
DSTACK_SRC_URL=${DSTACK_SRC_URL:-https://github.com/Dstack-TEE/dstack.git}
5627

57-
docker-build "$NAME" "" "shared/pinned-packages.txt"
58-
docker-build "gateway-builder-temp" "gateway-builder" "shared/builder-pinned-packages.txt"
28+
ensure_buildkit
29+
sync_shared_scripts "$SHARED_DIR"
5930

60-
git_status=$(git status --porcelain -- shared/)
61-
if [ -n "$git_status" ]; then
62-
echo "The working tree is not clean, please commit or stash your changes before re-running the build"
63-
exit 1
64-
fi
31+
touch "$SHARED_DIR/builder-pinned-packages.txt"
32+
touch "$SHARED_DIR/pinned-packages.txt"
33+
34+
docker_build "$NAME" "" "$SHARED_DIR/pinned-packages.txt"
35+
docker_build "gateway-builder-temp" "gateway-builder" "$SHARED_DIR/builder-pinned-packages.txt"
6536

37+
check_clean_tree "$SHARED_DIR"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Copied from build/shared/ at build time by build-image.sh
2+
pin-packages.sh
3+
config-qemu.sh

0 commit comments

Comments
 (0)