| name | containerize |
| description | Build minimal, non-root OCI images — `ko` for Go or a distroless multi-stage Dockerfile — then scan, sign, and SBOM them. Use when containerizing or packaging an app for deployment. |
| metadata | {"author":"Médéric HURIER (Fmind)","source":"github.com/fmind/dotfiles/tree/main/skills/containerize","created":"2026-07-04T00:00:00.000Z","updated":"2026-07-06T00:00:00.000Z"} |
Containerize an Application
Build a small, non-root, reproducible OCI image and verify it before it ships. Pairs with k8s-local for the local dev loop and security-scan for image scanning.
Choose an Approach
-
Go → ko (default, no Dockerfile): builds a distroless, multi-arch, reproducible image straight from a package path. Add it per project (go get -tool github.com/google/ko, then go tool ko).
export KO_DOCKER_REPO=registry.localhost:5050/<slug>
go tool ko build ./cmd/<slug> --bare --platform=linux/amd64,linux/arm64
-
Python (or any other language) → multi-stage Dockerfile on a distroless or minimal base (optimized with uv). Copy and customize:
docker build -t <registry>/<slug>:<tag> .
docker buildx build --platform linux/amd64,linux/arm64 -t <registry>/<slug>:<tag> --push .
Verify Before Ship
- Scan the built image (fail on HIGH/CRITICAL — see security-scan):
trivy image <registry>/<slug>:<tag>
- Sign keyless with Sigstore (OIDC, no long-lived keys):
cosign sign <registry>/<slug>@<digest>
- SBOM for provenance:
trivy image --format cyclonedx -o sbom.json <registry>/<slug>:<tag>
Mise Task Integration
Integrate image building and checking into the project's canonical task vocabulary (mise.toml):
[tasks."build:image"]
description = "Build OCI image"
run = "go tool ko build ./cmd/<slug> --bare"
[tasks."check:image"]
description = "Scan container image for vulnerabilities"
run = "trivy image <registry>/<slug>:<tag>"
Local Dev Loop
Push to the shared k3d registry and deploy per k8s-local:
docker push registry.localhost:5050/<slug>:<tag>
Gotchas
- Non-root + minimal: distroless has no shell/package manager — debug with
kubectl debug ephemeral containers, not by adding a shell.
- Use
.dockerignore: Always exclude development artifacts, local virtual environments, and secrets to speed up builds and prevent credential leakage (see .dockerignore).
- Static binaries:
CGO_ENABLED=0 for distroless/static; use distroless/base only when cgo is required.
- Digests over tags in manifests: reference images by digest in Kubernetes so deploys are immutable.
Documentation