docker: multi-stage images for most architectures, CI, and fly rewrite - #220
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a container build/publish pipeline for mesh-llm by adding multi-stage Docker images for multiple runtime variants (client, CPU, Vulkan, CUDA, ROCm), plus a GitHub Actions workflow to build/push them (including multi-arch manifests where applicable). It also rewrites fly/Dockerfile to include a UI build stage so Fly deploys work from a clean checkout.
Changes:
- Added multi-stage Dockerfiles for client/CPU/Vulkan/CUDA/ROCm variants and a shared
docker/entrypoint.sh. - Added
.github/workflows/docker.ymlto build/push per-arch images and merge multi-arch manifests for select variants. - Added a spec-compliance harness (
scripts/verify-docker-spec.sh) and human tracker (docker/SPEC_COMPLIANCE.md); updatedJustfilewith Docker build/run recipes.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
.dockerignore |
Ignores Node/UI artifacts and local/editor state to keep Docker contexts clean |
.github/workflows/docker.yml |
New CI workflow to build/push Docker images and create multi-arch manifests |
Justfile |
Adds just docker-build-* and docker-run-* helper recipes |
docker/Dockerfile.client |
Multi-stage client-only image (UI build + Rust build) |
docker/Dockerfile.cpu |
Multi-stage CPU image including llama.cpp CPU build |
docker/Dockerfile.vulkan |
Multi-stage Vulkan image including llama.cpp Vulkan build |
docker/Dockerfile.cuda |
Multi-stage CUDA image including llama.cpp CUDA build |
docker/Dockerfile.rocm |
Multi-stage ROCm image including llama.cpp ROCm build |
docker/entrypoint.sh |
Shared runtime entrypoint selecting behavior via APP_MODE |
docker/SPEC_COMPLIANCE.md |
Human-readable checklist mirroring the verifier script |
fly/Dockerfile |
Rewritten multi-stage Fly console image including UI build stage |
scripts/verify-docker-spec.sh |
New script enforcing Docker/spec invariants across files |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
eb92950 to
fe2dd9a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
49b172b to
d45ea15
Compare
d45ea15 to
ad6213e
Compare
i386
left a comment
There was a problem hiding this comment.
LGTM - I would just double check some of the copilot comments before merging.
4e02ec3 to
0cf85f6
Compare
* main: (50 commits) v0.60.0-rc.1: prerelease Support exact release updates Add prerelease release flow docker: multi-stage images for most architectures, CI, and fly rewrite (#220) ui: always handle images and PDFs in the browser Fix MoE canonical ranking review feedback Resolve remaining MoE review threads Fix remaining MoE review feedback Add HF job pricing estimates for MoE analysis Fix MoE review follow-ups Add built-in HF job workflow for MoE analysis Fix HF job submission script and sanitize labels Refine MoE ranking runtime and share UX Fix MoE ranking resolution review feedback Rename MoE commands and suggest sharing rankings feat: add moe planning, analysis, and submission commands Fix runtime process-name validation fallback Fix PR 217 process reaping and merge build break feat(hardware): add hardware information enrichment runtime: fix reaper signal logic, force_killed accounting, zero start-time handling, and dir permissions ...
Summary
This PR adds five multi-stage Docker images (client, cpu, vulkan, cuda, rocm), a CI workflow that publishes them as native multi-arch manifests, and fixes a latent bug in
fly/Dockerfilethat would break any cleanroom deploy.What you can do now
Or build locally with the new
justrecipes:just docker-build-client just docker-build-cpu just docker-build-vulkan just docker-build-cuda # override arch: just docker-build-cuda "mesh-llm:cuda" "75;80" just docker-build-rocmImages published
:latest,:client:cpu:vulkan:cuda:rocmAll images ship a shared entrypoint with three modes selected via
APP_MODE:console(default) — client node, API on:9337, web console on:3131worker— full node with bundled llama binaries at/usr/local/lib/mesh-llm/bin/mesh-llmThe UI is embedded in the binary (
include_dir!) and always co-deployed with the runtime — there is no UI-less mode.Fly.io deploys now actually work from clean state
fly/Dockerfilepreviously used a singleFROM rust:lateststage with no UI build step. It relied onmesh-llm/ui/dist/already existing in the build context, so any deploy from a fresh checkout would hit theinclude_dir!compile-time macro and fail.This PR rewrites it as a 4-stage multi-stage build structurally identical to
docker/Dockerfile.client, withnode:24-alpinebuilding the UI anddebian:bookworm-slimfor the runtime.fly.tomlis untouched — the runtime contract (EXPOSE 3131 9337,ENV APP_MODE=console,ENTRYPOINT ["/entrypoint.sh"]) is preserved, sofly deploy --config fly/console/fly.toml --dockerfile fly/Dockerfileworks unchanged. Cleanroom worktree builds are part of the test evidence.Architecture
Multi-stage pattern (all Dockerfiles). Four or five stages:
ui-builder(node:24-alpine) →rust-deps(cargo-chef 0.1.68 with full workspace manifests +mesh-llm/proto/) →rust-builder(overwrites stubui/distwith real build beforecargo build --release --locked) → optionalllama-builder-<flavor>(clonesmichaelneale/llama.cpp@upstream-latest, shared cmake flagsGGML_RPC=ON BUILD_SHARED_LIBS=OFF LLAMA_OPENSSL=OFF CMAKE_BUILD_TYPE=Release) →runtime.Llama binaries land at
/usr/local/lib/mesh-llm/bin/{rpc-server,llama-server}-<flavor>with an unsuffixedllama-moe-splitshared across flavors. The llama.cpp commit SHA is baked into/usr/local/share/mesh-llm/llama-revision.txtand an OCI label.CUDA correctness.
docker/Dockerfile.cudaships-DGGML_CUDA_FA_ALL_QUANTS=ON— this is a correctness requirement, not a perf tuning knob. Without it, asymmetric K/V quantization paths hitBEST_FATTN_KERNEL_NONEand crash rpc-server (see ggml-org/llama.cpp#20866). The CI workflow grep-verifiesGGML_CUDA_FA_ALL_QUANTS:BOOL=ONappears in the CMake cache on every CUDA build, so the flag cannot silently drop.Spec compliance harness.
scripts/verify-docker-spec.shenforces 13 invariants across all Dockerfiles and the workflow (ui-builder before cargo build,libdbus-1-devfor keyring sync-secret-service, nojust bundle, noprotobuf-compilerapt package since protoc is vendored viaprotoc_bin_vendored, no QEMU, flavored binary naming, runtime libsca-certificates libgomp1 libdbus-1-3, etc.). Current state: 52 PASSED, 0 FAILED.docker/SPEC_COMPLIANCE.mdtracks each item with file:line references and a verification log.CI.
.github/workflows/docker.ymldefines 11 jobs: client/cpu/vulkan × (amd64, arm64, merge) + cuda + rocm amd64-only. ARM64 uses nativeubuntu-24.04-armrunners — no QEMU anywhere. Merge jobs stitch per-arch digests withdocker buildx imagetools create. GHA cache scopes are split so a Rust-only change invalidates only the llama layer of one variant, and CUDA/ROCm caches are isolated from debian-based variants (different base images).release.ymlis untouched — no coupling in either direction.Validation
bash scripts/verify-docker-spec.sh→ 52 PASSED / 0 FAILED / 0 SKIPPED--versionreturnsmesh-llm 0.58.0, flavored binaries present at expected paths,lddreports zero unresolved libs on the client image, all images under their size budgets (250 MB / 600 MB / 900 MB / 4.5 GB / 12 GB respectively).fly/Dockerfilecleanroom build verified viagit worktree addwithui/distpre-deleted.just docker-build-*recipes dry-runned with arch overrides.Files changed
No changes to
mesh-llm/src/,Cargo.toml,Cargo.lock,release.yml, orfly.toml.Notes for reviewers
:clientimage.docker/SPEC_COMPLIANCE.mdcalls this out.cargo-chefis pinned to0.1.68 --lockedand thecookstep now also uses--lockedfor reproducibility.libvulkan-dev(1.3.239) because currentllama.cpp@upstream-latestneedsVK_EXT_layer_settingsfrom 1.3.261+. The runtime loader from Debian is kept; only headers are upgraded.rocm/dev-ubuntu-24.04:7.0base (not-complete) to keep the image reasonable —-completeis ~20 GB.fly/Dockerfileconvention; K3S/pod users can override viasecurityContext.runAsNonRoot.Closes #115