diff --git a/.github/workflows/build-ralphex-fe.yml b/.github/workflows/build-ralphex-fe.yml index e5f5902..a6c9b16 100644 --- a/.github/workflows/build-ralphex-fe.yml +++ b/.github/workflows/build-ralphex-fe.yml @@ -56,7 +56,7 @@ jobs: context: ralphex-fe dockerfile: ralphex-fe/Dockerfile version-tag: ${{ needs.prepare.outputs.version-tag }} - verify-command: 'bun --version && hugo version' + verify-command: 'bun --version && hugo version && rtk --version' extra-verify-script: | chromium-browser --no-sandbox --version && \ test "$PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH" = "/usr/bin/chromium-browser" && \ diff --git a/.hadolint.yaml b/.hadolint.yaml index c78cc9a..b691273 100644 --- a/.hadolint.yaml +++ b/.hadolint.yaml @@ -11,6 +11,18 @@ ignored: - DL3047 # avoid using wget; use curl - DL4001 # either use wget or curl, not both + # --platform on FROM is intentional for cross-compilation (e.g. building + # arm64 musl binaries natively on amd64 to avoid slow QEMU emulation). + - DL3029 # do not use --platform with FROM + + # Dynamic FROM (e.g. FROM stage-${TARGETARCH}) references a build stage, + # not an untagged external image. Hadolint cannot resolve it statically. + - DL3006 # always tag image version explicitly + + # Separate RUN instructions are intentional for Docker layer caching + # (e.g. apk install vs cargo install in builder stages). + - DL3059 # multiple consecutive RUN instructions + # pipefail SHELL not required — only one pipe exists (bun install) # and curl -f already fails on HTTP errors. - DL4006 # set SHELL option -o pipefail before RUN with pipe diff --git a/ralphex-fe/Dockerfile b/ralphex-fe/Dockerfile index b501f95..571487c 100644 --- a/ralphex-fe/Dockerfile +++ b/ralphex-fe/Dockerfile @@ -1,6 +1,31 @@ ARG BUN_VERSION=1.3.9 ARG HUGO_VERSION=0.156.0 ARG RALPHEX_VERSION=0.20.0 +ARG RTK_VERSION=0.26.0 + +# ── RTK builder: amd64 (native musl build on Alpine) ─────────────────── +# rust:alpine already targets musl; just need musl-dev for C dependencies. +FROM --platform=linux/amd64 rust:alpine AS rtk-amd64 +ARG RTK_VERSION +RUN apk add --no-cache musl-dev +RUN cargo install --root /output \ + --git https://github.com/rtk-ai/rtk.git --tag "v${RTK_VERSION}" --locked \ + --target x86_64-unknown-linux-musl + +# ── RTK builder: arm64 (cross-compile with pre-built musl toolchain) ─── +# messense/rust-musl-cross:aarch64-musl provides a complete aarch64 musl +# cross-compiler (CC, linker, headers) pre-configured via .cargo/config.toml. +# Runs natively on amd64 — no QEMU emulation. +FROM --platform=linux/amd64 messense/rust-musl-cross:aarch64-musl AS rtk-arm64 +ARG RTK_VERSION +RUN cargo install --root /output \ + --git https://github.com/rtk-ai/rtk.git --tag "v${RTK_VERSION}" --locked \ + --target aarch64-unknown-linux-musl + +# ── Select the correct builder based on target architecture ───────────── +# BuildKit resolves TARGETARCH per platform; only the needed stage is built. +ARG TARGETARCH +FROM rtk-${TARGETARCH} AS rtk-builder # Extend the ralphex base image which provides the ralphex binary at /srv/ralphex # along with Claude Code, Codex, Node.js, git, ripgrep, and other development tools @@ -62,6 +87,10 @@ RUN set -eux; \ rm hugo.tar.gz hugo_checksums.txt; \ hugo version +# Copy RTK binary from the architecture-matched builder stage +COPY --from=rtk-builder /output/bin/rtk /usr/local/bin/rtk +RUN rtk --version + # OCI labels for container metadata and GitHub Package integration LABEL org.opencontainers.image.source="https://github.com/gatezh/devcontainer-images" LABEL org.opencontainers.image.description="Ralphex-fe: Frontend development image with Bun, Hugo Extended, Chromium, and Ralphex" diff --git a/ralphex-fe/README.md b/ralphex-fe/README.md index 9be6fb6..5f1d967 100644 --- a/ralphex-fe/README.md +++ b/ralphex-fe/README.md @@ -11,6 +11,7 @@ This is a standalone Docker image, not a devcontainer configuration. It can be u - **Bun 1.3.9** - Fast JavaScript runtime, bundler, and package manager - **Hugo Extended 0.155.3** - Full-featured static site generator with extended capabilities - **Chromium** - System browser for headless end-to-end testing +- **RTK 0.26.0** - [Rust Token Killer](https://www.rtk-ai.app/) - CLI proxy to minimize LLM token consumption - **Git** - Version control (included from base) - **Zsh** - Modern shell (included from base)