KRM functions are distributed as container images. This guide covers building and running containerized functions.
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.
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"]docker build -t ghcr.io/kptdev/krm-functions-catalog/my-function:v0.1 .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.
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.yamldocker run --rm -v $(pwd):/data ghcr.io/kptdev/krm-functions-catalog/my-function:v0.1 /data/deployment.yamldocker 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 --docIn 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: productionNote: 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.
- 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 function images to a registry is handled by the krm-functions-catalog CI pipeline. See the catalog's CONTRIBUTING.md for the release workflow.