Conversation
Refs nxcite#16 (the Docker half). - Dockerfile: rust:1-bookworm builder (ring still wants a C compiler) into gcr.io/distroless/cc-debian12:nonroot — glibc plus the CA roots rustls-native-certs reads for S3, no shell, uid 65532. - .github/workflows/docker.yml: one native runner per architecture (amd64 on ubuntu-24.04, arm64 on ubuntu-24.04-arm, both free on public repos) rather than one job emulating arm64 under QEMU. Each pushes a digest-only image; a final job stitches the digests into one multi-arch tag. PRs build without pushing, so fork PRs work. Publishes to ghcr.io/${{ github.repository }} — no registry secrets to configure. - release.yml calls docker.yml after cutting the release. A `push: tags:` trigger would not work: the tag is created with `gh release create` using GITHUB_TOKEN, and GITHUB_TOKEN events do not start workflow runs. - README: docker run example, tag scheme, and a plain Deployment/Service for Kubernetes.
|
Force-pushed a revision after a review pass. Four fixes, one of which killed half the original PR: 1. Releases would never have published an image. The first version triggered on 2. Concurrency was keyed wrong. 3. Runs as non-root. 4. README was wrong about credentials. Neither the Also dropped Verified locally on this branch: One thing that needs a maintainer, not a commit: the first push creates the GHCR package as private, so anonymous Still no Helm chart, for the reasons in the description — happy to be talked out of that. 🤖 Generated with Claude Code |
Addresses the Docker half of #16.
What's here
Dockerfile—rust:1-bookwormbuilder (not-slim:ringstill needs a C compiler) intogcr.io/distroless/cc-debian12, which gives glibc plus the CA roots rustls needs to trust S3, and no shell. Cargo registry and target dir are BuildKit cache mounts; the target mount is keyed onTARGETPLATFORMso a single-builder multi-arch build can't have the twocargos racing on the sametarget/release/nx-cache-awspath..github/workflows/docker.yml— publishes toghcr.io/${{ github.repository }}..dockerignoreREADME.md— adocker runexample, the tag scheme, and a plain Deployment/Service for Kubernetes.Why a matrix instead of one multi-platform build
Building both platforms in one job puts arm64 through QEMU, which is roughly an order of magnitude slower on a release build. Hosted arm runners are free on public repos, so each half compiles natively. Each build job pushes an untagged digest-only image and hands the digest to the
manifestjob via an artifact; that job stitches both digests into one tag. This is the pattern from the Docker docs for distributing a build across runners.Details worth knowing:
outputs: type=cacheonly), so PRs from forks work without registry credentials.GITHUB_TOKENalready haspackages: write, so this works the moment it merges with nothing for you to configure. Docker Hub needs a repo created plusDOCKERHUB_USERNAME/DOCKERHUB_TOKENsecrets — happy to add that login step if you'd rather publish there, or in addition.latesttracks the newest release, not the tip ofmaster(metadata-action'slatest=auto).masterpushes publishmasterandsha-<short-sha>.concurrencygroup is keyed on the SHA: a release push updates bothmasterand thevX.Y.Ztag, and this collapses the two runs into one build that publishesX.Y.Z.No Helm chart
Deliberately left out. The server is one stateless container with no volumes, no sidecars, and about five environment variables — a chart would add a values schema, chart versioning, a chart repo to host, and CI to publish it, for something
kubectl applyalready does. The README section covers it in ~35 lines, including the note that on EKS you drop the AWS credential variables and attach an IAM role to the ServiceAccount. Glad to reconsider if you disagree.Verified
docker build --platform linux/arm64 .succeeds on this tree (Apple Silicon).actionlintclean on the workflow.master, and it should go green on this PR (build-only, no push).🤖 Generated with Claude Code