Verify the build provenance. This proves the image was produced by the

July 8, 2026 Β· View on GitHub

minimal β€” hardened container images

Small, hardened container images, free and MIT-licensed.
Built from source with Chainguard's apko and Wolfi packages, rebuilt every six hours.
Every image is cosign-signed, ships an SPDX SBOM attestation, and carries SLSA Level 3 build provenance. You can verify all of it without an account.

🌐  Browse the full catalog at minimalcontainers.comΒ  β†’

Build status Image Catalog License: MIT SLSA Level 3 Images: 57 Architectures

Image catalog Β· Verify an image Β· All 57 images Β· HN discussion


Pull and verify in 30 seconds

The point of these images is that you don't have to trust me. Pull one, then check the provenance yourself:

# Pull. It's public β€” no login, no rate limit.
docker pull ghcr.io/rtvkiz/minimal-python:latest

# Verify the build provenance. This proves the image was produced by the
# workflow file in this repo, at a specific commit, on a GitHub-hosted runner.
gh attestation verify oci://ghcr.io/rtvkiz/minimal-python:latest --owner rtvkiz

# Pull the SPDX SBOM so you can see exactly what's inside.
cosign verify-attestation --type spdxjson \
  --certificate-identity-regexp='https://github.com/rtvkiz/minimal/' \
  --certificate-oidc-issuer='https://token.actions.githubusercontent.com' \
  ghcr.io/rtvkiz/minimal-python:latest \
  | jq -r '.payload | @base64d | fromjson | .predicate' > python-sbom.spdx.json

More verification recipes (cosign signature, SBOM, SLSA provenance) live in .github/SECURITY.md.

How minimal is different

minimalChainguardDocker HardenedMinimus / RapidFort
LicenseMITProprietaryApache-2.0Proprietary
Cost$0~$30k/image/yrFree + paid supportSales call
Auth to pullNoYesYesYes
Rate limitsNoneYesYesYes
Build recipes publicYes, every melange.yamlNoYes, DockerfilesNo
Cosign sig + SBOM + SLSA L3YesYesYesYes
Vendor SLA, FedRAMP/STIGNoYes (paid)Yes (paid)Yes (paid)

Reach for minimal if you want hardened images without paying or signing up, if you want to read every build recipe end-to-end, or if you want a working template to fork into your own internal catalog.

It's probably not the right fit if you need a vendor contract, FedRAMP or STIG accreditation paperwork, or a thousand-plus images on day one β€” those are real things this project doesn't try to solve.

What every image ships with

  • A cosign keyless signature, verifiable against the public Rekor transparency log.
  • An SPDX SBOM attached as an in-toto attestation β€” every package, version, and license.
  • SLSA v1.0 build provenance β€” cryptographic proof of which workflow, which commit, and which runner produced the image.
  • A daily Grype scan, with results in the public catalog and the GitHub Security tab.
  • Native linux/amd64 and linux/arm64 builds.
  • A non-root user by default (UID 65532), unless the upstream insists otherwise.
  • No shell where possible β€” most images don't ship /bin/sh.
  • A six-hour rebuild cadence, so Wolfi CVE patches land in hours, not days.

Available Images β€” 57 total

CategoryCountHighlights
Languages & runtimes9python, node-slim, bun, go, java, ruby, php, dotnet, deno
Databases5mysql, mariadb, postgres-slim, sqlite, opensearch
Caches, queues, messaging7redis-slim, valkey, memcached, kafka, rabbitmq, nats, mosquitto
Web servers & proxies6nginx, httpd, caddy, haproxy, traefik, envoy
Observability14prometheus, alertmanager, victoria-metrics, thanos, mimir, jaeger, loki, tempo, otelcol, fluent-bit, telegraf, node-exporter, blackbox-exporter, pushgateway
Infrastructure7coredns, etcd, openbao, keycloak, qdrant, registry, consul
Kubernetes, CI & IaC4helm, kubectl, opentofu, trivy
Apps5jenkins, gitea, minio, rails, mailpit

