How Iris Environment Variables Are Injected Into Docker Containers
Iris injects environment variables into Docker containers through a two-phase pipeline that embeds immutable build-time metadata via Dockerfile directives and propagates dynamic run-time configuration via the DockerRuntime class.
The marin-community/marin project implements a strict environment variable injection system to ensure containerized workers maintain provenance tracking while receiving live configuration from the controller. This dual-phase approach separates static image attributes from mutable deployment parameters, ensuring reproducibility across distributed clusters.
Build-Time Injection via Dockerfile ARG and ENV
Iris bakes provenance metadata directly into container images during the build process. This guarantees that every image carries immutable identifiers regardless of where it executes.
Defining Iris Metadata as Build Arguments
In lib/iris/Dockerfile, Iris declares build arguments between lines 193-201 to capture version control context. These declarations accept values passed during the Docker build process:
ARG IRIS_GIT_HASH=unknown
ARG IRIS_PROVENANCE={}
ARG IRIS_REVISION_DATE=
When the Iris build pipeline executes, it passes specific commit hashes and build timestamps to these arguments. This establishes a permanent link between the running container and the exact source revision used to construct it.
Promoting ARG to ENV Variables
Immediately after declaration, Iris promotes these build arguments to environment variables using the ENV directive. This conversion persists the values in the final image layer:
ENV IRIS_GIT_HASH=${IRIS_GIT_HASH}
ENV IRIS_PROVENANCE=${IRIS_PROVENANCE}
ENV IRIS_REVISION_DATE=${IRIS_REVISION_DATE}
By promoting ARG to ENV, the metadata becomes queryable via docker inspect and accessible to applications running inside the container without requiring external configuration mounts.
Run-Time Injection via DockerRuntime
While build-time variables capture static metadata, the DockerRuntime class in lib/iris/cluster/runtime/docker.py handles dynamic configuration when launching worker containers.
Filtering IRIS_ Prefixed Variables
When DockerRuntime.create_container() executes, it filters the current process environment to identify Iris-specific configuration. The implementation iterates over os.environ and selects only keys beginning with the IRIS_ prefix:
env_vars = {
key: os.getenv(key)
for key in os.environ
if key.startswith("IRIS_")
}
This selective propagation ensures the container receives essential runtime parameters—such as IRIS_CONTROLLER_URL, IRIS_JOB_ENV, and IRIS_MULTIGPU_PROCESS_INDEX—without inheriting unrelated host environment variables that could cause conflicts.
Constructing the Docker Command
After collecting the filtered variables, DockerRuntime constructs the docker run command by expanding the environment dictionary into explicit --env flags:
docker_cmd = [
"docker", "run", "--rm",
*(f"--env={k}={v}" for k, v in env_vars.items()),
self.image,
*cmd
]
subprocess.run(docker_cmd, check=True)
Each key-value pair becomes an explicit --env KEY=VALUE argument in the subprocess call. This approach ensures compatibility across Docker versions and prevents environment leakage through inherited shell contexts.
Security and Configuration Boundaries
The injection mechanism respects security boundaries defined in lib/iris/config.py via the WorkerConfig class. When DOCKER_ACCESS is enabled, the runtime mounts the Docker socket while maintaining strict control over which variables propagate.
Sensitive values such as API tokens travel through the same IRIS_ prefixed channel, often consolidated under IRIS_JOB_ENV. Because DockerRuntime uses explicit command-line flags rather than environment files, these secrets remain scoped to the specific container process and do not persist in host shell histories.
Complete Worker Launch Example
Combining both phases, launching an Iris worker container executes as follows:
docker run --rm \
--env IRIS_CONTROLLER_URL=https://controller.example.com \
--env IRIS_JOB_ENV='{"HF_TOKEN":"abc123"}' \
--env IRIS_MULTIGPU_PROCESS_INDEX=0 \
ghcr.io/marin-community/iris-worker:latest \
python -m iris.task.main
In this invocation, IRIS_CONTROLLER_URL and IRIS_JOB_ENV originate from the controller's environment and pass through DockerRuntime, while the underlying image already contains IRIS_GIT_HASH from the build process documented in lib/iris/Dockerfile.
Summary
- Build-time injection uses
ARGandENVdirectives inlib/iris/Dockerfile(lines 193-201) to bake provenance metadata into images at build time. - Run-time injection relies on
DockerRuntimeinlib/iris/cluster/runtime/docker.pyto filterIRIS_prefixed variables and append them as--envflags todocker runcommands. - The WorkerConfig class in
lib/iris/config.pygoverns which security contexts and variables should propagate to containers. - The dual-phase approach separates immutable image metadata from dynamic configuration and secrets, ensuring reproducibility while maintaining operational flexibility.
Frequently Asked Questions
How does Iris distinguish between build-time and run-time environment variables?
Iris uses Dockerfile ARG and ENV directives for build-time data like IRIS_GIT_HASH, while the DockerRuntime class handles run-time variables by scanning for the IRIS_ prefix in the current process environment. Build-time variables become permanent image attributes baked into the container layer, whereas run-time variables are injected fresh via --env flags with every container launch.
Where does the DockerRuntime class locate the environment variables it injects?
DockerRuntime inspects the Python os.environ dictionary to source variables. According to the implementation in lib/iris/cluster/runtime/docker.py, it specifically filters for keys starting with IRIS_ to ensure only Iris-related configuration propagates to worker containers, preventing pollution from the host environment.
Can I pass sensitive secrets through Iris environment variables?
Yes. Iris injects secrets via the same IRIS_ prefixed mechanism, often consolidated under IRIS_JOB_ENV. Because DockerRuntime uses explicit --env flags generated at execution time rather than mounting environment files or using Docker's inherited environment feature, secrets remain scoped to the specific container process and do not persist on the host filesystem or in shell histories.
What happens if an environment variable is defined both at build-time and run-time?
Run-time values take precedence because DockerRuntime explicitly sets them via --env flags when executing docker run. This allows the same base image to serve different controllers or job configurations without rebuilding, while the build-time metadata remains available as fallback provenance data visible through docker inspect or inside the container.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →