For a high-level overview of the project, see README.md.
- Images and tool versions are defined in
deps.yaml. - Dockerfile templates live in
internal/dockerfile/tmpl/and are embedded into the generator binary at compile time. make generaterenders the templates intodockerfiles/Dockerfile.*and updatesimages-lock.yaml.make verifyensures no uncommitted changes exist (run in CI).make pushbuilds and pushes multi-arch images to GHCR.
deps.yaml has two sections for tools:
universal:— tools installed in every image (e.g.cosign,gh). Add here if the tool should be universally available.tools:— tools that are opt-in per image (e.g.govulncheck). Add here, then reference the tool name under the relevant image'stools:list.
Both require the same fields:
- name: mytool
source: org/repo # GitHub org/repo, or a full URL for static sources
version: v1.2.3
checksums:
linux/amd64: "<sha256>"
linux/arm64: "<sha256>"
release:
download_template: "mytool-{version}-{os}-{arch}.tar.gz"
extract: "mytool" # path of the binary inside the archive; omit for plain binariesAfter editing, run make generate and commit the updated Dockerfiles.
Tool families allow multiple versions of a tool to coexist in the same image, with a runtime selector to choose which one is active. This is useful for tools like Helm where you might need to support both v3 and v4.
To add a tool family:
- Add multiple tools with the same
familyfield indeps.yaml:
tools:
- name: helmv3
family: helm
source: "https://get.helm.sh"
version: v3.20.2
checksums:
linux/amd64: "<sha256>"
linux/arm64: "<sha256>"
release:
download_template: "{source}/helm-{version}-{os}-{arch}.tar.gz"
extract: "{os}-{arch}/helm"
- name: helmv4
family: helm
family_default: true # This version is active by default
source: "https://get.helm.sh"
version: v4.1.4
checksums:
linux/amd64: "<sha256>"
linux/arm64: "<sha256>"
release:
download_template: "{source}/helm-{version}-{os}-{arch}.tar.gz"
extract: "{os}-{arch}/helm"-
Run
make generate. This will:- Create a
select-{family}.shscript (e.g.select-helm.sh) - Add the family to the
ci-selectcommand - Set up the default symlink in
/var/ci-tools/active/
- Create a
-
Users can then select a version using:
- Environment variable:
SELECT_HELM_VERSION=helmv3 - Runtime command:
ci-select helm helmv3orselect-helm helmv3
- Environment variable:
Only one tool in a family should have family_default: true.
- Add a new entry under
images:indeps.yamlwith the desired Go base image (e.g.registry.suse.com/bci/golang:1.X.Y@sha256:...) and a name likego1.X. - Run
make generateand commit the new Dockerfile.
When make generate detects that a dockerfiles/Dockerfile.<name> no longer has a corresponding image in deps.yaml, it moves the file to archive/Dockerfile.<name>.<YYYYMMDD-HHMMSS> (UTC). Commit the archived file alongside the removal in deps.yaml.
# Generate Dockerfiles from templates and deps.yaml
make generate
# Build all images locally
make build
# Build and push to registry
make push REPO=ghcr.io/rancher/ci-image
# Run tests, generate, and build
make allGenerated Dockerfiles are checked in to the repository — they are not built on-the-fly. The expected workflow for any change to deps.yaml or the templates is:
- Make your changes.
- Run
make generateto regeneratedockerfiles/andimages-lock.yaml. - Commit both the source changes and the generated output together.
make verify (run in CI) fails if there are uncommitted generated files, so a PR with stale output will not pass.
dockerfiles/Dockerfile.<name>— the rendered Dockerfile for each image. Do not edit these directly; edit the templates instead.images-lock.yaml— a compiled index generated bymake generate. Records the active image names, resolved base images, platforms, tool set, and resolved versions forlatest-pinned tools. Do not edit manually.archive/Dockerfile.<name>.<YYYYMMDD-HHMMSS>— whenmake generatedetects that a Dockerfile no longer has a corresponding image indeps.yaml, it moves it here rather than deleting it. Commit these alongside any image removal.
Dockerfiles are generated by the Go program in main.go using Go's text/template package. The templates live in internal/dockerfile/tmpl/ and are embedded into the binary at compile time.
dockerfile.tmpl— root template that assembles a complete Dockerfile. It calls the component templates below via{{template ...}}and.Install.Render().zypper.tmpl— renders thezypper installlayer for system packages.curl_binary.tmpl,curl_gzip.tmpl,curl_archive.tmpl— render thecurl-based install layer for a tool, varying by download format (plain binary,.gz, or.tar.gz/.zip).
To change how Dockerfiles are structured, edit the relevant template. To add a new install format, add a new curl_<format>.tmpl and wire it up in internal/dockerfile/install.go.