services: bench: # Pinned to linux/amd64 regardless of host architecture (Docker Desktop emulates via QEMU # on arm64 hosts) -- confirmed necessary, not just cautious: JetBrains doesn't publish a # kotlin-native-prebuilt tarball for linux-aarch64 (Kotlin 2.3.10, as bitcoin-kmp pins it), # so a native linux/arm64 container fails partway through bitcoin-kmp's build even though # secp256k1-kmp's own from-source native build (which cross-compiles both linux-x86_64 and # linux-aarch64 unconditionally either way, see native/toolchain-aarch64.cmake) succeeds # fine under arm64. amd64 also matches secp256k1-kmp's own upstream assumption for this # exact target ("cross-compiled on a linux x64 host" -- see native/build.gradle.kts's # comment on buildSecp256k1LinuxArm64), so this is the well-trodden combination, not a # workaround bolted onto an otherwise-untested path. platform: linux/amd64 build: context: . dockerfile: Dockerfile platforms: - linux/amd64 args: USER_UID: ${HOST_UID:-1000} USER_GID: ${HOST_GID:-1000} # Runs as the host user's own UID/GID (exported by docker/run.sh) so anything the # container writes into a bind-mounted repo is owned by you on the host, not root. user: "${HOST_UID:-1000}:${HOST_GID:-1000}" # Hardening. A JVM/C build needs no Linux capabilities and never needs to gain privileges, # so both are removed outright. This does NOT make the container a security boundary against # whoever starts it -- the daemon is root and its API has no granularity -- but it does # narrow what third-party build code (Gradle scripts and their plugins are Turing-complete # and are fetched from the network) can reach if any of it turns out to be hostile. # If a build ever fails on a genuine capability need, relax this deliberately rather than # by reflex; failing closed is the point. security_opt: - no-new-privileges:true cap_drop: - ALL volumes: # The four repos, bind-mounted read-write (build output lands in the usual # target/build/.gradle directories inside each -- same as a native build would produce). # Paths assume the standard sibling layout under ~/dev/ this project already documents; # override with ECLAIR_DIR / BITCOIN_KMP_DIR / SECP256K1_KMP_DIR env vars if yours differ. # Default to the in-repo snapshot, so `docker compose` works on a bare clone even when it is # invoked directly rather than through run.sh. The runner overrides these with sibling # checkouts when they exist, which is the author's layout. - ${ECLAIR_DIR:-../sources/eclair}:/workspace/eclair - ${BITCOIN_KMP_DIR:-../sources/bitcoin-kmp}:/workspace/bitcoin-kmp - ${SECP256K1_KMP_DIR:-../sources/secp256k1-kmp}:/workspace/secp256k1-kmp - ..:/workspace/benchmark-iceberg # Named (Docker-managed) volumes, NOT bind mounts to your real ~/.m2 / ~/.gradle: build # caches that persist across runs for speed, without ever touching your host toolchain's # own state (a from-source Linux build shouldn't leak Linux-only artifacts into a host # ~/.m2 a native macOS/Windows build also uses). - iceberg-m2:/home/builder/.m2 - iceberg-gradle:/home/builder/.gradle working_dir: /workspace/benchmark-iceberg volumes: iceberg-m2: iceberg-gradle: