Public API for container image layer rules.
load("@rules_img//img:layer.bzl", "image_layer")
image_layer(name, srcs, annotations, annotations_file, compress, create_parent_directories,
default_metadata, estargz, file_metadata, include_runfiles, media_type, symlinks,
tree_artifact_handling)
Creates a container image layer from files, executables, and directories.
This rule packages files into a layer that can be used in container images. It supports:
- Adding files at specific paths in the image
- Setting file permissions and ownership
- Creating symlinks
- Including executables with their runfiles
- Compression (gzip, zstd) and eStargz optimization
Example:
load("@rules_img//img:layer.bzl", "image_layer", "file_metadata")
# Simple layer with files
image_layer(
name = "app_layer",
srcs = {
"/app/bin/server": "//cmd/server",
"/app/config.json": ":config.json",
},
)
# Layer with custom permissions
image_layer(
name = "secure_layer",
srcs = {
"/etc/app/config": ":config",
"/etc/app/secret": ":secret",
},
default_metadata = file_metadata(
mode = "0644",
uid = 1000,
gid = 1000,
),
file_metadata = {
"/etc/app/secret": file_metadata(mode = "0600"),
},
)
# Layer with symlinks
image_layer(
name = "bin_layer",
srcs = {
"/usr/local/bin/app": "//cmd/app",
},
symlinks = {
"/usr/bin/app": "/usr/local/bin/app",
},
)ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Files to include in the layer. Keys are paths in the image (e.g., "/app/bin/server"), values are labels to files or executables. Executables automatically include their runfiles unless include_runfiles is set to False. | Dictionary: String -> Label | optional | {} |
| annotations | Annotations to add to the layer metadata as key-value pairs. | Dictionary: String -> String | optional | {} |
| annotations_file | File containing newline-delimited KEY=VALUE annotations for the layer. The file should contain one annotation per line in KEY=VALUE format. Empty lines are ignored. Annotations from this file are merged with annotations specified via the annotations attribute.Example file content: |
Label | optional | None |
| compress | Compression algorithm to use. If set to 'auto', uses the global default compression setting. | String | optional | "auto" |
| create_parent_directories | Whether to automatically create parent directory entries in the tar file for all files. If set to 'auto', uses the global default create_parent_directories setting. When enabled, parent directories will be created automatically for all files in the layer. | String | optional | "auto" |
| default_metadata | JSON-encoded default metadata to apply to all files in the layer. Can include fields like mode, uid, gid, uname, gname, mtime, and pax_records. | String | optional | "" |
| estargz | Whether to use estargz format. If set to 'auto', uses the global default estargz setting. When enabled, the layer will be optimized for lazy pulling and will be compatible with the estargz format. | String | optional | "auto" |
| file_metadata | Per-file metadata overrides as a dict mapping file paths to JSON-encoded metadata. The path should match the path in the image (the key in srcs attribute). Metadata specified here overrides any defaults from default_metadata. | Dictionary: String -> String | optional | {} |
| include_runfiles | Whether to include runfiles for executable targets. When True (default), executables in srcs will include their runfiles tree. When False, only the executable file itself is included, without runfiles. | Boolean | optional | True |
| media_type | Override the layer media type. By default, the media type is auto-detected from the compression algorithm. | String | optional | "" |
| symlinks | Symlinks to create in the layer. Keys are symlink paths in the image, values are the targets they point to. | Dictionary: String -> String | optional | {} |
| tree_artifact_handling | How to handle duplicate tree artifacts (directories) in the layer. If set to 'full', each tree artifact is stored at its intended path (no deduplication). If set to 'deduplicate_symlink', duplicate tree artifacts are replaced with symlinks to the first occurrence. If set to 'auto', uses the global default from --@rules_img//img/settings:layer_tree_artifact_handling. | String | optional | "auto" |
load("@rules_img//img:layer.bzl", "layer_from_binary")
layer_from_binary(name, annotations, annotations_file, binary, compress, create_parent_directories,
estargz, include_runfiles, layer_budget, media_type, path, runfiles_path,
runfiles_shared_path, runfiles_sharing_mode, tree_artifact_handling)
Creates a container image layer from a *_binary target.
This rule packages a binary executable and its runfiles into a layer, and additionally provides image configuration (entrypoint, cmd, env, working_dir) via ImageLayerConfigInfo. When used as a layer in image_manifest, the configuration is automatically applied to the image with Dockerfile-like semantics.
The binary's args attribute becomes the image cmd, its env attribute (or
RunEnvironmentInfo provider) becomes env, and the binary path becomes the entrypoint.
When include_runfiles is True (default), the working directory is set to the runfiles root.
If the binary provides RunfilesGroupInfo (from rules_runfiles_group), the runfiles are split into separate layers based on the groups. This allows for better caching: stable layers (interpreter, stdlib) change infrequently and can be shared, while the application code layer changes with each build. The resolution protocol respects RunfilesGroupTransformInfo and RunfilesGroupMetadataInfo from the binary's aspect_hints.
When the number of groups exceeds what is practical for a container image, use layer_budget
to merge groups down to a maximum count. The merge algorithm respects group rank (only merges
within the same rank), do_not_merge flags, and weight hints (lighter groups merge first).
Example:
load("@rules_img//img:layer.bzl", "layer_from_binary")
load("@rules_img//img:image.bzl", "image_manifest")
# Package a Go binary with its runfiles
layer_from_binary(
name = "app_layer",
binary = "//cmd/server",
)
# Use in an image - entrypoint, cmd, env, and working_dir are set automatically
image_manifest(
name = "image",
base = "@distroless_base",
layers = [":app_layer"],
)
# Override the path inside the image
layer_from_binary(
name = "custom_path_layer",
binary = "//cmd/server",
path = "/usr/local/bin/",
)
# Without runfiles (static binary)
layer_from_binary(
name = "static_layer",
binary = "//cmd/server",
path = "/usr/local/bin/server",
include_runfiles = False,
)ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| annotations | Annotations to add to the layer metadata as key-value pairs. | Dictionary: String -> String | optional | {} |
| annotations_file | File containing newline-delimited KEY=VALUE annotations for the layer. The file should contain one annotation per line in KEY=VALUE format. Empty lines are ignored. Annotations from this file are merged with annotations specified via the annotations attribute.Example file content: |
Label | optional | None |
| binary | The *_binary target to package into the layer. The binary's args and env attributes are extracted and provided as image configuration (cmd and env) via ImageLayerConfigInfo. The data attribute is used for $(location) expansion in args and env values.If the binary provides RunfilesGroupInfo, the runfiles are split into separate layers per group. |
Label | required | |
| compress | Compression algorithm to use. If set to 'auto', uses the global default compression setting. | String | optional | "auto" |
| create_parent_directories | Whether to automatically create parent directory entries in the tar file for all files. If set to 'auto', uses the global default create_parent_directories setting. When enabled, parent directories will be created automatically for all files in the layer. | String | optional | "auto" |
| estargz | Whether to use estargz format. If set to 'auto', uses the global default estargz setting. When enabled, the layer will be optimized for lazy pulling and will be compatible with the estargz format. | String | optional | "auto" |
| include_runfiles | Whether to include runfiles for executable targets. When True (default), executables in srcs will include their runfiles tree. When False, only the executable file itself is included, without runfiles. | Boolean | optional | True |
| layer_budget | Maximum total number of layers produced by this rule. If set to a value > 0 and the binary provides RunfilesGroupInfo, groups are merged using the merge algorithm from rules_runfiles_group. The algorithm respects group rank (only merges within the same rank), do_not_merge flags, and weight hints (lighter groups merge first). When a group is marked as executable_group in RunfilesGroupMetadataInfo, the binary executable and supporting files are merged into that group's layer, and the full budget is available for runfiles groups. When no executable_group exists, one layer is reserved for a separate binary layer, and the remaining budget (layer_budget - 1) is used for groups; layer_budget=1 without an executable_group skips the grouped path entirely. 0 means no limit (all groups become separate layers, plus a binary layer unless an executable_group absorbs it). |
Integer | optional | 0 |
| media_type | Override the layer media type. By default, the media type is auto-detected from the compression algorithm. | String | optional | "" |
| path | Optional path of the binary inside the image. If the path ends with a slash ("/"), the basename of the binary will be automatically appended. If unset, this defaults to the rlocationpath of the binary (e.g., "main/cmd/server/server/server"). | String | optional | "" |
| runfiles_path | Optional path of the runfiles directory of the binary inside the image. If unset, this defaults to the path of the binary with a .runfiles suffix (e.g., "main/cmd/server/server/server.runfiles"). Note: depending on the runfiles_sharing_mode, this may be a symlink to a shared runfiles directory. | String | optional | "" |
| runfiles_shared_path | Optional path of the shared runfiles directory inside the image. This is only used when runfiles sharing is enabled and has a global default. | String | optional | "" |
| runfiles_sharing_mode | How to process runfiles. Runfiles can either be placed next to the executable (in a directory with a .runfiles suffix, the runfiles_path attribute), or placed in a shared runfiles path. When sharing runfiles, there will be symlink added: {runfiles_path} -> {runfiles_shared_path}. Possible settings: * "auto": Share runfiles based on the global default and based on the presence of RunfilesGroupInfo. Globally, runfiles sharing can be set to "shared", "private", or "auto", where auto shares runfiles if RunfilesGroupInfo is provided. * "shared": Always share runfiles. * "private": Never share runfiles |
String | optional | "auto" |
| tree_artifact_handling | How to handle duplicate tree artifacts (directories) in the layer. If set to 'full', each tree artifact is stored at its intended path (no deduplication). If set to 'deduplicate_symlink', duplicate tree artifacts are replaced with symlinks to the first occurrence. If set to 'auto', uses the global default from --@rules_img//img/settings:layer_tree_artifact_handling. | String | optional | "auto" |
load("@rules_img//img:layer.bzl", "layer_from_file")
layer_from_file(name, src, annotations, base_name_annotations, diff_id, diff_id_annotations,
media_type)
Creates a container image layer from an arbitrary file.
This rule uses any file as a container image layer blob, computing the necessary metadata (digest, size) without any tar-specific processing like compression or optimization.
This is useful for non-tar layer content such as Helm charts, WASM modules, or other OCI artifacts.
If you want to use an existing tar file as a layer, use layer_from_tar instead.
Example:
load("@rules_img//img:layer.bzl", "layer_from_file")
# Use an arbitrary artifact as a layer
layer_from_file(
name = "artifact_layer",
src = ":artifact.bin",
media_type = "application/octet-stream",
annotations = {
"org.opencontainers.image.title": "artifact.bin",
},
)ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| src | The file to use as a layer blob. | Label | required | |
| annotations | Annotations to add to the layer metadata as key-value pairs. | Dictionary: String -> String | optional | {} |
| base_name_annotations | List of annotations that are set to the basename of the file. | List of strings | optional | [] |
| diff_id | If set, interprets the file as a (potentially compressed) tar file and calculates the diff_id. Warning: if you do this, you probably want to use layer_from_tar instead. | Boolean | optional | False |
| diff_id_annotations | List of annotations that are set to the diff_id of the file. Only works with tar files. | List of strings | optional | [] |
| media_type | Layer media type. Defaults to "application/vnd.oci.image.layer.v1.tar" if not set. | String | optional | "application/vnd.oci.image.layer.v1.tar" |
load("@rules_img//img:layer.bzl", "layer_from_tar")
layer_from_tar(name, src, annotations, compress, estargz, media_type, optimize)
Creates a container image layer from an existing tar archive.
This rule converts tar files into container image layers, useful for incorporating pre-built artifacts, third-party distributions, or legacy build outputs.
The rule can:
- Use tar files as-is or recompress them
- Optimize tar contents by deduplicating files
- Add annotations to the layer metadata
Example:
load("@rules_img//img:layer.bzl", "layer_from_tar")
# Use an existing tar file as a layer
layer_from_tar(
name = "third_party_layer",
src = "@third_party_lib//:lib.tar.gz",
)
# Optimize and recompress
layer_from_tar(
name = "optimized_layer",
src = "//legacy:build_output.tar",
optimize = True, # Deduplicate contents
compress = "zstd", # Use zstd compression
)
# Add metadata annotations
layer_from_tar(
name = "annotated_layer",
src = "//vendor:dependencies.tar.gz",
annotations = {
"org.opencontainers.image.title": "Vendor Dependencies",
"org.opencontainers.image.version": "1.2.3",
},
)ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| src | The tar file to convert into a layer. Must be a valid tar file (optionally compressed). | Label | required | |
| annotations | Annotations to add to the layer metadata as key-value pairs. | Dictionary: String -> String | optional | {} |
| compress | Compression algorithm to use. If set to 'auto', it keeps the existing compression, unless the layer is being optimized. | String | optional | "auto" |
| estargz | Whether to use estargz format. If set to 'auto', uses the global default estargz setting. When enabled, the layer will be optimized for lazy pulling and will be compatible with the estargz format. | String | optional | "auto" |
| media_type | Override layer media type. Use e.g. "application/vnd.cncf.helm.chart.content.v1.tar" for Helm charts. | String | optional | "" |
| optimize | If set, rewrites the tar file to deduplicate it's contents. This is useful for reducing the size of the image, but will take extra time and space to store the optimized layer. | Boolean | optional | False |
load("@rules_img//img:layer.bzl", "file_metadata")
file_metadata(*, mode, uid, gid, uname, gname, mtime, pax_records)
Creates a JSON-encoded file metadata string for use with image_layer rules.
This function generates JSON metadata that can be used to customize file attributes in container image layers, such as permissions, ownership, and timestamps.
PARAMETERS
RETURNS
JSON-encoded string containing the file metadata.