Build pipeline
How canette builds container images using Railpack and BuildKit inside the cluster.
canette builds container images inside the cluster using Railpack and BuildKit.
This page is a work in progress.
Stages
Each build runs as a Kubernetes Job with two stages, each backed by a dedicated Go binary:
1. git-clone (init container) — canette-builder-git-init image
The git-init binary validates all inputs, sets up git credentials in Go (no shell), and shallow-clones the repository into a shared emptyDir volume at the exact ref. Supports public repos, PAT (HTTPS), and SSH deploy keys.
2. image-build (main container) — canette-builder-image-build image
The canette-build binary reads canette.yaml (size-checked and validated), determines the build strategy, and invokes buildctl directly with discrete arguments — no shell interpolation. Three strategies in order of priority:
- Explicit Dockerfile — if
build.dockerfileis set incanette.yaml - Auto-detect Dockerfile — if a
Dockerfileexists at the app root - Railpack — runs
railpack preparethen builds via the BuildKit gateway frontend
Supported frameworks
Railpack auto-detects: Node.js, Python, Go, Ruby, PHP, Java, Rust, Elixir, Deno, .NET, and more. A Dockerfile in the repo root is used directly if present.
When Railpack does not produce a working image
Railpack covers the common cases well, but auto-detection can miss framework-specific quirks, monorepo layouts, or unusual build toolchains. If your app builds successfully but does not start correctly — or if Railpack picks the wrong runtime — the recommended solution is to add a Dockerfile to the repository.
A Dockerfile at the app root takes precedence over Railpack automatically. This is a standard, well-understood format that gives you full control over the build without any canette-specific configuration. railpack.json is explicitly not supported — canette manages the build plan directly and will refuse to build if one is present.
BuildKit daemon
A long-lived rootless buildkitd deployment runs in canette-system. Build jobs connect to it via BUILDKIT_HOST — no daemon is started per-job.