A Cloud Native Buildpacks builder that produces minimal, secure application images using Google Distroless as the runtime base, while supporting all major Paketo Buildpacks languages.
| Component | Base image | Purpose |
|---|---|---|
| Build stack | ubuntu:24.04 |
Full toolchain for compiling apps |
| Run stack | gcr.io/distroless/cc:nonroot |
Minimal, shell-free runtime |
| Builder | CNB lifecycle + Paketo Buildpacks | Orchestrates builds |
The run image has no shell, no package manager, no debug tools — drastically reducing the attack surface of every application container built with this builder.
| Language | Buildpack |
|---|---|
| Java / Spring Boot | paketo-buildpacks/java |
| Java Native Image (GraalVM) | paketo-buildpacks/java-native-image |
| Go | paketo-buildpacks/go |
| Node.js | paketo-buildpacks/nodejs |
| Python | paketo-buildpacks/python |
| Ruby | paketo-buildpacks/ruby |
| PHP | paketo-buildpacks/php |
| .NET Core | paketo-buildpacks/dotnet-core |
| Procfile | paketo-buildpacks/procfile |
Prerequisites: Docker ≥ 20.10, pack CLI ≥ 0.33
pack build my-app \
--builder ghcr.io/patbaumgartner/distroless-buildpack-builder:latest \
--path ./my-apppack config default-builder ghcr.io/patbaumgartner/distroless-buildpack-builder:latest
pack build my-appConfigure once in pom.xml:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>ghcr.io/patbaumgartner/distroless-buildpack-builder:latest</builder>
<pullPolicy>IF_NOT_PRESENT</pullPolicy>
</image>
</configuration>
</plugin>Then build:
mvn spring-boot:build-image
# or override the builder without changing pom.xml:
mvn spring-boot:build-image \
-Dspring-boot.build-image.builder=ghcr.io/patbaumgartner/distroless-buildpack-builder:latestImages are published to GHCR on pushes to main, on version tags, and during scheduled refresh runs in CI. Pull requests execute build validation but do not publish images. Images include SLSA provenance attestations.
OCI-attached SBOM/provenance manifests are disabled during stack-image docker buildx publish steps due to a known CNB manifest-selection compatibility issue in pack; however, SBOM artifacts are still generated separately with Syft in CI.
| Image | Registry |
|---|---|
ghcr.io/patbaumgartner/distroless-buildpack-builder |
GHCR |
ghcr.io/patbaumgartner/distroless-buildpack-builder/build |
GHCR |
ghcr.io/patbaumgartner/distroless-buildpack-builder/run |
GHCR |
Prerequisites: Docker with buildx, pack CLI, make
make build-stack # Build + push multi-arch stack images (amd64, arm64)
make build-builder # Assemble the CNB builder image
make test # Run smoke + integration tests
make test-smoke # Run smoke tests only (fast)
make test-integration # Run integration tests onlyTo include Java samples in integration tests:
INCLUDE_JAVA=1 make test-integrationNote:
make build-stackusesdocker buildx build --pushto produce multi-arch images (linux/amd64+linux/arm64). It pushes directly to the registry — local loading of multi-platform images is not supported by Docker. SetPLATFORMS=linux/amd64to restrict to a single architecture.
All samples in samples/ expose / and /health on port 8080.
| Sample | Language |
|---|---|
samples/nodejs |
Node.js (Express 5) |
samples/go |
Go |
samples/python |
Python (Flask) |
samples/ruby |
Ruby (Sinatra) |
samples/dotnet-core |
.NET (ASP.NET Core) |
samples/php |
PHP |
samples/web-servers |
Static (Nginx) |
samples/java |
Java 25 / Spring Boot |
samples/java-native-image |
Java 25 / GraalVM Native Image |
Build any sample:
pack build my-app \
--path ./samples/nodejs \
--builder ghcr.io/patbaumgartner/distroless-buildpack-builder:latest├── builder.toml # CNB builder configuration
├── Makefile # Local build automation
├── CODE_OF_CONDUCT.md # Community behavior expectations
├── SUPPORT.md # Support and triage guidance
├── benchmarks/
│ └── budgets.json # Build/runtime SLO budgets
├── openrewrite/
│ └── rewrite.yml # Curated OpenRewrite recipe packs
├── stack/
│ ├── build/Dockerfile # Build stack image (Ubuntu 24.04)
│ └── run/Dockerfile # Run stack image (Google Distroless)
├── samples/ # Ready-to-build sample apps per language
├── tests/
│ ├── integration/ # End-to-end builder tests
│ └── smoke/ # Fast label + config validation
└── .github/
├── ISSUE_TEMPLATE/ # Bug report and feature request templates
├── dependabot.yml # Automated dependency updates
└── workflows/
├── build-and-push.yml # Build + push to GHCR
├── test.yml # Smoke + integration tests
├── security-scan.yml # Trivy CVE scan + Hadolint lint
├── scorecard.yml # OSSF Scorecard (weekly)
├── benchmark.yml # Build-time + runtime/startup/memory benchmarks
├── quality-gates.yml # Linting, static analysis, and Checkstyle
├── openrewrite.yml # OpenRewrite dry-run + scheduled modernization PRs
├── dependency-policy-review.yml # Quarterly dependency policy review issue
└── release.yml # GitHub releases on version tags
| Workflow | Trigger | Description |
|---|---|---|
| Build and Push | push to main, pull_request, version tags, daily |
Build/validate stack images + builder; publish on non-PR events |
| Integration Tests | push, pull_request | Smoke tests → integration tests (pack + mvn) |
| Security Scan | push, pull_request, weekly | Trivy CVE scan (filesystem + stack images) + Hadolint Dockerfile lint |
| OSSF Scorecard | push to main, weekly |
Supply-chain security posture analysis |
| Benchmark | after Build and Push, weekly | Build times + startup + memory + run image size SLOs |
| Quality Gates | push, pull_request | Linting (ShellCheck, actionlint, markdownlint), sample static analysis, and Checkstyle |
| OpenRewrite | push, pull_request, monthly | Java dry-run recipe checks + scheduled modernization PR |
| Dependency Policy Review | quarterly | Opens governance checklist issue for dependency strategy review |
| Release | version tags (v*) |
GitHub Release with pull instructions |
To detect when workloads become more expensive to run, CI enforces explicit budgets in benchmarks/budgets.json:
- Build-time SLO per sample (seconds)
- Runtime startup SLO per sample (seconds)
- Runtime memory SLO per sample (MiB)
- Maximum distroless run image size (MB)
The benchmark workflow persists machine-readable metric artifacts for each run, which enables trend analysis over time and early detection of resource-cost regressions.
The run image (gcr.io/distroless/cc:nonroot) provides:
- No shell — attackers cannot execute shell commands
- No package manager — nothing installable at runtime
- Non-root user (uid 1002) by default
- C++ runtime (
libstdc++,libgcc) included for Node.js and other C++ runtimes
Automated scanning on every push:
- Trivy — CVE scanning of repository filesystem plus local build/run stack images
- Hadolint — Dockerfile best-practice linting (blocking)
- Quality Gates — blocking static-analysis checks across scripts, workflows, docs, and sample applications
- OSSF Scorecard — Supply-chain security posture (weekly)
SARIF reports are published to the Security tab.
See SECURITY.md for the vulnerability disclosure policy.
See CONTRIBUTING.md.
Apache 2.0 — see LICENSE.