Push a single file as an ORAS artifact

July 27, 2026 ยท View on GitHub

Public API for container oras rules.

oras_file_layer

load("@rules_img//img:oras.bzl", "oras_file_layer")

oras_file_layer(*, name, src, annotations, aspect_hints, compatible_with, deprecation,
                exec_compatible_with, exec_group_compatible_with, exec_properties, features, kind,
                media_type, package_metadata, restricted_to, tags, target_compatible_with, testonly,
                title, toolchains, visibility)

Creates an ORAS-compatible layer from a single file.

This macro wraps layer_from_file and adds standard ORAS annotations so the resulting layer can be pushed to and pulled from OCI registries using ORAS tooling. The org.opencontainers.image.title annotation is automatically set to the base name of the source file (or overridden via the title attr).

Two modes are supported via the kind attribute:

  • "file" (default): The source file is used as an opaque blob.
  • "directory": The source file is treated as a tar archive. ORAS clients will unpack it on pull. The io.deis.oras.content.unpack and io.deis.oras.content.digest annotations are set automatically.

Example:

load("@rules_img//img:oras.bzl", "oras_file_layer")

# Push a single file as an ORAS artifact
oras_file_layer(
    name = "readme_layer",
    src = "README.md",
    media_type = "text/plain",
)

# Push a tar archive that ORAS clients will unpack
oras_file_layer(
    name = "docs_layer",
    src = ":docs.tar.gz",
    kind = "directory",
)

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this macro instance. Normally, this is also the name for the macro's main or only target. The names of any other targets that this macro might create will be this name with a string suffix.Namerequired
srcThe file to use as a layer blob.Labelrequired
annotationsAnnotations to add to the layer metadata as key-value pairs.Dictionary: String -> String; nonconfigurableoptional{}
aspect_hintsInherited rule attributeList of labelsoptionalNone
compatible_withInherited rule attributeList of labels; nonconfigurableoptionalNone
deprecationInherited rule attributeString; nonconfigurableoptionalNone
exec_compatible_withInherited rule attributeList of labels; nonconfigurableoptionalNone
exec_group_compatible_withInherited rule attributeDictionary: String -> List of labels; nonconfigurableoptionalNone
exec_propertiesInherited rule attributeDictionary: String -> StringoptionalNone
featuresInherited rule attributeList of stringsoptionalNone
kindThe kind of layer. "file" interprets the layer as-is, "directory" interprets the layer blob as a tar file containing a tree.String; nonconfigurableoptional"file"
media_typeLayer media type. Defaults to "application/vnd.oci.image.layer.v1.tar" if not set.StringoptionalNone
package_metadataInherited rule attributeList of labels; nonconfigurableoptionalNone
restricted_toInherited rule attributeList of labels; nonconfigurableoptionalNone
tagsInherited rule attributeList of strings; nonconfigurableoptionalNone
target_compatible_withInherited rule attributeList of labelsoptionalNone
testonlyInherited rule attributeBoolean; nonconfigurableoptionalNone
titleOptional override for org.opencontainers.image.title. If left empty, the title is derived from the base name of the blob.String; nonconfigurableoptional""
toolchainsInherited rule attributeList of labelsoptionalNone
visibilityThe visibility to be passed to this macro's exported targets. It always implicitly includes the location where this macro is instantiated, so this attribute only needs to be explicitly set if you want the macro's targets to be additionally visible somewhere else.List of labels; nonconfigurableoptional

oras_layer

load("@rules_img//img:oras.bzl", "oras_layer")

oras_layer(*, name, srcs, annotations, annotations_file, aspect_hints, compatible_with, compress,
           create_parent_directories, default_metadata, deprecation, estargz, exec_compatible_with,
           exec_group_compatible_with, exec_properties, features, file_metadata, include_runfiles,
           media_type, multi_file_layout, package_metadata, restricted_to, soci, symlinks, tags,
           target_compatible_with, testonly, title, toolchains, tree_artifact_handling, visibility)

Creates an ORAS-compatible layer from files and directories.

This macro wraps image_layer and adds standard ORAS annotations so the resulting layer can be pushed to and pulled from OCI registries using ORAS tooling:

  • org.opencontainers.image.title is set to the title attribute (defaults to the target name).
  • io.deis.oras.content.unpack is set to "true" so ORAS clients unpack the layer on pull.
  • io.deis.oras.content.digest is automatically derived from the layer's diff ID after the tar is produced.

Example:

load("@rules_img//img:oras.bzl", "oras_layer")

