---
tags:
- k8s
- l1
- flashcard-deck
- container-base-images
---
<!-- wiki:breadcrumb:start -->
[Portal](../../../../library/portal/index.md) | **Level:** [L1: Foundations](../../../../library/portal/levels.md) | **Topics:** [Container Base Images](../../../../library/portal/topics.md) | **Domain:** Kubernetes
<!-- wiki:breadcrumb:end -->

id	category	difficulty	tags	question	answer	source_path
container-base-images/001-lineup	container-base-images	easy	containers, docker, base-image	What are the main container base image options and their sizes?	Alpine: ~7MB (musl, ash shell, apk)\nDebian-slim: ~75MB (glibc, bash, apt)\nUbuntu: ~75MB (glibc, bash, apt, snap)\nDistroless: ~20MB (glibc, no shell, no pkg mgr)\nscratch: 0MB (literally nothing)\nUBI: ~95-200MB (glibc, RHEL compat)\nChainguard/Wolfi: ~15MB (glibc, minimal, hardened)\n\nRemember: rebuild base images regularly to pick up security patches. Set up automated builds triggered by upstream image updates. Stale images accumulate vulnerabilities.	training/library/topics/container-images/primer.md
container-base-images/002-alpine-musl	container-base-images	hard	containers, alpine, musl	What compatibility issues does Alpine's musl libc cause?	Binaries compiled on glibc distros won't run on Alpine.\nPython C extensions: build fails without musl-dev headers.\nDNS: no nsswitch.conf, different resolver behavior.\nGo with CGO: linking errors (fix: CGO_ENABLED=0).\nNode native modules: need python3, make, g++.\nLocale: missing locales, encoding errors.\nThreads: different stack defaults.\n\nRemember: Alpine = ~5 MB base image using musl libc and busybox. Smallest common base, but musl can cause compatibility issues with glibc-compiled binaries.\n\nGotcha: musl libc DNS resolution differs from glibc — it queries all nameservers in parallel, which can cause issues in some Kubernetes setups.	training/library/topics/container-images/primer.md
container-base-images/003-when-alpine	container-base-images	medium	containers, alpine, decision	When should you use Alpine as a container base image?	Good for: Go/Rust static binaries, simple apps without C extensions, size-critical deployments, CI tools.\nAvoid when: Python with numpy/pandas (C extensions), apps needing glibc, complex DNS requirements in Kubernetes (musl ndots issue), need for easy debugging.\n\nRemember: Alpine = ~5 MB base image using musl libc and busybox. Smallest common base, but musl can cause compatibility issues with glibc-compiled binaries.\n\nGotcha: musl libc DNS resolution differs from glibc — it queries all nameservers in parallel, which can cause issues in some Kubernetes setups.	training/library/topics/container-images/primer.md
container-base-images/004-when-debian-slim	container-base-images	medium	containers, debian, decision	When should you use Debian-slim as a container base image?	Best all-around choice when: you need glibc (Python C extensions, Java, .NET), you need apt for installing packages, you want a shell for debugging, Alpine's musl is causing issues.\n~75MB vs ~125MB full Debian. Good size-to-compatibility ratio.\n\nRemember: slim variants (python:3.11-slim) remove docs, man pages, and dev tools. Good balance between size and compatibility. Based on Debian, uses glibc.	training/library/topics/container-images/primer.md
container-base-images/005-distroless	container-base-images	medium	containers, distroless, security	What is a distroless container image and what are its tradeoffs?	Distroless has no shell, no package manager, no OS tools — only your binary + runtime libraries.\nPros: minimal attack surface, no shell exploits, fewer CVEs, forces good build practices.\nCons: cannot exec into container for debugging, need debug variant for troubleshooting, harder to test locally.\n\nRemember: distroless = no shell, no package manager, no OS tools. Only your app binary + runtime dependencies. Smallest attack surface, but harder to debug.	training/library/topics/container-images/primer.md
container-base-images/006-scratch	container-base-images	hard	containers, scratch, go	What is the scratch base image and what does it require?	scratch is literally empty (0 bytes). Only for statically compiled binaries (Go with CGO_ENABLED=0, Rust).\nYou must copy in everything: CA certs for HTTPS, timezone data, /etc/passwd for user lookups, /tmp if needed.\nNo libc, no shell, no DNS resolver — your binary must be fully self-contained.\n\nRemember: FROM scratch = empty image, no OS at all. Only works for statically compiled binaries (Go, Rust). Absolute smallest possible image.	training/library/topics/container-images/primer.md
container-base-images/007-multi-stage	container-base-images	medium	containers, docker, multi-stage	What is the multi-stage build pattern and why is it important?	Stage 1 (build): large image with compilers, headers, build tools. Compile your app.\nStage 2 (runtime): small image with only runtime deps. COPY --from=build the binary/artifacts.\nResult: build tools never appear in production image.\nReduces size by 50-90% and removes build-time attack surface.\n\nRemember: multi-stage builds use multiple FROM statements. Build stage has compilers/tools, final stage has only the runtime. Keeps images small and secure.\n\nExample: Stage 1: FROM golang:1.21 AS builder (compile). Stage 2: FROM alpine:3.19 (copy binary only). Build tools never ship to production.	training/library/topics/container-images/primer.md
container-base-images/008-layer-caching	container-base-images	medium	containers, docker, optimization	How do you optimize Docker layer caching?	Copy dependency files FIRST, install deps, THEN copy source code:\nCOPY requirements.txt .\nRUN pip install -r requirements.txt\nCOPY . .\nThis way, code changes don't bust the dependency cache.\nAlso: combine RUN commands, clean up in the same layer (rm -rf /var/lib/apt/lists/*).\n\nRemember: rebuild base images regularly to pick up security patches. Set up automated builds triggered by upstream image updates. Stale images accumulate vulnerabilities.	training/library/topics/container-images/street_ops.md
container-base-images/009-nonroot	container-base-images	easy	containers, docker, security	Why should containers run as non-root and how do you set this up?	Root in container = root on host if container escapes.\nDebian: RUN useradd -r -s /sbin/nologin -u 1000 appuser && USER appuser\nAlpine: RUN adduser -D -u 1000 appuser && USER appuser\nDistroless: use :nonroot tag variant.\nK8s enforces with runAsNonRoot: true in securityContext.\n\nRemember: always run containers as non-root. Add USER 1000:1000 in Dockerfile. Prevents container escape from gaining host root access.	training/library/topics/container-images/footguns.md
container-base-images/010-latest-tag	container-base-images	easy	containers, docker, best-practices	Why should you never use :latest tag in production Dockerfiles?	:latest today ≠ :latest tomorrow. A rebuild might pull a different version with breaking changes.\nPin to specific version: python:3.12.4-slim-bookworm\nEven floating tags like python:3.12-slim can change (3.12.4 → 3.12.5).\nRebuild intentionally, not accidentally.\n\nGotcha: never use :latest in production — it's mutable and unpredictable. Pin to specific versions (python:3.11.7-slim) for reproducible builds.	training/library/topics/container-images/footguns.md
container-base-images/011-alpine-python	container-base-images	hard	containers, alpine, python	Why is Alpine a poor choice for Python apps with C extensions?	No pre-built wheels exist for musl libc — only glibc.\nPackages like pandas, numpy, cryptography must compile from source.\nBuild takes 10-30 minutes vs seconds on Debian-slim.\nRequires gcc, musl-dev, linux-headers, etc.\nUse python:3.12-slim instead for Python apps with C extensions.\n\nRemember: Alpine = ~5 MB base image using musl libc and busybox. Smallest common base, but musl can cause compatibility issues with glibc-compiled binaries.\n\nGotcha: musl libc DNS resolution differs from glibc — it queries all nameservers in parallel, which can cause issues in some Kubernetes setups.	training/library/topics/container-images/footguns.md
container-base-images/012-alpine-k8s-dns	container-base-images	hard	containers, alpine, kubernetes, dns	Why does Alpine cause DNS issues in Kubernetes?	Alpine's musl resolver doesn't handle ndots:5 (K8s default) well. It queries all search domains for every DNS lookup, causing 10x more DNS queries.\nCan overwhelm CoreDNS under load.\nFix: set dnsConfig.options ndots=1 in Pod spec.\nOr use Debian-slim and avoid the issue entirely.\n\nRemember: Alpine = ~5 MB base image using musl libc and busybox. Smallest common base, but musl can cause compatibility issues with glibc-compiled binaries.\n\nGotcha: musl libc DNS resolution differs from glibc — it queries all nameservers in parallel, which can cause issues in some Kubernetes setups.	training/library/topics/container-images/footguns.md
container-base-images/013-ubi-variants	container-base-images	medium	containers, ubi, rhel	What are the Red Hat UBI variants and when to use each?	ubi9/ubi: full (~215MB, dnf, systemd) — general purpose\nubi9/ubi-minimal: smaller (~95MB, microdnf) — most production apps\nubi9/ubi-micro: tiny (~28MB, no pkg mgr) — like distroless\nubi9/ubi-init: with systemd — multi-process containers\nUse for: OpenShift, enterprise compliance, FIPS/STIG requirements.\n\nRemember: rebuild base images regularly to pick up security patches. Set up automated builds triggered by upstream image updates. Stale images accumulate vulnerabilities.	training/library/topics/container-images/primer.md
container-base-images/014-chainguard	container-base-images	medium	containers, chainguard, security	What are Chainguard images and why use them?	Hardened, minimal, signed container images with SBOMs.\nZero known CVEs (aggressively patched).\nWolfi-based: glibc (no musl issues) but Alpine-style minimal.\nProvenance and attestation built-in.\nUse when: supply chain security matters, compliance requires SBOM, you want glibc + minimal size.\n\nRemember: rebuild base images regularly to pick up security patches. Set up automated builds triggered by upstream image updates. Stale images accumulate vulnerabilities.	training/library/topics/container-images/primer.md
container-base-images/015-rebuild-schedule	container-base-images	medium	containers, docker, security	Why and how often should you rebuild container images?	Base image CVEs are discovered daily. Your 3-month-old image has unpatched vulnerabilities even if your code hasn't changed.\nRebuild weekly with --no-cache to pull latest base.\nAutomate with CI (weekly cron job).\nScan with Trivy after each build.\nUse Dependabot/Renovate to track base image updates.\n\nRemember: rebuild base images regularly to pick up security patches. Set up automated builds triggered by upstream image updates. Stale images accumulate vulnerabilities.	training/library/topics/container-images/street_ops.md
container-base-images/016-decision-tree	container-base-images	easy	containers, docker, decision	What is the quick decision tree for choosing a container base image?	Need a shell? No → Need glibc? No → scratch (static binary). Yes → distroless/Chainguard.\nNeed a shell? Yes → Need glibc? No → Alpine. Yes → RHEL required? Yes → UBI minimal. No → Debian-slim.\n\nRemember: rebuild base images regularly to pick up security patches. Set up automated builds triggered by upstream image updates. Stale images accumulate vulnerabilities.	training/library/topics/container-images/primer.md
container-base-images/017-dockerignore	container-base-images	easy	containers, docker	Why is .dockerignore important and what should be in it?	Without .dockerignore, COPY . . sends everything to the daemon: .git/ (hundreds of MB), node_modules/, .env (SECRETS!), tests/, .venv/.\nResult: bloated image, slow builds, leaked secrets.\nMinimum: .git, .github, .venv, __pycache__, node_modules, .env, *.md, tests/\n\nRemember: rebuild base images regularly to pick up security patches. Set up automated builds triggered by upstream image updates. Stale images accumulate vulnerabilities.	training/library/topics/container-images/footguns.md
container-base-images/018-debug-no-shell	container-base-images	hard	containers, distroless, debugging	How do you debug a distroless or scratch container with no shell?	1. kubectl debug -it pod/myapp --image=busybox (ephemeral debug container)\n2. kubectl debug -it pod/myapp --image=nicolaka/netshoot (network debugging)\n3. kubectl cp pod/myapp:/app/logs/error.log ./error.log\n4. kubectl logs pod/myapp\n5. Build a debug stage in Dockerfile (--target debug)\n6. Use distroless :debug variant temporarily\n\nRemember: distroless = no shell, no package manager, no OS tools. Only your app binary + runtime dependencies. Smallest attack surface, but harder to debug.	training/library/topics/container-images/street_ops.md
container-base-images/019-timezone-missing	container-base-images	medium	containers, alpine, timezone	Why do timezone operations fail in Alpine/distroless containers?	"Alpine and distroless don't include timezone data.\ntime.LoadLocation(""America/New_York"") fails.\nFix: Alpine: apk add --no-cache tzdata. Debian-slim: apt install tzdata.\nSet ENV TZ=America/New_York.\nFor distroless: copy /usr/share/zoneinfo from build stage.\n\nRemember: Alpine = ~5 MB base image using musl libc and busybox. Smallest common base, but musl can cause compatibility issues with glibc-compiled binaries.\n\nGotcha: musl libc DNS resolution differs from glibc — it queries all nameservers in parallel, which can cause issues in some Kubernetes setups."	training/library/topics/container-images/footguns.md
container-base-images/020-size-impact	container-base-images	easy	containers, docker, optimization	What is the practical impact of container image size?	Every 100MB removed: faster pulls (cold starts on new nodes), less disk usage across fleet, fewer CVEs to scan/patch, smaller attack surface.\nExample Python app: ubuntu ~450MB, python:slim ~150MB, python:alpine ~60MB, distroless ~50MB.\nSize matters most for: cold start latency, CI build times, security scan surface.\n\nRemember: rebuild base images regularly to pick up security patches. Set up automated builds triggered by upstream image updates. Stale images accumulate vulnerabilities.	training/library/topics/container-images/primer.md

<!-- wiki:related:start -->
---

## Wiki Navigation

### Related Content

- [Container Images](../../../../library/topics/container-images/index.md) (Topic Pack, L1) — Container Base Images

<!-- wiki:related:end -->