Browse every image β€” with live CVE scans, all tags, SBOMs, and build provenance β€” at minimalcontainers.com, or expand the full pull-command list below.

Full image catalog with pull commands
ImagePull CommandShellUse Case
Languages
Pythondocker pull ghcr.io/rtvkiz/minimal-python:latestNoPython apps, microservices
Node.js-slimdocker pull ghcr.io/rtvkiz/minimal-node-slim:latestNoNode.js apps, JavaScript
Bundocker pull ghcr.io/rtvkiz/minimal-bun:latestNoFast JavaScript/TypeScript runtime
Godocker pull ghcr.io/rtvkiz/minimal-go:latestNoGo development, CGO builds
.NET Runtimedocker pull ghcr.io/rtvkiz/minimal-dotnet:latestNo.NET 10 runtime for apps
Javadocker pull ghcr.io/rtvkiz/minimal-java:latestNoOpenJDK 26 JRE for Java apps
Rubydocker pull ghcr.io/rtvkiz/minimal-ruby:latestNoRuby 4.0 runtime (built from source)
PHPdocker pull ghcr.io/rtvkiz/minimal-php:latestNoPHP 8.5 CLI (built from source)
Railsdocker pull ghcr.io/rtvkiz/minimal-rails:latestNoRuby 4.0 + Rails 8.1 (built from source)
Denodocker pull ghcr.io/rtvkiz/minimal-deno:latestNoSecure TypeScript/JavaScript runtime
Databases
MySQLdocker pull ghcr.io/rtvkiz/minimal-mysql:latestYesMySQL LTS 8.4.x, built from source
MariaDBdocker pull ghcr.io/rtvkiz/minimal-mariadb:latestYesMariaDB LTS 11.4.x, built from source
PostgreSQL-slimdocker pull ghcr.io/rtvkiz/minimal-postgres-slim:latestNoRelational database
SQLitedocker pull ghcr.io/rtvkiz/minimal-sqlite:latestNoEmbedded SQL database CLI
OpenSearchdocker pull ghcr.io/rtvkiz/minimal-opensearch:latestNo*OpenSearch 3.x β€” search & analytics
Caches, Queues, Messaging
Redis-slimdocker pull ghcr.io/rtvkiz/minimal-redis-slim:latestNoIn-memory data store
Memcacheddocker pull ghcr.io/rtvkiz/minimal-memcached:latestNoIn-memory caching (built from source)
Valkeydocker pull ghcr.io/rtvkiz/minimal-valkey:latestNoBSD-licensed Redis fork (LF)
Kafkadocker pull ghcr.io/rtvkiz/minimal-kafka:latestYesApache Kafka 4.x, KRaft mode
RabbitMQdocker pull ghcr.io/rtvkiz/minimal-rabbitmq:latestYesRabbitMQ 4.x AMQP broker
NATSdocker pull ghcr.io/rtvkiz/minimal-nats:latestNoNATS Server with JetStream
Mosquittodocker pull ghcr.io/rtvkiz/minimal-mosquitto:latestNoEclipse Mosquitto MQTT broker (EPL-2.0/EDL-1.0)
Web Servers & Proxies
Nginxdocker pull ghcr.io/rtvkiz/minimal-nginx:latestNoReverse proxy, static files
HTTPDdocker pull ghcr.io/rtvkiz/minimal-httpd:latestMaybe*Apache web server
Caddydocker pull ghcr.io/rtvkiz/minimal-caddy:latestNoAutomatic HTTPS web server
HAProxydocker pull ghcr.io/rtvkiz/minimal-haproxy:latestNoTCP/HTTP load balancer
Traefikdocker pull ghcr.io/rtvkiz/minimal-traefik:latestNoCloud-native reverse proxy
Envoydocker pull ghcr.io/rtvkiz/minimal-envoy:latestNoService proxy & load balancer
Observability
Prometheusdocker pull ghcr.io/rtvkiz/minimal-prometheus:latestNoMetrics collection & alerting
VictoriaMetricsdocker pull ghcr.io/rtvkiz/minimal-victoria-metrics:latestNoHigh-perf metrics storage
Jaegerdocker pull ghcr.io/rtvkiz/minimal-jaeger:latestNoDistributed tracing (v2)
Lokidocker pull ghcr.io/rtvkiz/minimal-loki:latestNoLog aggregation (Grafana Labs)
Tempodocker pull ghcr.io/rtvkiz/minimal-tempo:latestNoDistributed tracing backend (Grafana Labs, AGPL)
OTel Collectordocker pull ghcr.io/rtvkiz/minimal-otelcol:latestNoOpenTelemetry Collector core
Fluent Bitdocker pull ghcr.io/rtvkiz/minimal-fluent-bit:latestNoLightweight log processor
Node Exporterdocker pull ghcr.io/rtvkiz/minimal-node-exporter:latestNoPrometheus host hardware & OS metrics
Blackbox Exporterdocker pull ghcr.io/rtvkiz/minimal-blackbox-exporter:latestNoPrometheus endpoint probing (HTTP/DNS/TCP/ICMP)
Pushgatewaydocker pull ghcr.io/rtvkiz/minimal-pushgateway:latestNoPrometheus metrics push for batch jobs
Infrastructure
CoreDNSdocker pull ghcr.io/rtvkiz/minimal-coredns:latestNoKubernetes default DNS
etcddocker pull ghcr.io/rtvkiz/minimal-etcd:latestNoDistributed key-value store
OpenBaodocker pull ghcr.io/rtvkiz/minimal-openbao:latestNoSecret management (Vault fork)
Keycloakdocker pull ghcr.io/rtvkiz/minimal-keycloak:latestYesIdentity & access management
Qdrantdocker pull ghcr.io/rtvkiz/minimal-qdrant:latestNoVector DB for AI/ML (Rust)
Registrydocker pull ghcr.io/rtvkiz/minimal-registry:latestNoOCI distribution registry (Docker Registry v2), built from source
Consuldocker pull ghcr.io/rtvkiz/minimal-consul:latestNoHashiCorp Consul service discovery + KV (BUSL-1.1)
Kubernetes & CI
Helmdocker pull ghcr.io/rtvkiz/minimal-helm:latestNoHelm 3 CLI for Kubernetes chart deployment
kubectldocker pull ghcr.io/rtvkiz/minimal-kubectl:latestNokubectl CLI for Kubernetes cluster operations
Apps
Jenkinsdocker pull ghcr.io/rtvkiz/minimal-jenkins:latestYesCI/CD automation
Giteadocker pull ghcr.io/rtvkiz/minimal-gitea:latestYesSelf-hosted Git service
MinIOdocker pull ghcr.io/rtvkiz/minimal-minio:latestNoS3-compatible object storage
Mailpitdocker pull ghcr.io/rtvkiz/minimal-mailpit:latestNoSMTP & email testing for developers, built from source
AI / ML
CUDA PythondisabledNoPython + CUDA 12.9 + cuDNN 9.10 (build paused, code retained)

*HTTPD, Jenkins, Kafka, MySQL, OpenSearch, Gitea, Keycloak include shell (sh/busybox/bash) via transitive Wolfi dependencies or because the upstream entrypoint requires it. CI treats shell presence as informational.

Quick Start

# Python app
docker run --rm -v $(pwd):/app ghcr.io/rtvkiz/minimal-python:latest /app/main.py

# Nginx reverse proxy
docker run -d -p 8080:80 ghcr.io/rtvkiz/minimal-nginx:latest

# PostgreSQL
docker run -d -p 5432:5432 -v pgdata:/var/lib/postgresql/data \
  ghcr.io/rtvkiz/minimal-postgres-slim:latest

# Redis
docker run -d -p 6379:6379 ghcr.io/rtvkiz/minimal-redis-slim:latest

# Kafka (KRaft mode β€” auto-initializes storage on first boot)
docker run -d -p 9092:9092 -v kafkadata:/var/kafka/data \
  ghcr.io/rtvkiz/minimal-kafka:latest
More docker run examples (Node, Go, MySQL, MariaDB, Java, .NET, PHP, Rails, RabbitMQ, Gitea, …)
# Node.js
docker run --rm -v $(pwd):/app -w /app ghcr.io/rtvkiz/minimal-node-slim:latest index.js

