Skip to content

Create an Docker image for the bencher CLI - #683

Merged
epompeii merged 2 commits into
develfrom
u/ep/cli-docker
Mar 3, 2026
Merged

Create an Docker image for the bencher CLI#683
epompeii merged 2 commits into
develfrom
u/ep/cli-docker

Conversation

@epompeii

@epompeii epompeii commented Mar 3, 2026

Copy link
Copy Markdown
Member

This changeset creates a Docker (OCI) image for the bencher CLI.

This will allow you to run:

  1. Build the image
docker build -f services/cli/Dockerfile --build-arg MOLD_VERSION=2.34.1 --tag bencher . 
  1. Run the image container
docker run --rm bencher mock

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

PR: #683
Base: devel
Head: u/ep/cli-docker
Commit: c8da482f85ccde81acfaef11cb9839dbecfc7c9b


Good — the CLI docker build step structure is consistent with the API docker build. Now I have all the information needed for the review.


PR Review: CLI Docker Image & Minimal Dependencies

Commits

  1. 9bde7fcc9cli_docker: Initial CLI Dockerfile with full COPY of all crates
  2. c8da482f8minimal_deps: Optimize to only COPY crates actually needed by bencher_cli

Overall Assessment

This is a clean, well-structured PR that adds Docker support for the bencher CLI binary. The approach closely follows the existing patterns from the API and Console Dockerfiles, and the minimal_deps optimization is a good idea — stubbing out unneeded crates avoids copying large source trees and improves Docker layer caching.


Positive Observations

  • Consistent patterns: The build.yml, release.yml, and ci.yml changes mirror the existing API/Console docker jobs exactly.
  • Minimal runtime image: Uses distroless/cc-debian12 with only the binary — no shell, no unnecessary libs. Good security posture.
  • Smart dependency pruning (minimal_deps): Only copies the 7 lib/ crates actually in the bencher_cli dependency tree (bencher_adapter, bencher_client, bencher_comment, bencher_context, bencher_json, bencher_parser, bencher_valid). All plus/, api_*, and server-only lib crates are stubbed.
  • .dockerignore properly restricts the build context.
  • CLAUDE.md updated to reflect three Dockerfiles.

Issues

1. Docker layer caching — many RUN cargo init layers (Minor)

services/cli/Dockerfile:19-63 — There are 35 separate RUN cargo init commands, each creating its own Docker layer. While this matches the Console Dockerfile pattern, consider collapsing them into fewer RUN commands joined by && to reduce the number of layers.

This is a minor optimization and the current approach is consistent with existing Dockerfiles, so it's fine to leave as-is if consistency is preferred.

2. MOLD_VERSION build arg with no default (Potential build failure)

services/cli/Dockerfile:12ARG MOLD_VERSION has no default. If someone runs docker build locally without passing --build-arg MOLD_VERSION=..., the mold download URL will be malformed and the build will fail with an opaque curl error. The API Dockerfile has the same issue, so this is consistent, but worth noting.

3. Missing services/cli/Cargo.toml in .dockerignore exclusion for full context

services/cli/Dockerfile.dockerignore:12 — The exclusion !services/cli/Cargo.toml is present, which is correct. However, the .dockerignore does not exclude !services/api/ or !services/runner/ directories. Since the Dockerfile only does COPY services/api/openapi.json and RUN cargo init api / RUN cargo init runner, the current .dockerignore correctly excludes these via the * glob (only !services/api/openapi.json would be needed for the openapi.json, and it's already covered by the more general path patterns). Looks correct.

4. bencher_client/build.rs reads ../../services/api/openapi.json (Correctly handled)

services/cli/Dockerfile:86 — The COPY services/api/openapi.json line is necessary because bencher_client's build.rs reads this file via a relative path. This is correctly handled.

5. No --platform specified in Docker build

services/cli/Dockerfile and .github/workflows/build.yml:202-213 — QEMU is set up but no --platform flag is passed to docker/build-push-action. The API docker build has the same pattern, so this is consistent. The build will default to the host architecture (linux/amd64 on the ubuntu runner). If multi-arch CLI images are desired in the future, a platforms input would need to be added.

6. Artifact naming collision potential

.github/workflows/build.yml:30-31CLI_DOCKER_IMAGE is set to bencher while CLI_BIN_NAME (in release.yml) is also bencher. The artifact is bencher.tar.gz. Since release.yml uploads both the Docker image tarball and the CLI binary (with version/arch suffixes), there shouldn't be an actual collision, but the naming is worth being aware of.

7. Missing services/cli/Dockerfile in the .dockerignore itself

services/cli/Dockerfile.dockerignore — The Dockerfile itself is not excluded from the build context. This is a very minor point — it won't affect the build, but is slightly non-idiomatic.


Security

  • Base images are pinned by SHA256 digest — good practice.
  • Distroless runtime image has minimal attack surface.
  • No secrets embedded in the image.
  • The ENTRYPOINT is just the CLI binary — no shell available in the final image.

No Issues Found With

  • Release workflow: Download, load, tag, push to GHCR and Docker Hub are all consistent with the existing API/Console patterns.
  • CI filter paths: services/cli/Dockerfile is correctly added to the docker filter.
  • The CLAUDE.md update correctly changes "both" to "all three".

Summary

Approve with minor suggestions. The PR is well-constructed and follows existing project patterns faithfully. The main substantive work (Dockerfile, CI/CD integration, minimal dependency optimization) is all correct. No bugs or security concerns found.


Model: claude-opus-4-6

@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchu/ep/cli-docker
Testbedubuntu-22.04
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
microseconds (µs)
(Result Δ%)
Upper Boundary
microseconds (µs)
(Limit %)
Adapter::Json📈 view plot
🚷 view threshold
3.72 µs
(+13.33%)Baseline: 3.29 µs
4.46 µs
(83.43%)
Adapter::Magic (JSON)📈 view plot
🚷 view threshold
3.79 µs
(+15.14%)Baseline: 3.29 µs
4.42 µs
(85.84%)
Adapter::Magic (Rust)📈 view plot
🚷 view threshold
25.94 µs
(+2.51%)Baseline: 25.31 µs
31.20 µs
(83.13%)
Adapter::Rust📈 view plot
🚷 view threshold
2.83 µs
(+0.87%)Baseline: 2.81 µs
3.46 µs
(81.94%)
Adapter::RustBench📈 view plot
🚷 view threshold
2.78 µs
(-0.80%)Baseline: 2.81 µs
3.44 µs
(81.05%)
head_version_insert/batch/10📈 view plot
🚷 view threshold
98.74 µs
(+2.40%)Baseline: 96.43 µs
123.61 µs
(79.88%)
head_version_insert/batch/100📈 view plot
🚷 view threshold
232.46 µs
(+0.22%)Baseline: 231.95 µs
262.84 µs
(88.44%)
head_version_insert/batch/255📈 view plot
🚷 view threshold
456.67 µs
(+0.08%)Baseline: 456.31 µs
492.17 µs
(92.79%)
head_version_insert/batch/50📈 view plot
🚷 view threshold
155.92 µs
(+0.03%)Baseline: 155.88 µs
181.82 µs
(85.75%)
threshold_query/join/10📈 view plot
🚷 view threshold
138.72 µs
(-0.15%)Baseline: 138.93 µs
168.08 µs
(82.53%)
threshold_query/join/20📈 view plot
🚷 view threshold
154.79 µs
(+1.14%)Baseline: 153.05 µs
182.53 µs
(84.80%)
threshold_query/join/5📈 view plot
🚷 view threshold
132.58 µs
(+0.78%)Baseline: 131.56 µs
158.24 µs
(83.79%)
threshold_query/join/50📈 view plot
🚷 view threshold
195.27 µs
(+0.79%)Baseline: 193.73 µs
226.18 µs
(86.33%)
🐰 View full continuous benchmarking report in Bencher

@epompeii
epompeii merged commit 15ac855 into devel Mar 3, 2026
58 of 60 checks passed
@epompeii
epompeii deleted the u/ep/cli-docker branch March 3, 2026 04:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant