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.
The point of these images is that you don't have to trust me. Pull one, then check the provenance yourself:
root@kitploit:~
# 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
minimal
Chainguard
Docker Hardened
Minimus / RapidFort
License
MIT
Proprietary
Apache-2.0
Proprietary
Cost
$0
~$30k/image/yr
Free + paid support
Sales call
Auth to pull
No
Yes
Yes
Yes
Rate limits
None
Yes
Yes
Yes
Build recipes public
Yes, every melange.yaml
No
Yes, Dockerfiles
No
Cosign sig + SBOM + SLSA L3
Yes
Yes
Yes
Yes
Vendor SLA, FedRAMP/STIG
No
Yes (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.
coredns, etcd, openbao, keycloak, qdrant, registry, consul
Kubernetes, CI & IaC
4
helm, kubectl, opentofu, trivy
Apps
5
jenkins, 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.
*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
root@kitploit:~
# 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, …)
root@kitploit:~
# 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:
Tag
Format
Example
Mutable
Version
VERSION-rEPOCH
ghcr.io/rtvkiz/minimal-redis-slim:8.4.1-r0
No
Latest
latest
ghcr.io/rtvkiz/minimal-redis-slim:latest
Yes
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:
root@kitploit:~
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):
root@kitploit:~
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.
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.
Image
Category
Reference
Status
ruby
runtime
Chainguard ruby-public
✅
python
runtime
Chainguard python-public
✅
node-slim
runtime
Chainguard node-public
✅
go
runtime
Chainguard go-public
✅
java
runtime
Chainguard jdk-public
✅
dotnet
runtime
Chainguard dotnet-runtime-10-public
✅
php
runtime
in-house (composer deferred — see PR)
✅
rails
runtime
in-house (derive from ruby)
✅
bun
runtime
in-house
✅
deno
runtime
in-house
✅
postgres-slim
daemon
Chainguard postgres-public
✅
mariadb
daemon
Chainguard mariadb-public
✅
mysql
daemon
in-house
✅
redis-slim
daemon
Chainguard redis-public
✅
valkey
daemon
Chainguard valkey-public
✅
memcached
daemon
in-house
✅
sqlite
daemon
in-house
✅
opensearch
daemon
in-house
✅
kafka
daemon
in-house
✅
rabbitmq
daemon
in-house
✅
nats
daemon
in-house
✅
etcd
daemon
in-house
✅
root@kitploit:~
# 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"]
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.
# 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
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: