Skip to content

build

The build section defines how imglife generates Dockerfiles from templates and pushes base images to your registry.

build:
core_version: "1.0.0"
registry: registry.example.com/bases
builder: imglife-builder # optional buildx builder name
platforms: [linux/amd64, linux/arm64]
sbom: true
tag_format: "{registry}/{folder}:{mirror-tag}-{build_name}"
hooks:
post_image_build:
- cmd: cosign sign --yes {image}
timeout: 120s
images:
- name: alpine
folder: images/alpine
type: core
mirror_image: registry.example.com/mirrors/alpine
mirror_tag: "3.21.3"
version: "3.21.3"
Field Type Required Default Description
core_version string yes Organisation build version; bumped when your templates/config change
registry string yes Base path where built images are pushed
builder string no docker buildx builder instance name; omit to use the default
platforms []string no [linux/amd64] Default target platforms
sbom bool no false Attach SBOM attestation (requires buildx)
tag_format string no {registry}/{folder}:{mirror-tag}-{build_name} Token template for the full image reference (see Tag format)
hooks.post_image_build []Hook no Commands to run after each image is built and pushed
Field Type Required Default Description
name string yes Image name (used in logs and the {build_name} token)
folder string yes Registry sub-path for the built image (the {folder} token), e.g. images/alpine
type string yes core, spe, or spe-dev (affects EOL checking)
mirror_image string yes Mirror image used as FROM (must not include a tag)
mirror_tag string no latest resolved Pin a specific mirror tag; omit to auto-resolve the latest
mirror_tag_regex string no Restricts automatic latest-tag resolution to mirror tags matching this anchored regex (validated at config load). Mutually exclusive with mirror_tag. See Version lines.
version string conditional Required for spe/spe-dev; forbidden for core (which uses core_version)
tmpl string conditional templates/core.tmpl Template path; required for spe/spe-dev, forbidden for core
args map[string]string no Additional --build-arg values
os_family string no auto-detected Overrides OS family detection for templates ({{.OSFamily}}). Known values: alpine, debian, ubuntu, rhel; free-form lowercase values are allowed for custom templates.
platforms []string no inherits top-level Per-image platform override
sbom bool no inherits top-level Per-image SBOM override
hooks Hooks no Per-image hooks
Type Description EOL checked Appears in status
core Production base image Yes Yes
spe Special-purpose variant Yes Yes
spe-dev Development variant No No

Several build.images blocks may share the same folder (and usually the same mirror_image). Each block is then an independent version line, identified by its mirror_tag or mirror_tag_regex:

images:
- name: jdk-core-8
folder: jdk
type: core
mirror_image: registry.example.com/mirrors/jdk
mirror_tag_regex: ^8-jdk-alpine.*$
- name: jdk-core-25
folder: jdk
type: core
mirror_image: registry.example.com/mirrors/jdk
mirror_tag_regex: ^25-jdk-alpine.*$

Every command reasons per line, not per repository:

Command Per-line behaviour
build Resolves the latest mirror tag within the line only
status One table row per block, each with its own tag, build date, EOL cycle and Markdown link definition ([base-<image-name>])
cleanup keep_last is applied per line — an older line (JDK 8) is no longer evicted by a newer one (JDK 25) in the same repo
check The suggested latest_tag and the EOL cycle stay within the line of the tag in use
eol Alerts and endoflife.date cycles are resolved from the tag’s line

The same applies to sync entries sharing a target, where the line is defined by tag / tag_regex.

imglife renders Dockerfile.tmpl using Go’s text/template engine. The following variables are available:

