-
Notifications
You must be signed in to change notification settings - Fork 3.8k
fix: Docker distroless build failure and critical security updates #22601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Fix distroless build failure by replacing heredoc syntax with explicit shell call - Distroless has no shell, must use /bin/sh from build stage mounts - Fixes CI/CD pipeline that has been failing for months (#20414) - Security updates for base images: - Distroless: debian11 → debian12 (addresses CVEs in #22594) - Alpine: 3.20 → 3.21 (latest stable) - Fix incorrect symlink name 'nodebun' → 'node' in distroless This minimal fix addresses the critical issue preventing distroless images from being published while maintaining the minimal attack surface philosophy of distroless containers.
WalkthroughUpdates Dockerfiles: Alpine base image bumped from 3.20 to 3.21. Distroless base moved from Debian 11 to Debian 12, with symlink bootstrap switched to use the build-stage shell due to distroless lacking a shell, and the node symlink target adjusted. Existing bunx symlink and verification retained. Changes
Suggested reviewers
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
Pre-merge checks (3 passed)✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (4)
dockerhub/alpine/Dockerfile (2)
1-1: Version bump looks good; consider pinning digests.Alpine 3.21 upgrade aligns with the PR’s security intent. To reduce supply-chain drift, consider pinning image digests for both stages.
If desired, I can add a follow-up commit pinning both FROM lines to immutable digests.
Also applies to: 47-47
63-63: Stale comment: references “glibc APKs” but only musl libs are installed.The step installs libgcc/libstdc++ (musl world) and doesn’t fetch glibc APKs. Update the comment for clarity.
-# Temporarily use the `build`-stage /tmp folder to access the glibc APKs: +# Temporarily use the `build`-stage /tmp folder (for artifacts) while creating user/symlinks:dockerhub/distroless/Dockerfile (2)
58-58: Base upgrade to Debian 12 is appropriate; suggest pinning digest.Good move for CVE posture. Pin the distroless base to a digest to avoid unreviewed tag drift.
I can add the specific sha256 if you’d like me to resolve and commit it.
1-1: Add Dockerfile syntax directive for BuildKit mounts.Since this file uses
RUN --mount=..., add a syntax directive to avoid builder variability across environments.+# syntax=docker/dockerfile:1.6 FROM debian:bookworm-slim AS build
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
dockerhub/alpine/Dockerfile(2 hunks)dockerhub/distroless/Dockerfile(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-03T17:10:13.486Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.486Z
Learning: Use `bun bd <...cmd>` to run commands with your debug build of Bun
Applied to files:
dockerhub/distroless/Dockerfile
| # Temporarily use the `build`-stage image binaries to create symlinks: | ||
| # We must use the shell from the build stage since distroless has no shell | ||
| RUN --mount=type=bind,from=build,source=/usr/bin,target=/usr/bin \ | ||
| --mount=type=bind,from=build,source=/bin,target=/bin \ | ||
| --mount=type=bind,from=build,source=/usr/lib,target=/usr/lib \ | ||
| --mount=type=bind,from=build,source=/lib,target=/lib \ | ||
| <<EOF | ||
| ln -s /usr/local/bin/bun /usr/local/bin/bunx | ||
| which bunx | ||
| mkdir -p /usr/local/bun-node-fallback-bin | ||
| ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/nodebun | ||
| EOF | ||
| /bin/sh -c ' \ | ||
| ln -s /usr/local/bin/bun /usr/local/bin/bunx && \ | ||
| which bunx && \ | ||
| mkdir -p /usr/local/bun-node-fallback-bin && \ | ||
| ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node \ | ||
| ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“which” may be unavailable; use POSIX builtin and make symlinks idempotent.
On Debian slim, which isn’t guaranteed (and the mounted build stage may not have it). Use command -v (POSIX builtin) and make ln idempotent with -sf to avoid failures on cache rebuilds.
RUN --mount=type=bind,from=build,source=/usr/bin,target=/usr/bin \
--mount=type=bind,from=build,source=/bin,target=/bin \
--mount=type=bind,from=build,source=/usr/lib,target=/usr/lib \
--mount=type=bind,from=build,source=/lib,target=/lib \
- /bin/sh -c ' \
- ln -s /usr/local/bin/bun /usr/local/bin/bunx && \
- which bunx && \
- mkdir -p /usr/local/bun-node-fallback-bin && \
- ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node \
- '
+ /bin/sh -c ' \
+ ln -sf /usr/local/bin/bun /usr/local/bin/bunx && \
+ command -v bunx >/dev/null && \
+ mkdir -p /usr/local/bun-node-fallback-bin && \
+ ln -sf /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node \
+ '🤖 Prompt for AI Agents
In dockerhub/distroless/Dockerfile around lines 72 to 83, the RUN uses the
external which and non-idempotent ln calls; replace uses of which with the POSIX
builtin command -v to check for bun and change ln to use -sf (force/symbolic) so
creating symlinks is idempotent and won’t fail on cache rebuilds or when which
is absent; ensure the shell invocation uses /bin/sh -c as before and adjust the
single-quoted command to perform command -v bun >/dev/null 2>&1 and create
symlinks with ln -sf.
## Problem Distroless Docker image build has been failing in CI/CD since v1.1.45 (4+ months ago). This prevented the distroless image from being published to Docker Hub. Error: `exec /bin/sh: no such file or directory` Root cause: Distroless base image does not contain shell, but Dockerfile used heredoc syntax which requires `/bin/sh` to execute. ## Solution 1. Create all symlinks in build stage (where shell is available) - ln -s /usr/local/bin/bun /usr/local/bin/bunx - ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node 2. In distroless stage, only COPY symlinks (no RUN commands needed) - COPY --from=build /usr/local/bin/bunx - COPY --from=build /usr/local/bun-node-fallback-bin/ 3. Upgrade base image from debian11 to debian12 - Fixes security vulnerabilities (1 HIGH CVE → 0) - Uses gcr.io/distroless/base-debian12 ## Testing - Local build: ✅ Success (both amd64) - Verified symlinks: ✅ All working (bun, bunx, node) - Image size: ~20 MB (minimal as expected) ## Related Issues Closes oven-sh#20414 Closes oven-sh#16666 Related to oven-sh#22601, oven-sh#19788
## Problem Distroless Docker image build has been failing in CI/CD since v1.1.45 (4+ months ago). This prevented the distroless image from being published to Docker Hub. Error: `exec /bin/sh: no such file or directory` Root cause: Distroless base image does not contain shell, but Dockerfile used heredoc syntax which requires `/bin/sh` to execute. ## Solution 1. Create all symlinks in build stage (where shell is available) - ln -s /usr/local/bin/bun /usr/local/bin/bunx - ln -s /usr/local/bin/bun /usr/local/bun-node-fallback-bin/node 2. In distroless stage, only COPY symlinks (no RUN commands needed) - COPY --from=build /usr/local/bin/bunx - COPY --from=build /usr/local/bun-node-fallback-bin/ 3. Upgrade base image from debian11 to debian12 - Fixes security vulnerabilities (1 HIGH CVE → 0) - Uses gcr.io/distroless/base-debian12 ## Testing - Local build: ✅ Success (linux/amd64) - Azure-dev build: ✅ Success (linux/amd64) - Verified symlinks: ✅ All working (bun, bunx, node) - Image size: 228MB (comparable to debian variant at 221MB) ## Related Issues Closes oven-sh#20414 Closes oven-sh#16666 Related to oven-sh#22601, oven-sh#19788
Summary
Fixes the critical build failure preventing distroless Docker images from publishing, plus security updates to base images.
Problems Fixed
nodebunshould benodeChanges (2 files, 11 lines)
1. Fixed Distroless Build ✅
The distroless Dockerfile used heredoc syntax which requires a shell, but distroless has no shell:
2. Security Updates ✅
3. Fixed Typo ✅
nodebuntonodein symlink pathSecurity Impact (Trivy Scans)
Before:
After:
Why 5 CVEs remain in Debian images
The remaining CVEs cannot be fixed without breaking functionality:
CVE-2023-45853 (zlib) - CRITICAL
CVE-2025-6020 (PAM) - HIGH
useradd,su, etc.3 other HIGH in PAM - Related to the authentication system
These are core OS packages. Users requiring zero CVEs should use:
bun:alpine- 0 CVEs, smallest sizebun:distroless- 0 HIGH/CRITICAL, no shell for maximum securityImpact
✅ Distroless will finally publish again (fixes #20414)
✅ Significantly reduces vulnerabilities (fixes #22594, #3272)
✅ Maintains compatibility and stability