# Bun
docker run --rm ghcr.io/rtvkiz/minimal-bun:latest --version

# Go
docker run --rm -v $(pwd):/app -w /app ghcr.io/rtvkiz/minimal-go:latest build -o /tmp/app .

# HTTPD
docker run -d -p 8080:80 ghcr.io/rtvkiz/minimal-httpd:latest

# Jenkins
docker run -d -p 8080:8080 -v jenkins_home:/var/jenkins_home ghcr.io/rtvkiz/minimal-jenkins:latest

# MySQL
docker run -d -p 3306:3306 -v mysqldata:/var/lib/mysql ghcr.io/rtvkiz/minimal-mysql:latest

# Memcached
docker run -d -p 11211:11211 ghcr.io/rtvkiz/minimal-memcached:latest

# SQLite
docker run --rm -v $(pwd):/data ghcr.io/rtvkiz/minimal-sqlite:latest /data/mydb.sqlite "SELECT sqlite_version();"

# .NET
docker run --rm -v $(pwd):/app ghcr.io/rtvkiz/minimal-dotnet:latest /app/myapp.dll

# Java
docker run --rm -v $(pwd):/app ghcr.io/rtvkiz/minimal-java:latest -jar /app/myapp.jar

# PHP
docker run --rm -v $(pwd):/app ghcr.io/rtvkiz/minimal-php:latest /app/index.php

# Rails
docker run --rm -v $(pwd):/app ghcr.io/rtvkiz/minimal-rails:latest -e "require 'rails'; puts Rails.version"

# RabbitMQ
docker run -d -p 5672:5672 -v rabbitmqdata:/var/lib/rabbitmq ghcr.io/rtvkiz/minimal-rabbitmq:latest

# Gitea
docker run -d -p 3000:3000 -v giteadata:/data/gitea ghcr.io/rtvkiz/minimal-gitea:latest

Using in production

Pin to immutable version tags. Every image is published with two tags:

TagFormatExampleMutable
VersionVERSION-rEPOCHghcr.io/rtvkiz/minimal-redis-slim:8.4.1-r0No
Latestlatestghcr.io/rtvkiz/minimal-redis-slim:latestYes

Dev variants (:latest-dev)

Most images publish a -dev companion built from the same source as prod β€” same runtime version, same curated package set β€” plus a shell, package manager, compiler toolchain, and image-appropriate debug tooling. Intended for CI build stages and in-pod debugging, not for production deployment.

Typical multi-stage usage:

FROM ghcr.io/rtvkiz/minimal-ruby:latest-dev AS build
WORKDIR /work
COPY Gemfile Gemfile.lock ./
RUN bundle install

FROM ghcr.io/rtvkiz/minimal-ruby:latest
COPY --from=build /work /work

To get an interactive shell, override the entrypoint (dev images keep the prod entrypoint for drop-in compatibility):

docker run -it --entrypoint /bin/sh   ghcr.io/rtvkiz/minimal-<image>:latest-dev
docker run -it --entrypoint /bin/bash ghcr.io/rtvkiz/minimal-<image>:latest-dev

