Size Comparison Table
Real, representative numbers from actual container images (as of 2025):
Image | Ubuntu | Alpine | Distroless | Chainguard | CleanStart -dev | CleanStart -prod |
|---|---|---|---|---|---|---|
Base (no app) | 77 MB | 7 MB | 20 MB | 19 MB | ~150 MB | ~15 MB |
Python 3.11 | 920 MB | 60 MB | 52 MB | 45 MB | ~350 MB | ~85 MB |
Node.js 20 | 1.1 GB | 180 MB | 120 MB | 95 MB | ~400 MB | ~110 MB |
Java 21 (JRE) | 470 MB | 190 MB | 220 MB | 160 MB | ~450 MB | ~180 MB |
Go (compiled) | 850 MB | 320 MB | 20 MB | 19 MB | ~350 MB | ~20 MB |
PostgreSQL 16 | 430 MB | 240 MB | N/A | 280 MB | ~500 MB | ~200 MB |
Nginx | 190 MB | 45 MB | N/A | 25 MB | ~250 MB | ~30 MB |
Key Observations
Alpine is the smallest option available but uses musl libc, which causes binary incompatibility. Distroless is minimal but limited to specific languages (Python, Node, Java). Chainguard images are lean, stripped, without package managers, and optimized for their platform. CleanStart -prod approaches distroless or Chainguard size despite GLIBC inclusion. CleanStart -dev is heavier because it includes debugging symbols and development tools.
What's Inside CleanStart Images?
CleanStart -prod (Production)
Production images include only what is necessary for security and operation. They contain GLIBC (~3 MB) needed for language runtimes and C dependencies. OpenSSL (~5 MB) provides TLS and cryptography. FIPS crypto modules (~8-12 MB) provide validated cryptography for compliance. Verification artifacts (~2-5 MB) include SBOM, signatures, and attestations. cleanimg-init (~500 KB) provides secure initialization process. Base OS layer (~5-10 MB) provides filesystem, systemd-minimal, and basic utilities. Language runtime (varies) supports Python, Node, Java, Go, etc.
CleanStart -dev (Development)
Development images add tools for troubleshooting and debugging. They include everything in -prod PLUS GDB, strace, ltrace (~30 MB) for debuggers. curl, wget, netcat (~10 MB) provide network tools. vim, less, grep (~15 MB) provide text tools. build-essential (~60 MB) provides compilers and headers (optional). Debug symbols (~50-100 MB) include unstripped binaries.
What's NOT in CleanStart Images
CleanStart strips components to reduce attack surface. Shells (bash, sh) are not present; all execution goes through cleanimg-init. Package managers (apt, apk, npm, pip) are absent since images are immutable. Compilers and build tools (gcc, make) are missing; no compilation at runtime. Unnecessary libraries are excluded; only used dependencies are present. Documentation files are not included; /usr/share/doc and man pages are absent. Locales are stripped except en_US.UTF-8. Cache files such as apt cache and pip cache are removed.
This eliminates 40-60% of typical image bloat.
Size vs. Security Tradeoff Analysis
Why Bigger Isn't Always Worse
CleanStart -prod is slightly larger than distroless/Chainguard because of specific trade-offs. GLIBC over musl means better compatibility and certified security patches, although musl works great for Go and Alpine but causes problems with Python, Java, and C extensions. Verified crypto means FIPS-validated cryptography modules take space but are required for federal and defense contracts. You cannot buy that smaller. Comprehensive metadata includes SBOM files, signatures, and attestations that prove provenance and compliance. That is not bloat; it is insurance. Flexible base means CleanStart works with any runtime (Python, Node, Java, Rust), whereas distroless specializes per-language, so you need multiple tools.
Security Impact of Size
Smaller images have one main security advantage: less code equals fewer vulnerabilities. But there are important caveats. musl libc has fewer CVEs because fewer people use it. GLIBC's larger codebase has been audited more thoroughly. Fewer dependencies can hide critical flaws (missing crypto validation). CleanStart's approach is to ship verified, complete, audited components rather than stripping down to minimal.
Practical Tradeoff
Metric | Distroless | Alpine | Chainguard | CleanStart -prod |
|---|---|---|---|---|
Size | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
Compatibility | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
Crypto Validation | ⭐⭐⭐ | ⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
FIPS Certified | ❌ | ❌ | ❌ | ✅ |
Provenance Proof | ⭐⭐ | ⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
Multi-language | ❌ | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
How to Check Your Own Image Sizes
Using docker images
docker images | grep cleanstart # OutputREPOSITORY TAG IMAGE ID SIZEgcr.io/cleanstart/python 3.11-prod abc123def456 85MBgcr.io/cleanstart/python 3.11-dev xyz789def456 320MBgcr.io/cleanstart/node 20-prod pqr456stu789 110MBUsing crane (CNCF tool)
crane inspects images without pulling them:
# Install cranebrew install crane # or visit github.com/google/go-containerregistry # Check image size (config + layers)crane manifest gcr.io/cleanstart/app:1.0.0 | jq '.config.size'# Output: 12345 # Sum all layerscrane manifest gcr.io/cleanstart/app:1.0.0 | jq '.layers[] | .size' | awk '{sum+=$1} END {print sum}'# Output: 85000000 # Compare two imagesecho "Ubuntu:"crane manifest ubuntu:latest | jq '.config.size + (.layers | map(.size) | add)'# 77000000 echo "CleanStart:"crane manifest gcr.io/cleanstart/base:latest | jq '.config.size + (.layers | map(.size) | add)'# 15000000Using docker Inspection
# Pull the imagedocker pull gcr.io/cleanstart/app:1.0.0 # Show sizedocker images gcr.io/cleanstart/app:1.0.0 # Inspect layersdocker inspect gcr.io/cleanstart/app:1.0.0 | jq '.[] | .RootFS.Layers | length' # Show history (layer-by-layer)docker history gcr.io/cleanstart/app:1.0.0Using dive (Visual Layer Analysis)
dive shows what is in each layer:
# Install divebrew install dive # Analyze imagedive gcr.io/cleanstart/app:1.0.0 # Interactive view shows:# - Layer sizes# - File additions/removals per layer# - Wasted space (files deleted in later layers)Using syft (SBOM Generation)
Generate a software bill of materials to see what is included:
# Install syftbrew install syft # Generate SBOMsyft gcr.io/cleanstart/app:1.0.0 -o json > sbom.json # Show top packages by sizesyft gcr.io/cleanstart/app:1.0.0 -o table | sort -k4 -h | tail -20Practical Size Reduction Strategies
1. Use CleanStart -prod for Production
# ❌ DON'T: Use -dev in productionFROM gcr.io/cleanstart/python:3.11-dev AS prodCOPY app.py .CMD ["python", "app.py"]# Result: 320 MB (includes debuggers, build tools) # ✅ DO: Use -prod with multi-stage buildFROM gcr.io/cleanstart/python:3.11-dev AS buildCOPY requirements.txt .RUN pip install -r requirements.txt --target /deps FROM gcr.io/cleanstart/python:3.11-prodCOPY --from=build /deps /usr/local/lib/python3.11/site-packagesCOPY app.py .CMD ["python", "app.py"]# Result: 85 MB (no build tools, only runtime)2. Multi-Stage Builds (Eliminate Build Artifacts)
FROM gcr.io/cleanstart/node:20-dev AS builderWORKDIR /appCOPY package.json package-lock.json ./RUN npm ci --only=production FROM gcr.io/cleanstart/node:20-prodWORKDIR /appCOPY --from=builder /app/node_modules ./node_modulesCOPY app.js config.json ./CMD ["node", "app.js"]This strategy saves approximately 50 MB by removing npm cache, dev dependencies, and build artifacts.
3. Exclude Unnecessary Files
FROM gcr.io/cleanstart/python:3.11-prod # Create .dockerignore# __pycache__# *.pyc# .pytest_cache# .git# docs/# tests/# *.md COPY --chown=1000:1000 . /app/WORKDIR /appCMD ["python", "-m", "uvicorn", "main:app"]4. Slim Down Dependencies
# Audit dependenciespip show requests# Size: 200 KB # Remove unused packagespip uninstall -y jinja2 markupsafe # if not needed# ~500 KB saved # Use lighter alternativespip uninstall numpy pandaspip install polars # 10x smaller for many use cases5. Compression (Advanced)
Some registries (Harbor, ECR) compress layers:
# Check compressiongcloud container images describe gcr.io/cleanstart/app:1.0.0 \ --show-package-vulnerability # View compressed vs uncompressedcrane blob-digest gcr.io/cleanstart/app:1.0.0 | xargs \ gcloud container images list-tags gcr.io/cleanstart/app --filter="digest={}"Real-World Examples
Python API (Flask + SQLAlchemy)
With Ubuntu 22.04: 920 MB total consists of base OS (77 MB), Python 3.11 (450 MB), Flask and SQLAlchemy (50 MB), and other dependencies (343 MB).
With Alpine 3.18: 60 MB total consists of musl libc (7 MB), Python 3.11 (30 MB), Flask and SQLAlchemy (20 MB), and other dependencies (3 MB). However, some C extensions fail to compile with musl, causing compatibility issues.
With CleanStart -prod: 85 MB total consists of base OS (10 MB), GLIBC (3 MB), Python 3.11 (35 MB), Flask and SQLAlchemy (20 MB), FIPS crypto libraries (8 MB), and verification artifacts (9 MB).
Comparison: CleanStart is 91% smaller than Ubuntu while working with all packages, unlike Alpine. The additional 25 MB over Alpine includes FIPS-compliant crypto and verification artifacts.
Go Microservice
With Ubuntu 22.04: 850 MB total consists of base OS (77 MB), runtime libraries (350 MB), compiled binary (15 MB), and other components (408 MB).
With Distroless (Go): 20 MB total consists of base (5 MB), GLIBC (10 MB), and binary (5 MB). This is a perfect fit for static binaries.
With CleanStart -prod: 20 MB total consists of base OS (5 MB), GLIBC (3 MB), binary (5 MB), and verification artifacts (7 MB).
Comparison: CleanStart matches distroless in total image size for Go services. The key advantage is that CleanStart adds signed attestations and verification artifacts, providing cryptographic proof of secure build and supply chain integrity.
Compliance & Certification
Size does not matter if you cannot pass audits. CleanStart includes SBOM (software bill of materials) required by CISA/EO14028. It includes signatures (Cosign) to verify image authenticity. It includes FIPS module certification required for federal contracts. It includes provenance attestation proving build chain integrity. It includes vulnerability scanning pre-scanned at build time.
Distroless and Chainguard do not include all of these by default.
Summary
Use Case | Best Option | Why |
|---|---|---|
Maximum size reduction | Alpine or Distroless | Smallest footprint, static binaries |
Production (non-regulated) | Chainguard | Lean + compatible + verified |
Federal/Defense | CleanStart -prod | FIPS + SBOM + signatures required |
Development | CleanStart -dev | Debugging tools + full compatibility |
Compliance audits | CleanStart -prod | Attestations + signatures included |
Remember: 15-20 MB of verified, signed, FIPS-certified code beats 5 MB of opaque binary any day.
