Implementation:MaterializeInc Materialize ResolvedImage Build
Appearance
| Knowledge Sources | misc/python/materialize/mzbuild.py (ResolvedImage.build, ResolvedImage.write_dockerfile)
|
|---|---|
| Domains | Build Systems, Containerization, Cross-Compilation, CI/CD |
| Last Updated | 2026-02-08 |
Overview
Concrete implementation of multi-stage container image construction provided by ResolvedImage.build() in Materialize's mzbuild system, orchestrating pre-image actions, Dockerfile rewriting, and Docker build execution.
Description
ResolvedImage.build() (lines 879-953) is the method that actually builds a Docker image from source. It performs the following steps in sequence:
- Clean the build context -- Runs
git clean -ffdXon the image's directory to remove all untracked and gitignored files, ensuring a pristine build context.
- Execute pre-image actions -- Iterates over the image's
pre_imageslist (e.g.,CargoBuild,Copy) and runs each with the pre-prepared batch data fromprep.
- Assemble build arguments -- Constructs the
build_argsdictionary combining image-specific build args frommzbuild.ymlwith system-level args:BUILD_PROFILE,ARCH_GCC,ARCH_GO, andCI_SANITIZER.
- Render the Dockerfile -- Calls
write_dockerfile()which reads the image's Dockerfile, replaces allMZFROM {name}directives with standardFROM {resolved_spec}lines (using the dependency's fingerprint-tagged spec), and writes the result to a temporary file.
- Select build backend -- Attempts to use
docker buildx build. If buildx is not installed, falls back todocker build(unlesspush=True, in which case buildx is required and an error is raised).
- Authenticate to GHCR -- If the
GITHUB_GHCR_TOKENenvironment variable is set, logs intoghcr.iousingdocker loginwith thematerialize-botuser.
- Execute the Docker build -- Runs the assembled command, piping the rendered Dockerfile via stdin (
-f -). With buildx, the image is dual-tagged for both Docker Hub (docker.io/{spec}) and GHCR (ghcr.io/materializeinc/{spec}). The--loadflag is used for local builds, or--pushfor remote publishing.
Usage
Use ResolvedImage.build() when:
- Building an image locally during development -- Call with
push=False(default) to build and load the image into the local Docker daemon. - As part of the
DependencySet.acquire()workflow -- When a pre-built image cannot be pulled from the registry,acquire()falls back to building from source. - Never call directly without preparation -- The
prepdictionary must be populated by callingDependencySet._prepare_batch()first, which runsPreImage.prepare_batch()for all pre-image action types.
Code Reference
Source Location
| File | misc/python/materialize/mzbuild.py
|
|---|---|
build()
|
Lines 879-953 |
write_dockerfile()
|
Lines 860-877 |
spec()
|
Lines 851-858 |
Signature
class ResolvedImage:
def build(self, prep: dict[type[PreImage], Any], push: bool = False) -> None:
"""Build the image from source.
Requires that the caller has already acquired all dependencies and
prepared all `PreImage` actions via `PreImage.prepare_batch`.
"""
...
def write_dockerfile(self) -> IO[bytes]:
"""Render the Dockerfile without mzbuild directives.
Returns:
file: A handle to a temporary file containing the adjusted
Dockerfile.
"""
...
@cache
def spec(self) -> str:
"""Return the "spec" for the image.
A spec is the unique identifier for the image given its current
fingerprint. It is a valid Docker Hub name.
"""
return self.image.docker_name(tag=f"mzbuild-{self.fingerprint()}")
Import
from materialize.mzbuild import ResolvedImage
I/O Contract
Inputs
| Parameter | Type | Description |
|---|---|---|
prep |
dict[type[PreImage], Any] |
Pre-computed preparation data for each pre-image action type, produced by DependencySet._prepare_batch().
|
push |
bool |
If False (default), build and load into the local Docker daemon (--load). If True, build and push to remote registries (--push).
|
self.image.path |
Path |
Directory containing the Dockerfile and mzbuild.yml.
|
self.image.pre_images |
list[PreImage] |
Pre-image actions (e.g., CargoBuild, Copy) to execute before Docker build.
|
self.image.build_args |
dict |
Additional Docker build arguments from mzbuild.yml.
|
self.image.rd.profile |
Profile |
Rust build profile name injected as BUILD_PROFILE build arg.
|
self.image.rd.arch |
Arch |
Target architecture, used for ARCH_GCC, ARCH_GO, and --platform.
|
self.image.rd.sanitizer |
Sanitizer |
Sanitizer mode injected as CI_SANITIZER build arg.
|
GITHUB_GHCR_TOKEN env var |
str (optional) |
If set, used to authenticate to GHCR before building. |
Outputs
| Output | Type | Description |
|---|---|---|
| Return value | None |
The method returns nothing; it operates via side effects. |
| Side effect: Docker image | Docker daemon / registry | A Docker image tagged with self.spec() is either loaded locally (--load) or pushed to registries (--push).
|
| Side effect: git clean | Filesystem | All untracked and gitignored files in the image directory are removed. |
| Side effect: pre-image artifacts | Filesystem | Pre-image actions (e.g., Cargo build) may produce binary artifacts in the build context. |
Usage Examples
Building an image locally (via DependencySet):
from pathlib import Path
from materialize.mzbuild import Repository
repo = Repository(root=Path("/path/to/materialize"))
deps = repo.resolve_dependencies([repo.images["environmentd"]])
# acquire() tries to pull first, falls back to build()
deps.acquire()
Understanding the internal build flow:
# Step 1: Clean the build context
# git clean -ffdX /path/to/image/dir
# Step 2: Run pre-image actions
# e.g., CargoBuild compiles Rust binaries and copies them
# into the image directory
# Step 3: Assemble build args
# build_args = {
# **image.build_args, # from mzbuild.yml
# "BUILD_PROFILE": "OPTIMIZED", # from rd.profile
# "ARCH_GCC": "x86_64", # from rd.arch
# "ARCH_GO": "amd64", # from rd.arch.go_str()
# "CI_SANITIZER": "none", # from rd.sanitizer
# }
# Step 4: Render Dockerfile (MZFROM -> FROM)
# MZFROM some-dep --> FROM materialize/some-dep:mzbuild-FINGERPRINT
# Step 5: Execute docker buildx build
# docker buildx build --progress=plain -f - \
# --build-arg=BUILD_PROFILE=OPTIMIZED \
# --build-arg=ARCH_GCC=x86_64 \
# --build-arg=ARCH_GO=amd64 \
# --build-arg=CI_SANITIZER=none \
# -t docker.io/materialize/environmentd:mzbuild-FINGERPRINT \
# -t ghcr.io/materializeinc/materialize/environmentd:mzbuild-FINGERPRINT \
# --platform=linux/amd64 \
# /path/to/image/dir \
# --load
Dual-tagging for Docker Hub and GHCR:
# When using buildx, the image is tagged for both registries:
# -t docker.io/{spec}
# -t ghcr.io/materializeinc/{spec}
#
# Where {spec} = "materialize/environmentd:mzbuild-ABCDE..."
# This allows the image to be pulled from either registry.
Related Pages
Implements Principle
Requires Environment
- Environment:MaterializeInc_Materialize_Docker_Compose_Runtime
- Environment:MaterializeInc_Materialize_Python_CI_Builder_Runtime
Uses Heuristic
Page Connections
Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment