fabro/bin/dev/docker-build.sh
Bryan Helmkamp 908f078cec
chore(docker): add --tag to docker-build.sh, document it in AGENTS.md
Lets a smoke-test harness pick its own image tag without racing the default
fabro:latest, and points future agent sessions at bin/dev/docker-build.sh
so they don't hand-roll a throwaway Dockerfile.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:03:08 -04:00

100 lines
3.2 KiB
Bash
Executable file

#!/usr/bin/env bash
# Build a local fabro Docker image from the current working tree.
#
# The Docker image uses musl binaries for a small Alpine-based runtime. We
# compile fabro-cli for the target musl triple inside rust:1-bookworm using
# cargo-zigbuild (zig as the C compiler + linker). Cargo registry and target
# dir are cached in named volumes so subsequent runs are incremental.
#
# Usage:
# bin/dev/docker-build.sh # host arch, build image at end
# bin/dev/docker-build.sh --arch amd64 # force amd64 (uses QEMU on non-amd64 hosts — slow)
# bin/dev/docker-build.sh --tag fabro:smoke # tag image as fabro:smoke (default: fabro)
# bin/dev/docker-build.sh --arch arm64 --compile-only
# # stage binary only; skip `docker build`
# # (useful for multi-arch buildx verification)
set -euo pipefail
cd "$(dirname "$0")/../.."
arch=""
compile_only=0
tag="fabro"
while [ $# -gt 0 ]; do
case "$1" in
--arch)
arch="$2"
shift 2
;;
--tag)
tag="$2"
shift 2
;;
--compile-only)
compile_only=1
shift
;;
*)
echo "unknown argument: $1" >&2
exit 1
;;
esac
done
if [ -z "$arch" ]; then
case "$(uname -m)" in
x86_64|amd64) arch=amd64 ;;
aarch64|arm64) arch=arm64 ;;
*) echo "unsupported host arch: $(uname -m)" >&2; exit 1 ;;
esac
fi
case "$arch" in
amd64) target=x86_64-unknown-linux-musl zig_arch=x86_64 ;;
arm64) target=aarch64-unknown-linux-musl zig_arch=aarch64 ;;
*) echo "unsupported arch: $arch (expected amd64 or arm64)" >&2; exit 1 ;;
esac
ZIG_VERSION=0.13.0
echo "Building fabro-cli for $target inside rust:1-bookworm via cargo-zigbuild..."
docker run --rm --platform "linux/$arch" \
-v "$PWD:/src" \
-v fabro-docker-cargo-registry:/usr/local/cargo/registry \
-v "fabro-docker-cargo-target-$arch:/target" \
-v "fabro-docker-zig-$arch:/opt/zig" \
-v "fabro-docker-cargo-tools-$arch:/opt/cargo-tools" \
-w /src \
-e CARGO_TARGET_DIR=/target \
-e LIBZ_SYS_STATIC=1 \
rust:1-bookworm \
bash -c "
set -e
apt-get update -qq && apt-get install -y -qq pkg-config perl make cmake xz-utils curl >/dev/null
if [ ! -x /opt/zig/zig-linux-$zig_arch-$ZIG_VERSION/zig ]; then
curl -fsSL https://ziglang.org/download/$ZIG_VERSION/zig-linux-$zig_arch-$ZIG_VERSION.tar.xz | tar -xJ -C /opt/zig
fi
export PATH=/opt/cargo-tools/bin:/opt/zig/zig-linux-$zig_arch-$ZIG_VERSION:\$PATH
if ! command -v cargo-zigbuild >/dev/null; then
cargo install --locked --root /opt/cargo-tools cargo-zigbuild
fi
rustup target add $target
cargo zigbuild --release -p fabro-cli --target $target
"
echo "Extracting binary from builder cache..."
mkdir -p "docker-context/$arch"
docker run --rm --platform "linux/$arch" \
-v "fabro-docker-cargo-target-$arch:/target" \
-v "$PWD/docker-context/$arch:/out" \
rust:1-bookworm \
cp "/target/$target/release/fabro" /out/fabro
if [ "$compile_only" -eq 1 ]; then
echo "Staged docker-context/$arch/fabro (skipping docker build per --compile-only)."
exit 0
fi
echo "Building Docker image as $tag..."
docker build --platform "linux/$arch" -t "$tag" .