# Package application files as an ORAS artifact
oras_layer(
    name = "app_layer",
    srcs = {
        "/app/bin/server": "//cmd/server",
        "/app/config.json": ":config",
    },
)

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this macro instance. Normally, this is also the name for the macro's main or only target. The names of any other targets that this macro might create will be this name with a string suffix.Namerequired
srcsFiles to include in the layer. Keys are paths in the image (e.g., "/app/bin/server"), values are labels to files or executables.

When a value is an executable, the executable is placed at the path key and its runfiles tree is included (unless include_runfiles is set to False). Any additional default outputs of the target (the rest of DefaultInfo.files beyond the executable) are also copied, each placed at the same location relative to the executable that it has in the source tree.

When a value is a non-executable target that produces more than one default output, the path key is treated as a directory and the outputs are placed inside it according to multi_file_layout.
Dictionary: String -> LabeloptionalNone
annotationsAnnotations to add to the layer metadata as key-value pairs.Dictionary: String -> String; nonconfigurableoptional{}
annotations_fileFile containing annotations for the layer, as JSON or newline-delimited text.

The file is parsed in one of the following formats, auto-detected from its contents:

- JSON object with string values: {"key": "value"} - JSON object with list values: {"key": ["value1", "value2"]} (the last value wins) - JSON array of KEY=VALUE strings: ["key=value"] - newline-delimited KEY=VALUE text (one per line; blank lines and # comments are ignored)

Values in JSON objects are used verbatim, so they can encode arbitrary strings including values that contain =, spaces, or newlines. The KEY=VALUE forms (JSON array and text) split on the first = and trim surrounding whitespace from the key and value.

Annotations from this file are merged with annotations specified via the annotations attribute, which take precedence for matching keys.

Example file content:
version=1.0.0
build.date=2024-01-15
source.url=https://github.com/...
LabeloptionalNone
aspect_hintsInherited rule attributeList of labelsoptionalNone
compatible_withInherited rule attributeList of labels; nonconfigurableoptionalNone
compressCompression algorithm to use. If set to 'auto', uses the global default compression setting.Stringoptional"gzip"
create_parent_directoriesWhether 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.Stringoptional"enabled"
default_metadataJSON-encoded default metadata to apply to all files in the layer. Can include fields like mode, uid, gid, uname, gname, mtime, and pax_records.StringoptionalNone
deprecationInherited rule attributeString; nonconfigurableoptionalNone
estargzWhether 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.StringoptionalNone
exec_compatible_withInherited rule attributeList of labels; nonconfigurableoptionalNone
exec_group_compatible_withInherited rule attributeDictionary: String -> List of labels; nonconfigurableoptionalNone
exec_propertiesInherited rule attributeDictionary: String -> StringoptionalNone
featuresInherited rule attributeList of stringsoptionalNone
file_metadataPer-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 -> StringoptionalNone
include_runfilesWhether 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.

Either way, any additional default outputs of the target (the rest of DefaultInfo.files beyond the executable) are copied into the layer, placed relative to the executable.
BooleanoptionalNone
media_typeOverride the layer media type. By default, the media type is auto-detected from the compression algorithm.StringoptionalNone
multi_file_layoutHow to place a non-executable src that produces MORE THAN ONE default output.

- "package_relative" (default): treat the path key as a directory and place each file inside it, preserving its path relative to the producing target's package. - "flatten": place each file directly in the directory by basename (restores the older behavior).

A src that produces a single output is always placed exactly at its path key, regardless of this setting.
StringoptionalNone
package_metadataInherited rule attributeList of labels; nonconfigurableoptionalNone
restricted_toInherited rule attributeList of labels; nonconfigurableoptionalNone
sociWhether to emit a SOCI ztoc (table of contents) for this layer. If set to 'auto', uses the global default //img/settings:soci setting. When enabled and the layer is gzip-compressed, a ztoc is produced in the layer action and recorded on the SingleLayerInfo provider, so images that build a SOCI Index Manifest v2 can reuse it instead of regenerating it. Non-gzip layers never emit a ztoc.StringoptionalNone
symlinksSymlinks to create in the layer. Keys are symlink paths in the image, values are the targets they point to.Dictionary: String -> StringoptionalNone
tagsInherited rule attributeList of strings; nonconfigurableoptionalNone
target_compatible_withInherited rule attributeList of labelsoptionalNone
testonlyInherited rule attributeBoolean; nonconfigurableoptionalNone
titleOptional value for org.opencontainers.image.title. If left empty, the title is derived from the target name.String; nonconfigurableoptional""
toolchainsInherited rule attributeList of labelsoptionalNone
tree_artifact_handlingHow 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.StringoptionalNone
visibilityThe visibility to be passed to this macro's exported targets. It always implicitly includes the location where this macro is instantiated, so this attribute only needs to be explicitly set if you want the macro's targets to be additionally visible somewhere else.List of labels; nonconfigurableoptional