Dev variants share the prod image's signing, SBOM, and SLSA provenance pipeline. They are not tracked on the public CVE dashboard β€” they intentionally ship a larger attack surface. See .github/SECURITY.md for the policy and docs/dev-variants/CONVENTIONS.md for the package composition rules.

Shipping today: 57 of 57 dev variants β€” every image in the catalog now ships a :latest-dev companion built from the same source as prod.

Per-image dev variant status

Legend: βœ… shipping :latest-dev Β· 🚧 in progress Β· πŸ“ planned

Categories follow the three templates in docs/dev-variants/templates/ (runtime / daemon / server). The "Reference" column shows where we mirror Chainguard's public <image>-public/devConfigs package set; in-house means Chainguard ships an Enterprise-only image and we designed the dev composition ourselves.

ImageCategoryReferenceStatus
rubyruntimeChainguard ruby-publicβœ…
pythonruntimeChainguard python-publicβœ…
node-slimruntimeChainguard node-publicβœ…
goruntimeChainguard go-publicβœ…
javaruntimeChainguard jdk-publicβœ…
dotnetruntimeChainguard dotnet-runtime-10-publicβœ…
phpruntimein-house (composer deferred β€” see PR)βœ…
railsruntimein-house (derive from ruby)βœ…
bunruntimein-houseβœ…
denoruntimein-houseβœ…
postgres-slimdaemonChainguard postgres-publicβœ…
mariadbdaemonChainguard mariadb-publicβœ…
mysqldaemonin-houseβœ…
redis-slimdaemonChainguard redis-publicβœ…
valkeydaemonChainguard valkey-publicβœ…
memcacheddaemonin-houseβœ…
sqlitedaemonin-houseβœ…
opensearchdaemonin-houseβœ…
kafkadaemonin-houseβœ…
rabbitmqdaemonin-houseβœ…
natsdaemonin-houseβœ…
etcddaemonin-houseβœ…
qdrantdaemonin-houseβœ…
nginxserverChainguard nginx-publicβœ…
haproxyserverChainguard haproxy-publicβœ…
minioserverChainguard minio-client-public (server in-house)βœ…
httpdserverin-houseβœ…
caddyserverin-houseβœ…
traefikserverin-houseβœ…
envoyserverin-houseβœ…
prometheusserverin-houseβœ…
victoria-metricsserverin-houseβœ…
jaegerserverin-houseβœ…
otelcolserverin-houseβœ…
lokiserverin-houseβœ…
fluent-bitserverin-houseβœ…
node-exporterserverin-houseβœ…
blackbox-exporterserverin-houseβœ…
pushgatewayserverin-houseβœ…
corednsserverin-houseβœ…
giteaserverin-houseβœ…
jenkinsserverin-houseβœ…
keycloakserverin-houseβœ…
openbaoserverin-houseβœ…
registryserverChainguard registry-publicβœ…
mailpitserverin-house (Chainguard ships no public mailpit)βœ…
consulserverin-house (Chainguard ships no public consul; BUSL-1.1)βœ…
temposerverin-house (Chainguard ships no public tempo; AGPL-3.0)βœ…
mosquittodaemonin-house (Chainguard ships no public mosquitto; EPL-2.0/EDL-1.0)βœ…
# Production Dockerfile β€” pin by version tag, ideally by digest
FROM ghcr.io/rtvkiz/minimal-go:1.26.0-r0 AS build
WORKDIR /src
COPY . .
RUN go build -o /out/app

FROM ghcr.io/rtvkiz/minimal-python:3.14.0-r0
COPY --from=build /out/app /usr/bin/app
ENTRYPOINT ["/usr/bin/app"]

Enforce signature + provenance in Kubernetes with sigstore-policy-controller or Kyverno:

