| 1 | # syntax=docker/dockerfile:1 |
| 2 | # Codewhale multi-arch Docker image (#501) |
| 3 | # |
| 4 | # Build: docker buildx build --platform linux/amd64,linux/arm64 -t codewhale:latest . |
| 5 | # Run: docker run --rm -it -e DEEPSEEK_API_KEY -v codewhale-home:/home/codewhale/.codewhale codewhale |
| 6 | # |
| 7 | # The image ships the canonical binaries (`codewhale`, `codew`, and |
| 8 | # `codewhale-tui`) in a minimal runtime layer. |
| 9 | # |
| 10 | # API keys MUST be passed at runtime (never baked into the image): |
| 11 | # docker run --rm -it -e DEEPSEEK_API_KEY codewhale |
| 12 | # Or mount an env file: |
| 13 | # docker run --rm -it --env-file .env codewhale |
| 14 | |
| 15 | ARG RUST_VERSION=1.88 |
| 16 | |
| 17 | # ── Stage 1: Build ──────────────────────────────────────────────────── |
| 18 | FROM --platform=$BUILDPLATFORM rust:${RUST_VERSION}-slim-bookworm AS builder |
| 19 | ARG TARGETPLATFORM |
| 20 | ARG TARGETARCH |
| 21 | ARG BUILDPLATFORM |
| 22 | ARG DEEPSEEK_BUILD_SHA |
| 23 | |
| 24 | ENV CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc \ |
| 25 | CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \ |
| 26 | PKG_CONFIG_ALLOW_CROSS=1 \ |
| 27 | PKG_CONFIG_LIBDIR_aarch64_unknown_linux_gnu=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig \ |
| 28 | DEEPSEEK_BUILD_SHA=${DEEPSEEK_BUILD_SHA} |
| 29 | |
| 30 | RUN if [ "${TARGETARCH}" = "arm64" ] && [ "${BUILDPLATFORM}" != "${TARGETPLATFORM}" ]; then \ |
| 31 | dpkg --add-architecture arm64; \ |
| 32 | fi \ |
| 33 | && apt-get update \ |
| 34 | && apt-get install -y --no-install-recommends \ |
| 35 | pkg-config libdbus-1-dev \ |
| 36 | && if [ "${TARGETARCH}" = "arm64" ] && [ "${BUILDPLATFORM}" != "${TARGETPLATFORM}" ]; then \ |
| 37 | apt-get install -y --no-install-recommends \ |
| 38 | gcc-aarch64-linux-gnu libc6-dev-arm64-cross libdbus-1-dev:arm64; \ |
| 39 | fi \ |
| 40 | && rm -rf /var/lib/apt/lists/* |
| 41 | |
| 42 | # Translate Docker platform into Rust target triple. |
| 43 | # linux/amd64 → x86_64-unknown-linux-gnu |
| 44 | # linux/arm64 → aarch64-unknown-linux-gnu |
| 45 | RUN case "${TARGETPLATFORM}" in \ |
| 46 | linux/amd64) echo x86_64-unknown-linux-gnu > /rust-target ;; \ |
| 47 | linux/arm64) echo aarch64-unknown-linux-gnu > /rust-target ;; \ |
| 48 | *) echo "Unsupported platform: ${TARGETPLATFORM}" >&2; exit 1 ;; \ |
| 49 | esac |
| 50 | |
| 51 | RUN rustup target add "$(cat /rust-target)" |
| 52 | |
| 53 | WORKDIR /build |
| 54 | COPY . . |
| 55 | |
| 56 | # Build both binaries for the target platform. --locked ensures |
| 57 | # reproducible builds from the committed lockfile. |
| 58 | RUN --mount=type=cache,id=codewhale-target-${TARGETARCH},target=/build/target,sharing=locked \ |
| 59 | --mount=type=cache,id=codewhale-cargo-registry-${TARGETARCH},target=/usr/local/cargo/registry,sharing=locked \ |
| 60 | --mount=type=cache,id=codewhale-cargo-git-${TARGETARCH},target=/usr/local/cargo/git,sharing=locked \ |
| 61 | rustup target add "$(cat /rust-target)" \ |
| 62 | && cargo build --release --locked --target "$(cat /rust-target)" \ |
| 63 | -p codewhale-cli -p codewhale-tui \ |
| 64 | && mkdir -p /out \ |
| 65 | && cp target/$(cat /rust-target)/release/codewhale /out/ \ |
| 66 | && cp target/$(cat /rust-target)/release/codew /out/ \ |
| 67 | && cp target/$(cat /rust-target)/release/codewhale-tui /out/ |
| 68 | |
| 69 | # ── Stage 2: Runtime ────────────────────────────────────────────────── |
| 70 | FROM debian:bookworm-slim |
| 71 | |
| 72 | RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 73 | ca-certificates \ |
| 74 | libdbus-1-3 \ |
| 75 | && rm -rf /var/lib/apt/lists/* |
| 76 | |
| 77 | # Non-root user with explicit UID/GID for filesystem ownership clarity. Keep |
| 78 | # the legacy state directory for read-fallback migration; v0.9.0 no longer |
| 79 | # ships legacy deepseek command shims. |
| 80 | RUN groupadd --gid 1000 codewhale \ |
| 81 | && useradd --create-home --shell /bin/bash --uid 1000 --gid 1000 codewhale \ |
| 82 | && install -d -m 0700 -o codewhale -g codewhale /home/codewhale/.codewhale \ |
| 83 | && install -d -m 0700 -o codewhale -g codewhale /home/codewhale/.deepseek |
| 84 | USER codewhale |
| 85 | WORKDIR /home/codewhale |
| 86 | |
| 87 | COPY --from=builder --chown=codewhale:codewhale /out/codewhale /usr/local/bin/codewhale |
| 88 | COPY --from=builder --chown=codewhale:codewhale /out/codew /usr/local/bin/codew |
| 89 | COPY --from=builder --chown=codewhale:codewhale /out/codewhale-tui /usr/local/bin/codewhale-tui |
| 90 | |
| 91 | # The dispatcher expects to find its companion binary next to it. |
| 92 | # Both are in /usr/local/bin — no further path setup needed. |
| 93 | |
| 94 | ENTRYPOINT ["codewhale"] |
| 95 | CMD [] |
| 96 |