Variable Example Description
{{.MirrorImage}} registry.example.com/mirrors/alpine:3.21.3 Fully-resolved mirror image reference (tag already appended)
{{.CoreVersion}} 1.0.0 Organisation core version (build.core_version)
{{.Version}} 3.21.3 core_version for core images, or the image version
{{.Name}} alpine Image name
{{.Type}} core Image type (core, spe, spe-dev)
{{.OSFamily}} alpine OS family of the mirror image (see OS family resolution)
{{.Args}} {KEY: value} Map of the image’s args
Function Example Description
bool {{ if bool (index .Args "FLAG") }} Parses an Args value as a boolean (accepts true/True/TRUE, false/False/FALSE, 1/0, t/f, case-insensitively — unlike a raw string comparison against YAML’s literal scalar text). Missing/empty arg → false without error; invalid value → build error.
int {{ if gt (int (index .Args "RETRY_COUNT")) 5 }} Parses an Args value as an integer for numeric comparisons (e.g. gt, lt, eq). Missing/empty arg → 0 without error; invalid value → build error.
float {{ if ge (float (index .Args "THRESHOLD")) 1.5 }} Parses an Args value as a float64 for numeric comparisons. Missing/empty arg → 0 without error; invalid value → build error.

{{.OSFamily}} is resolved through a three-level cascade; the first level that yields a result wins:

  1. os_family in the config — explicit per-image override, no network call.
  2. /etc/os-release inspection — the mirror image layers are read from the registry and the ID / ID_LIKE fields are mapped to a family (e.g. UBI images declare ID_LIKE="rhel fedora"rhel). Covers images whose name carries no OS hint, such as python:3.13.
  3. Name heuristics — keywords matched in the mirror image reference (alpine, debian and its codenames, ubuntu and its codenames, ubi/rhel/redhat/centos/rockylinux/almalinux).

Possible values: alpine, debian, ubuntu, rhel, an unmapped os-release ID passed through as-is (e.g. wolfi), or unknown. When the resolution ends at unknown, a warning is logged at build time suggesting to set os_family explicitly:

images:
- name: ubi
folder: images/ubi
type: core
mirror_image: registry.example.com/mirrors/ubi9
os_family: rhel # explicit override — skips detection

Example Dockerfile.tmpl:

FROM {{ .MirrorImage }}
RUN apk add --no-cache \
ca-certificates \
tzdata \
curl
# OCI labels are injected automatically by imglife

imglife injects these OCI labels on every build:

org.opencontainers.image.created = <build timestamp>
org.opencontainers.image.revision = <git SHA>
org.opencontainers.image.source = <project URL>
org.opencontainers.image.base.name = <mirror image>
org.opencontainers.image.base.digest = <mirror digest>

tag_format is rendered with single-brace tokens (not Go templates). The default is {registry}/{folder}:{mirror-tag}-{build_name}, which produces the full destination reference. You can customise it:

build:
tag_format: "{registry}/{folder}:{mirror-tag}-org{version}"
# Produces: registry.example.com/bases/images/alpine:3.21.3-org1.0.0

Available tokens:

Token Expands to Example
{registry} build.registry registry.example.com/bases
{folder} the image folder images/alpine
{type} the image type core
{version} core_version for core, otherwise the image version 1.0.0
{build_name} {type}{version} core1.0.0
{mirror-tag} the resolved mirror tag 3.21.3

Validation rules: unknown tokens are rejected, {registry} is required, and at least one of {build_name}, {type}, or {version} must be present.

build:
platforms: [linux/amd64, linux/arm64]
builder: imglife-builder # buildx builder must support multi-arch

When platforms has more than one entry, imglife uses docker buildx build with --push to publish a multi-arch manifest. A builder with docker-container driver is required.

Instead of building and pushing, imglife can write Docker build contexts to a local directory for consumption by external builders (Kaniko, Buildah):

Terminal window
imglife build --output-dir /tmp/imglife-contexts

Each context directory contains a Dockerfile, a build.json manifest, and any required files. See imglife build for the full reference.

build:
hooks:
post_image_build:
- cmd: cosign sign --yes {image}
timeout: 120s
continue_on_error: false

In hook commands, the literal placeholder {image} is replaced with the fully-qualified image reference including tag. It is the only substitution available; the command is run via sh -c.

Each hook entry accepts cmd (required), timeout (optional Go duration, e.g. 120s), and continue_on_error (optional bool).