# Kyverno ClusterPolicy β€” only allow signed minimal-* images
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-minimal-images
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-signature
      match:
        any:
          - resources:
              kinds: [Pod]
      verifyImages:
        - imageReferences:
            - "ghcr.io/rtvkiz/minimal-*"
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/rtvkiz/minimal/*"
                    issuer: "https://token.actions.githubusercontent.com"

The -r0 suffix is the revision number β€” resets to r0 on each upstream version bump, increments (r1, r2, …) for rebuilds of the same upstream version (e.g., dependency patches). Old version tags are preserved across rebuilds.

Build pipeline

Pipeline diagram
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                            BUILD PIPELINE                                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  Signing Keys:                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  PRs: keygen job (ephemeral) β”‚ Main: repository secrets (persistent)β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                              β”‚                                              β”‚
β”‚                              β–Ό                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  melange-build              β”‚    β”‚      build-apko                     β”‚ β”‚
β”‚  β”‚  Native ARM64 runners       β”‚    β”‚      Wolfi pre-built packages       β”‚ β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚ β”‚
β”‚  β”‚  β”‚ x86_64 β”‚  β”‚  aarch64   β”‚ β”‚    β”‚  β”‚  Wolfi  │────►│ apko publish  β”‚  β”‚ β”‚
β”‚  β”‚  β”‚ ubuntu β”‚  β”‚ ubuntu-arm β”‚ β”‚    β”‚  β”‚ packagesβ”‚     β”‚ (multi-arch)  β”‚  β”‚ β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚ β”‚
β”‚  β”‚       β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜        β”‚    β”‚                          β”‚          β”‚ β”‚
β”‚  β”‚             β–Ό               β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚  β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚                               β”‚            β”‚
β”‚  β”‚     β”‚   artifacts  β”‚        β”‚                               β”‚            β”‚
β”‚  β”‚     β”‚ (x86+arm64)  β”‚        β”‚                               β”‚            β”‚
β”‚  β”‚     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚                               β”‚            β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                               β”‚            β”‚
β”‚               β–Ό                                                β”‚            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                               β”‚            β”‚
β”‚  β”‚  build-melange              β”‚                               β”‚            β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚                               β”‚            β”‚
β”‚  β”‚  β”‚  merge  β”‚β–Ίβ”‚   apko     │─┼────────────────────────────────            β”‚
β”‚  β”‚  β”‚ packagesβ”‚ β”‚  publish   β”‚ β”‚                               β”‚            β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚                               β”‚            β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                               β”‚            β”‚
β”‚                                                                β–Ό            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                     Verification & Attestation                       β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚
β”‚  β”‚  β”‚  Grype   │─►│   Test   │─►│  cosign  │─►│  SBOM + SLSA L3     β”‚   β”‚   β”‚
β”‚  β”‚  β”‚ CVE scan β”‚  β”‚  image   β”‚  β”‚   sign   β”‚  β”‚    attestations     β”‚   β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β”‚  Note: PRs build and test but do not publish. Only main branch publishes.   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Update schedule

TriggerWhenPurpose
ScheduledEvery 6 hoursPick up latest CVE patches from Wolfi
PushOn merge to mainDeploy configuration changes
ManualWorkflow dispatchEmergency rebuilds

Vulnerability scan results appear in the live catalog, the job summary, and the GitHub Security tab.

Automated upstream tracking

Source-built images are tracked by dedicated workflows that check upstream daily and open PRs:

Per-image update workflows (21 total)
WorkflowWatchesWhat It Does
update-jenkins.ymlJenkins LTS releasesUpdates version in melange config, Makefile, build.yml
update-redis.ymlRedis GitHub releasesUpdates version and SHA256
update-mysql.ymlMySQL LTS (8.4.x) GitHub tagsUpdates version and SHA256
update-memcached.ymlMemcached GitHub releasesUpdates version and SHA256
update-kafka.ymlApache Kafka 4.x GitHub tagsUpdates version and SHA512
update-php.ymlphp.net releases APIUpdates version and SHA256; opens issue for new minor/major series
update-rails.ymlRubyGems API + Ruby GitHub tagsUpdates Rails gem and Ruby source versions independently
update-rabbitmq.ymlRabbitMQ GitHub releasesUpdates version and SHA256
update-minio.ymlMinIO GitHub releasesUpdates release tag, date-based version, and SHA256
update-victoria-metrics.ymlVictoriaMetrics GitHub releasesUpdates version and SHA256
update-jaeger.ymlJaeger v2.x GitHub releasesUpdates version and SHA256; warns on major version change
update-otelcol.ymlOTel Collector stable releasesUpdates version and SHA256; skips prereleases
update-qdrant.ymlQdrant v1.x GitHub releasesUpdates version and SHA256
update-etcd.ymletcd v3.x GitHub releasesUpdates version and SHA256
update-opensearch.ymlOpenSearch 3.x GitHub releasesUpdates version in Makefile and README
update-gitea.ymlGitea v1.x GitHub tagsUpdates version and SHA256
update-coredns.ymlCoreDNS v1.x GitHub tagsUpdates version and SHA256
update-openbao.ymlOpenBao v2.x GitHub tagsUpdates version and SHA256
update-loki.ymlLoki v3.x GitHub tagsUpdates version and SHA256
update-fluent-bit.ymlFluent Bit v5.x GitHub tagsUpdates version and SHA256
update-keycloak.ymlKeycloak 26.x GitHub tagsUpdates version and SHA256
update-wolfi-packages.ymlWolfi APKINDEXDetects new Python, Node, Go, .NET, Java, PostgreSQL, Deno versions

Patch updates are auto-PR'd and validated by CI. Minor/major bumps create a GitHub Issue with a manual upgrade checklist.

Image specifications (versions, users, entrypoints)
ImageVersionUserEntrypointWorkdir
Python3.14.xnonroot (65532)/usr/bin/python3/app
Node.js-slim25.xnonroot (65532)/usr/bin/dumb-init -- /usr/bin/node/app
Bunlatestnonroot (65532)/usr/bin/bun/app
Go1.26.xnonroot (65532)/usr/bin/go/app
Nginxmainlinenginx (65532)/usr/sbin/nginx -g "daemon off;"/
HTTPD2.4.xwww-data (65532)/usr/sbin/httpd -DFOREGROUND/var/www/localhost/htdocs
Jenkins2.555.x LTSjenkins (1000)tini -- java -jar jenkins.war/var/jenkins_home
Redis8.6.xredis (65532)/usr/bin/redis-server/
MySQL8.4.xmysql (65532)/usr/bin/docker-entrypoint.sh/
MariaDB11.4.xmariadb (65532)/usr/bin/mariadbd/var/lib/mysql
Memcached1.6.xmemcached (65532)/usr/bin/memcached/
PostgreSQL18.xpostgres (70)/usr/bin/postgres/
SQLite3.51.xnonroot (65532)/usr/bin/sqlite3/data
.NET Runtime10.xnonroot (65532)/usr/bin/dotnet/app
Java26.xnonroot (65532)/usr/bin/java/app
Ruby4.0.xnonroot (65532)/usr/bin/ruby/work
PHP8.5.xnonroot (65532)/usr/bin/php/app
RailsRuby 4.0.x + Rails 8.1.xnonroot (65532)/usr/bin/ruby/app
Kafka4.2.xkafka (65532)/usr/bin/kafka-entrypoint.sh/
RabbitMQ4.3.xrabbitmq (65532)/opt/rabbitmq/sbin/rabbitmq-server/
NATSlatestnonroot (65532)/usr/bin/nats-server/
Valkeylatestnonroot (65532)/usr/bin/valkey-server/
MinIORELEASE.2025-10-15minio (65532)/usr/bin/minio server --console-address :9001 /data/data
OpenSearch3.7.0opensearch (65532)/usr/share/opensearch/opensearch-docker-entrypoint.sh/usr/share/opensearch/data
etcd3.6.xnonroot (65532)/usr/bin/etcd/var/lib/etcd
VictoriaMetrics1.142.xnonroot (65532)/usr/bin/victoria-metrics/
Jaeger2.18.xnonroot (65532)/usr/bin/jaeger/
OTel Collector0.151.xnonroot (65532)/usr/bin/otelcol/
Qdrant1.17.xnonroot (65532)/usr/bin/qdrant/qdrant
Deno2.xnonroot (65532)/usr/bin/deno/app
Gitea1.26.xgitea (65532)/usr/bin/gitea web --config /etc/gitea/app.ini/var/lib/gitea
CoreDNS1.14.xnonroot (65532)/usr/bin/coredns/
OpenBao2.5.xopenbao (65532)/usr/bin/bao server/openbao/data
Keycloak26.6.xkeycloak (65532)/opt/keycloak/bin/kc.sh start-dev/opt/keycloak/data
Loki3.6.xloki (65532)/usr/bin/loki/loki
Fluent Bit5.0.xnonroot (65532)/usr/bin/fluent-bit/

Build locally

# Prerequisites
go install chainguard.dev/apko@latest
go install chainguard.dev/melange@latest
brew install anchore/grype/grype

# Build & test a specific image
make python
make test-python

# Build everything
make build

# Scan for CVEs
make scan

See the Makefile for the full target list.

Project structure

Repository layout
minimal/
β”œβ”€β”€ <image>/
β”‚   β”œβ”€β”€ apko/<name>.yaml          # final image config
β”‚   β”œβ”€β”€ melange.yaml              # source build (optional)
β”‚   └── test.sh                   # smoke test
β”œβ”€β”€ .github/
β”‚   β”œβ”€β”€ SECURITY.md               # disclosure policy + verification recipes
β”‚   └── workflows/
β”‚       β”œβ”€β”€ build.yml             # main CI pipeline (6h rebuilds)
β”‚       β”œβ”€β”€ patch-go-deps.yml     # daily Go transitive CVE patching
β”‚       β”œβ”€β”€ update-<image>.yml    # per-image upstream version tracking
β”‚       └── update-wolfi-packages.yml
β”œβ”€β”€ Makefile
β”œβ”€β”€ README.md
β”œβ”€β”€ CONTRIBUTING.md
└── LICENSE

Status and roadmap

Recently landed:

  • Cosign keyless signatures on every image.
  • SPDX SBOMs attached as in-toto attestations, verifiable with cosign verify-attestation.
  • SLSA v1.0 build provenance, verifiable with gh attestation verify.
  • A public CVE dashboard with per-image breakdowns.
  • A six-hour rebuild cadence, plus daily patching of Go transitive CVEs.

Next up:

  • VEX statements for CVEs that aren't actually exploitable in our images, so the dashboard stops showing noise.
  • Consolidating the per-image update workflows into one matrix-driven job.
  • Niche AI/ML images (CUDA-aware Python variants) β€” there's a HN thread where this came up and it seems worth exploring.

What this project is not:

  • Solo-maintained, so there's no vendor SLA and no on-call rotation.
  • Not FedRAMP / FIPS / STIG accredited. The verifiable provenance and SBOMs help with audits, but they don't replace the paperwork.

Contributing

PRs are welcome. CONTRIBUTING.md has the build setup, the image conventions, and the local validation checklist I run before pushing.

If you find a security issue, please use GitHub's private vulnerability reporting rather than opening a public issue. The disclosure policy and response timeline are in .github/SECURITY.md.

License

MIT β€” see LICENSE.

Container images include packages from Wolfi and other sources, each with their own licenses (Apache-2.0, MIT, GPL, LGPL, BSD, etc.). Full license information is in each image's SBOM:

cosign download sbom ghcr.io/rtvkiz/minimal-python:latest | jq '.packages[].licenseConcluded'