Skip to content

ci: single-source glibc image (zigbuild 2.28 + distroless + prebuilt binary)#61

Merged
wadahiro merged 2 commits into
mainfrom
ci/docker-single-source-glibc
Jun 13, 2026
Merged

ci: single-source glibc image (zigbuild 2.28 + distroless + prebuilt binary)#61
wadahiro merged 2 commits into
mainfrom
ci/docker-single-source-glibc

Conversation

@wadahiro

Copy link
Copy Markdown
Owner

Addresses two issues raised on the release pipeline:

  1. The container binary wasn't the published binary (different libc/build → different hash). Now the image contains the exact released binary.
  2. The image wasn't usable out of the box (forced --config → crash without a mount; default bind 127.0.0.1 unreachable in a container).

Single source of truth (glibc)

  • Linux binaries built with cargo-zigbuild, glibc floor 2.28 (RHEL 8 / Debian 10), on the stable ubuntu-latest runner. One binary runs on every currently-supported distro (RHEL 8/9, Debian 10–13, Ubuntu 20.04+) and in the container — independent of the runner's own glibc, so we never have to chase runner OS / glibc versions again.
    • Why a low floor is safe: glibc is dynamically linked, so the binary runs against the host/container glibc (the container uses distroless debian13 = glibc 2.41, kept patched via base-image updates). The floor only bounds the symbol set, not the runtime glibc.
    • archive keeps the published asset names unchanged (no .2.28 suffix).
  • The docker job no longer compiles. It downloads the just-published linux binaries and COPYs them into the image (Dockerfile.release), so the container and the downloadable binary are byte-identical. No RUN steps → the multi-arch image is assembled by COPY alone (no QEMU), in a single fast job.

Images

  • Dockerfile.release (new): runtime-only, FROM gcr.io/distroless/cc-debian13:nonroot (latest distroless, glibc 2.41), COPY bin/scim-server-${TARGETARCH}.
  • Dockerfile: self-contained dev/compose/CI build switched from alpine/musl to a glibc toolchain (rust:1.96-bookworm) + distroless/cc-debian13 runtime, matching the released runtime.
  • .dockerignore added.

Usability

  • Default CMD ["--host", "0.0.0.0"]docker run -p 3000:3000 IMAGE runs a zero-config demo (in-memory SQLite, unauthenticated) reachable on the published port. For real use:
    docker run -p 3000:3000 -v $PWD/config.yaml:/data/config.yaml \
      ghcr.io/wadahiro/scim-server:latest --config /data/config.yaml
    
  • docker-compose.yml sets command: ["--config", "/data/config.yaml"] explicitly.

Verified locally

  • Self-contained image builds, runs (scim-server 0.4.0), and serves ServiceProviderConfigHTTP 200 bound to 0.0.0.0 (zero-config). Size 73.6MB.
  • Dockerfile.release COPY path builds (no compile) and runs.

Not yet exercised in CI

  • The cargo-zigbuild glibc-2.28 compile and the full download→COPY→multi-arch push run for the first time on the next release. I can run a throwaway end-to-end verification first (as we did for the multi-arch change) if you'd like — say the word.

🤖 Generated with Claude Code

wadahiro and others added 2 commits June 13, 2026 17:10
…ilt binary)

Make the published container image contain the *exact* binary published as a
release asset (byte-identical), on a stable glibc footing, and make the image
usable out of the box.

Release binaries (release.yml):
- Build the linux binaries with cargo-zigbuild pinned to a glibc 2.28 floor
  (RHEL 8 / Debian 10), on the stable `ubuntu-latest` runner. One binary then
  runs on every currently-supported distro (RHEL 8/9, Debian 10–13, Ubuntu
  20.04+) and on the distroless runtime — independent of the runner's glibc.
  `archive` keeps the published asset name free of the `.2.28` suffix.
- The `docker` job no longer compiles: it downloads the just-published linux
  binaries and COPYs them into the image (Dockerfile.release). The container
  and the downloadable binary are therefore identical. With no RUN steps the
  multi-arch image is assembled by COPY alone (no QEMU), in a single job.

Images:
- Dockerfile.release (new): runtime-only, FROM distroless/cc-debian13 (latest,
  glibc 2.41), COPY bin/scim-server-${TARGETARCH}.
- Dockerfile: self-contained build for dev/compose/CI switched from
  alpine/musl to a glibc toolchain (rust:1.96-bookworm) + distroless/cc-debian13
  runtime, so local images match the released runtime.
- Add .dockerignore to shrink the build context.

Usability:
- Default CMD is now `--host 0.0.0.0` → `docker run -p 3000:3000 IMAGE` starts a
  zero-config demo (in-memory SQLite, unauthenticated) reachable on the
  published port. For real use, mount a config and pass `--config
  /data/config.yaml`. docker-compose sets that command explicitly.

Verified locally: self-contained image builds, runs, and serves
ServiceProviderConfig (HTTP 200) bound to 0.0.0.0; Dockerfile.release COPY path
builds and runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Release the single-source glibc image and zero-config-demo usability change.

Release-As: 0.4.1
@wadahiro wadahiro merged commit 49d5672 into main Jun 13, 2026
12 checks passed
@wadahiro wadahiro deleted the ci/docker-single-source-glibc branch June 13, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant