Containerizing KRM Functions
May 29, 2026 · View on GitHub
KRM functions are distributed as container images. This guide covers building and running containerized functions.
Dockerfile
The krm-functions-catalog
provides a shared Dockerfile at build/docker/go/Dockerfile that all the catalog
functions use. It accepts BUILDER_IMAGE and BASE_IMAGE as build args.
For standalone functions or local development, use a multi-stage build with a
minimal base image. The function binary should be statically linked (no CGO), so
it can run on scratch or distroless:
FROM golang:1.26-alpine AS builder
ENV CGO_ENABLED=0
WORKDIR /go/src/
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /usr/local/bin/function ./
FROM scratch
COPY --from=builder /usr/local/bin/function /usr/local/bin/function
ENTRYPOINT ["function"]
Key points:
CGO_ENABLED=0produces a static binary that runs onscratch.- The
scratchbase image has zero overhead — no shell, no OS packages. - If you need TLS certificates (e.g., for network calls), use
gcr.io/distroless/staticinstead ofscratch. - Copy only the binary to the final image to minimize size.
Alternative with distroless
FROM golang:1.26-alpine AS builder
ENV CGO_ENABLED=0
WORKDIR /go/src/
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /usr/local/bin/function ./
FROM gcr.io/distroless/static:nonroot
COPY --from=builder /usr/local/bin/function /usr/local/bin/function
ENTRYPOINT ["function"]
Building
docker build -t ghcr.io/kptdev/krm-functions-catalog/my-function:v0.1 .
Image Naming Convention
Follow this pattern for function images:
ghcr.io/kptdev/krm-functions-catalog/{function-name}:{version}
Examples:
ghcr.io/kptdev/krm-functions-catalog/set-labels:v0.1ghcr.io/kptdev/krm-functions-catalog/enforce-namespace:v1.0ghcr.io/kptdev/krm-functions-catalog/generate-configmap:v0.3
Use semantic versioning for tags. Avoid latest in production pipelines.
Running
KRM functions read from STDIN and write to STDOUT:
docker run --rm -i ghcr.io/kptdev/krm-functions-catalog/my-function:v0.1 < input.yaml > output.yaml
With file mode
docker run --rm -v $(pwd):/data ghcr.io/kptdev/krm-functions-catalog/my-function:v0.1 /data/deployment.yaml
Help and doc flags
docker run --rm ghcr.io/kptdev/krm-functions-catalog/my-function:v0.1 --help
docker run --rm ghcr.io/kptdev/krm-functions-catalog/my-function:v0.1 --doc
Using with kpt
In a Kptfile pipeline, kpt fn render will pull the image from the registry
and run it against your package resources:
apiVersion: kpt.dev/v1
kind: Kptfile
metadata:
name: my-package
pipeline:
mutators:
- image: ghcr.io/kptdev/krm-functions-catalog/set-labels:v0.1
configMap:
app: my-app
validators:
- image: ghcr.io/kptdev/krm-functions-catalog/enforce-namespace:v1.0
configMap:
namespace: production
Note: the image must be published and accessible from the machine running
kpt fn render. For local development, build the image locally first. It
will be used from the local Docker cache without pulling.
Tips
- Keep images small — a typical Go KRM function image is 5–15 MB with
scratch. - Pin dependency versions in
go.modfor reproducible builds. - Use
.dockerignoreto exclude test data, docs, and other non-build files. - Test the container locally before publishing:
echo '{"apiVersion":"config.kubernetes.io/v1","kind":"ResourceList","items":[]}' | \ docker run --rm -i ghcr.io/kptdev/krm-functions-catalog/my-function:v0.1
Publishing
Publishing function images to a registry is handled by the krm-functions-catalog CI pipeline. See the catalog's CONTRIBUTING.md for the release workflow.