99#
1010# Build Hygiene Rules:
1111# - Prefer `RUN --mount=type=cache` for package caches (`apt`, `bun`, `cargo`,
12- # `pip`, and `pnpm/npm`) when BuildKit is available.
12+ # `pip`, and `pnpm/npm`) when BuildKit is available. New RUN steps that
13+ # download or compile dependencies should reuse existing cache mounts or add
14+ # new ones following the same patterns:
15+ # - APT: --mount=type=cache,target=/var/lib/apt/lists
16+ # --mount=type=cache,target=/var/cache/apt
17+ # - Cargo: --mount=type=cache,id=cargo-registry-${TARGETARCH},target=...registry,uid=1000,gid=1000,mode=0755
18+ # (also cargo-git and cargo-target; scope per TARGETARCH for multi-platform)
19+ # - Bun: --mount=type=cache,target=.../.bun/install/cache,uid=1000,gid=1000,mode=0755
20+ # - pip: --mount=type=cache,target=.../.cache/pip,uid=1000,gid=1000,mode=0755
21+ # For non-root caches, always set uid/gid/mode and add a `chown -R` guard
22+ # at the start of the RUN body to fix subdirectory ownership from prior builds.
1323# - Remove temp workdirs in the same layer where they are created (for example
1424# `/tmp/opencode-repo`) so transient artifacts do not persist in image layers.
1525# - Do not rely on cleanup in later layers; deleted files still exist in lower
@@ -295,11 +305,15 @@ RUN eval "$(/home/opencoder/.local/bin/mise activate bash)" \
295305# -----------------------------------------------------------------------------
296306# ripgrep 15.1.0 - fast regex search
297307# eza 0.23.4 - modern ls replacement
298- # NOTE: Avoid cache mounts here due to permission issues with non-root Cargo cache
299- RUN mkdir -p /home/opencoder/.cargo/registry /home/opencoder/.cargo/git \
308+ # Cache cargo registry/git indices across builds to skip re-downloading crate metadata.
309+ # Scoped per architecture to prevent amd64/arm64 cache corruption during multi-platform builds.
310+ # uid/gid match opencoder (1000); chown fixes subdirectory ownership from prior builds.
311+ ARG TARGETARCH
312+ RUN --mount=type=cache,id=cargo-registry-${TARGETARCH},target=/home/opencoder/.cargo/registry,uid=1000,gid=1000,mode=0755 \
313+ --mount=type=cache,id=cargo-git-${TARGETARCH},target=/home/opencoder/.cargo/git,uid=1000,gid=1000,mode=0755 \
314+ sudo chown -R opencoder:opencoder /home/opencoder/.cargo/registry /home/opencoder/.cargo/git \
300315 && . /home/opencoder/.cargo/env \
301- && cargo install --locked ripgrep@15.1.0 eza@0.23.4 \
302- && rm -rf /home/opencoder/.cargo/registry /home/opencoder/.cargo/git
316+ && cargo install --locked ripgrep@15.1.0 eza@0.23.4
303317
304318# lazygit v0.58.1 (2026-01-12) - terminal UI for git
305319# Disabled temporarily to reduce Docker build time.
@@ -510,6 +524,7 @@ USER opencoder
510524ARG OPENCODE_SOURCE=remote
511525ARG OPENCODE_COMMIT
512526ARG OPENCODE_LOCAL_REF
527+ ARG TARGETARCH
513528
514529# CLI builds use a custom build-context generator that always adds
515530# packages/opencode. Repo-root Docker builds rely on checkout + .dockerignore to
@@ -536,7 +551,15 @@ COPY --chown=opencoder:opencoder packages/opencode /tmp/opencode-local
536551# which causes `bun install --frozen-lockfile` to fail nondeterministically.
537552# - The retry loop intentionally clears only this cache dir between attempts so
538553# each retry gets a clean cache state while preserving reproducibility.
554+ # Cargo cache mounts: registry/git for crate metadata, target dir for compiled
555+ # artifacts (the big win — enables incremental compilation across builds).
556+ # Target dir lives at /tmp/cargo-target-broker instead of inside the source tree
557+ # to avoid conflicts with `rm -rf /tmp/opencode-repo` cleanup later in this RUN.
558+ # All cargo caches scoped per TARGETARCH to prevent multi-platform corruption.
539559RUN --mount=type=cache,target=/home/opencoder/.bun/install/cache,uid=1000,gid=1000,mode=0755 \
560+ --mount=type=cache,id=cargo-registry-${TARGETARCH},target=/home/opencoder/.cargo/registry,uid=1000,gid=1000,mode=0755 \
561+ --mount=type=cache,id=cargo-git-${TARGETARCH},target=/home/opencoder/.cargo/git,uid=1000,gid=1000,mode=0755 \
562+ --mount=type=cache,id=cargo-target-broker-${TARGETARCH},target=/tmp/cargo-target-broker,uid=1000,gid=1000,mode=0755 \
540563 OPENCODE_COMMIT_OVERRIDE="${OPENCODE_COMMIT:-}" \
541564 && OPENCODE_LOCAL_REF="${OPENCODE_LOCAL_REF:-local-unknown}" \
542565 && OPENCODE_COMMIT="9fc1f2cd6084bb1611ee33d7085fa86a5ea6511f" \
@@ -558,6 +581,7 @@ RUN --mount=type=cache,target=/home/opencoder/.bun/install/cache,uid=1000,gid=10
558581 && cd /tmp/opencode-repo \
559582 && sudo mkdir -p /home/opencoder/.bun/install/cache \
560583 && sudo chown -R opencoder:opencoder /home/opencoder/.bun/install/cache \
584+ && sudo chown -R opencoder:opencoder /home/opencoder/.cargo/registry /home/opencoder/.cargo/git /tmp/cargo-target-broker \
561585 && export BUN_INSTALL_CACHE_DIR=/home/opencoder/.bun/install/cache \
562586 && bun_install_ok=0; \
563587 for attempt in 1 2 3; do \
@@ -593,9 +617,9 @@ RUN --mount=type=cache,target=/home/opencoder/.bun/install/cache,uid=1000,gid=10
593617 && sudo chown -R opencoder:opencoder /opt/opencode \
594618 && sudo chmod +x /opt/opencode/bin/opencode \
595619 && cd /tmp/opencode-repo/packages/opencode-broker \
596- && cargo build --release \
620+ && CARGO_TARGET_DIR=/tmp/cargo-target-broker cargo build --release \
597621 && sudo mkdir -p /usr/local/bin \
598- && sudo cp target/release/opencode-broker /usr/local/bin/opencode-broker \
622+ && sudo cp /tmp/cargo- target-broker /release/opencode-broker /usr/local/bin/opencode-broker \
599623 && sudo chmod 4755 /usr/local/bin/opencode-broker \
600624 && rm -rf /tmp/opencode-repo /tmp/opencode-local \
601625 && sudo find /home/opencoder/.bun/install/cache -mindepth 1 -maxdepth 1 -exec rm -rf {} + || true \
0 commit comments