# rules_docker **Repository Path**: mirrors_databricks/rules_docker ## Basic Information - **Project Name**: rules_docker - **Description**: Rules for building and handling Docker images with Bazel - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-24 - **Last Updated**: 2025-10-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Bazel Container Image Rules Travis CI | Bazel CI :---: | :---: [](https://travis-ci.org/bazelbuild/rules_docker) | [](https://ci.bazel.io/job/rules_docker) ## Basic Rules * [container_image](#container_image-1) ([example](#container_image)) * [container_bundle](#container_bundle-1) ([example](#container_bundle)) * [container_import](#container_import) * [container_load](#container_load) * [container_pull](#container_pull-1) ([example](#container_pull)) * [container_push](#container_push-1) ([example](#container_push)) These rules used to be `docker_build`, `docker_push`, etc. and the aliases for these (mostly) legacy names still exist largely for backwards-compatibility. We also have **early-stage** `oci_image`, `oci_push`, etc. aliases for folks that enjoy the consistency of a consistent rule prefix. The only place the format-specific names currently do any more than alias things is in `foo_push`, where they also specify the appropriate format as which to publish the image. ### Overview This repository contains a set of rules for pulling down base images, augmenting them with build artifacts and assets, and publishing those images. **These rules do not require / use Docker for pulling, building, or pushing images.** This means: * They can be used to develop Docker containers on Windows / OSX without `boot2docker` or `docker-machine` installed. * They do not require root access on your workstation. Also, unlike traditional container builds (e.g. Dockerfile), the Docker images produced by `container_image` are deterministic / reproducible. __NOTE:__ `container_push` and `container_pull` make use of [google/containerregistry](https://github.com/google/containerregistry) for registry interactions. ## Language Rules * [cc_image](#cc_image) ([signature]( https://docs.bazel.build/versions/master/be/c-cpp.html#cc_binary)) * [go_image](#go_image) ([signature]( https://github.com/bazelbuild/rules_go#go_binary)) * [py_image](#py_image) ([signature]( https://docs.bazel.build/versions/master/be/python.html#py_binary)) * [py3_image](#py3_image) ([signature]( https://docs.bazel.build/versions/master/be/python.html#py_binary)) * [java_image](#java_image) ([signature]( https://docs.bazel.build/versions/master/be/java.html#java_binary)) * [war_image](#war_image) ([signature]( https://docs.bazel.build/versions/master/be/java.html#java_library)) * [scala_image](#scala_image) ([signature]( https://github.com/bazelbuild/rules_scala#scala_binary)) * [groovy_image](#groovy_image) ([signature]( https://github.com/bazelbuild/rules_groovy#groovy_binary)) * [rust_image](#rust_image) ([signature]( https://github.com/bazelbuild/rules_rust#rust_binary)) * [d_image](#d_image) ([signature]( https://github.com/bazelbuild/rules_d#d_binary)) ### Overview In addition to low-level rules for building containers, this repository provides a set of higher-level rules for containerizing applications. The idea behind these rules is to make containerizing an application built via a `lang_binary` rule as simple as changing it to `lang_image`. By default these higher level rules make use of the [`distroless`]( https://github.com/googlecloudplatform/distroless) language runtimes, but these can be overridden via the `base="..."` attribute (e.g. with a `container_pull` or `container_image` target). ## Setup Add the following to your `WORKSPACE` file to add the external repositories: ```python git_repository( name = "io_bazel_rules_docker", remote = "https://github.com/bazelbuild/rules_docker.git", tag = "v0.3.0", ) load( "@io_bazel_rules_docker//container:container.bzl", "container_pull", container_repositories = "repositories", ) # This is NOT needed when going through the language lang_image # "repositories" function(s). container_repositories() container_pull( name = "java_base", registry = "gcr.io", repository = "distroless/java", # 'tag' is also supported, but digest is encouraged for reproducibility. digest = "sha256:deadbeef", ) ``` ## Using with Docker locally. Suppose you have a `container_image` target `//my/image:helloworld`: ```python container_image( name = "helloworld", ... ) ``` You can load this into your local Docker client by running: `bazel run my/image:helloworld`. For the `lang_image` targets, this will also **run** the container to maximize compatibility with `lang_binary` rules. You can suppress this behavior by passing the single flag: `bazel run :foo -- --norun` Alternatively, you can build a `docker load` compatible bundle with: `bazel build my/image:helloworld.tar`. This will produce the file: `bazel-genfiles/my/image/helloworld.tar`, which you can load into your local Docker client by running: `docker load -i bazel-genfiles/my/image/helloworld.tar`. Building this target can be expensive for large images. These work with both `container_image`, `container_bundle`, and the `lang_image` rules. For everything except `container_bundle`, the image name will be `bazel/my/image:helloworld`. For `container_bundle`, it will apply the tags you have specified. ## Authorization You can use these rules to access private images using standard Docker authentication methods. e.g. to utilize the [Google Container Registry]( https://gcr.io) [credential helper]( https://github.com/GoogleCloudPlatform/docker-credential-gcr): ```shell $ gcloud components install docker-credential-gcr $ docker-credential-gcr configure-docker ``` See also: * [Amazon ECR Docker Credential Helper]( https://github.com/awslabs/amazon-ecr-credential-helper) * [Azure Docker Credential Helper]( https://github.com/Azure/acr-docker-credential-helper) ## Varying image names A common request from folks using `container_push` or `container_bundle` is to be able to vary the tag that is pushed or embedded. There are two options at present for doing this. ### Stamping The first option is to use `stamp = True`. ```python # A common pattern when users want to avoid trampling # on each other's images during development. container_push( name = "publish", format = "Docker", # Any of these components may have variables. registry = "gcr.io", repository = "my-project/my-image", tag = "{BUILD_USER}", # Trigger stamping. stamp = True, ) ``` The next natural question is: "Well what variables can I use?" This option consumes the workspace-status variables Bazel defines in `stable-status.txt` and `volatile-status.txt`. These files will appear in the target's runfiles: ```shell $ bazel build //docker/testdata:push_stamp ... $ cat bazel-bin/docker/testdata/push_stamp.runfiles/io_bazel_rules_docker/stable-status.txt BUILD_EMBED_LABEL BUILD_HOST bazel BUILD_USER mattmoor $ cat bazel-bin/docker/testdata/push_stamp.runfiles/io_bazel_rules_docker/volatile-status.txt BUILD_TIMESTAMP 1498740967769 ``` You can augment these variables via `--workspace_status_command`, including through the use of [`.bazelrc`](https://github.com/kubernetes/kubernetes/blob/81ce94ae1d8f5d04058eeb214e9af498afe78ff2/build/root/.bazelrc#L6). ### Make variables The second option is to employ `Makefile`-style variables: ```python container_bundle( name = "bundle", images = { "gcr.io/$(project)/frontend:latest": "//frontend:image", "gcr.io/$(project)/backend:latest": "//backend:image", } ) ``` These variables are specified on the CLI using: ```shell bazel build --define project=blah //path/to:bundle ``` ## Debugging `lang_image` rules By default the `lang_image` rules use the `distroless` base runtime images, which are optimized to be the minimal set of things your application needs at runtime. That can make debugging these containers difficult because they lack even a basic shell for exploring the filesystem. To address this, we publish variants of the `distroless` runtime images tagged `:debug`, which are the exact-same images, but with additions such as `busybox` to make debugging easier. For example (in this repo): ```shell $ bazel run -c dbg testdata:go_image ... INFO: Build completed successfully, 5 total actions INFO: Running command line: bazel-bin/testdata/go_image Loaded image ID: sha256:9c5c2167a1db080a64b5b401b43b3c5cdabb265b26cf7a60aabe04a20da79e24 Tagging 9c5c2167a1db080a64b5b401b43b3c5cdabb265b26cf7a60aabe04a20da79e24 as bazel/testdata:go_image Hello, world! $ docker run -ti --rm --entrypoint=sh bazel/testdata:go_image -c "echo Hello, busybox." Hello, busybox. ``` ## Examples ### container_image ```python container_image( name = "app", # References container_pull from WORKSPACE (above) base = "@java_base//image", files = ["//java/com/example/app:Hello_deploy.jar"], cmd = ["Hello_deploy.jar"] ) ``` ### cc_image To use `cc_image`, add the following to `WORKSPACE`: ```python load( "@io_bazel_rules_docker//cc:image.bzl", _cc_image_repos = "repositories", ) _cc_image_repos() ``` Then in your `BUILD` file, simply rewrite `cc_binary` to `cc_image` with the following import: ```python load("@io_bazel_rules_docker//cc:image.bzl", "cc_image") cc_image( name = "cc_image", srcs = ["cc_image.cc"], deps = [":cc_image_library"], ) ``` ### py_image To use `py_image`, add the following to `WORKSPACE`: ```python load( "@io_bazel_rules_docker//python:image.bzl", _py_image_repos = "repositories", ) _py_image_repos() ``` Then in your `BUILD` file, simply rewrite `py_binary` to `py_image` with the following import: ```python load("@io_bazel_rules_docker//python:image.bzl", "py_image") py_image( name = "py_image", srcs = ["py_image.py"], deps = [":py_image_library"], main = "py_image.py", ) ``` ### py_image (fine layering) For Python and Java's `lang_image` rules, you can factor dependencies that don't change into their own layers by overriding the `layers=[]` attribute. Consider this sample from the `rules_k8s` repository: ```python py_image( name = "server", srcs = ["server.py"], # "layers" is just like "deps", but it also moves the dependencies each into # their own layer, which can dramatically improve developer cycle time. For # example here, the grpcio layer is ~40MB, but the rest of the app is only # ~400KB. By partitioning things this way, the large grpcio layer remains # unchanging and we can reduce the amount of image data we repush by ~99%! layers = [ requirement("grpcio"), "//examples/hellogrpc/proto:py", ], main = "server.py", ) ``` ### py3_image To use a Python 3 runtime instead of the default of Python 2, use `py3_image`, instead of `py_image`. The other semantics are identical. ### go_image To use `go_image`, add the following to `WORKSPACE`: ```python # You *must* import the Go rules before setting up the go_image rules. git_repository( name = "io_bazel_rules_go", commit = "{HEAD}", remote = "https://github.com/bazelbuild/rules_go.git", ) load("@io_bazel_rules_go//go:def.bzl", "go_repositories") go_repositories() load( "@io_bazel_rules_docker//go:image.bzl", _go_image_repos = "repositories", ) _go_image_repos() ``` Then in your `BUILD` file, simply rewrite `go_binary` to `go_image` with the following import: ```python load("@io_bazel_rules_docker//go:image.bzl", "go_image") go_image( name = "go_image", srcs = ["main.go"], importpath = "github.com/your/path/here", ) ``` ### go_image (custom base) To use a custom base image, with any of the `lang_image` rules, you can override the default `base="..."` attribute. Consider this modified sample from the `distroless` repository: ```python # Create a passwd file with a nonroot user and uid. passwd_file( name = "nonroot", info = "nonroot", uid = 1002, username = "nonroot", ) # Include it in our base image as a tar. container_image( name = "passwd_image", base = "@go_image_base//image", tars = [":nonroot.passwd.tar"], user = "nonroot", ) # Simple go program to print out the username and uid. go_image( name = "user", srcs = ["user.go"], # Override the base image. base = ":passwd_image", ) ``` ### java_image To use `java_image`, add the following to `WORKSPACE`: ```python load( "@io_bazel_rules_docker//java:image.bzl", _java_image_repos = "repositories", ) _java_image_repos() ``` Then in your `BUILD` file, simply rewrite `java_binary` to `java_image` with the following import: ```python load("@io_bazel_rules_docker//java:image.bzl", "java_image") java_image( name = "java_image", srcs = ["Binary.java"], # Put these runfiles into their own layer. layers = [":java_image_library"], main_class = "examples.images.Binary", ) ``` ### war_image To use `war_image`, add the following to `WORKSPACE`: ```python load( "@io_bazel_rules_docker//java:image.bzl", _java_image_repos = "repositories", ) _java_image_repos() ``` Then in your `BUILD` file, simply rewrite `java_war` to `war_image` with the following import: ```python load("@io_bazel_rules_docker//java:image.bzl", "war_image") war_image( name = "war_image", srcs = ["Servlet.java"], # Put these JARs into their own layers. layers = [ ":java_image_library", "@javax_servlet_api//jar:jar", ], ) ``` ### scala_image To use `scala_image`, add the following to `WORKSPACE`: ```python # You *must* import the Scala rules before setting up the scala_image rules. git_repository( name = "io_bazel_rules_scala", commit = "{HEAD}", remote = "https://github.com/bazelbuild/rules_scala.git", ) load("@io_bazel_rules_scala//scala:scala.bzl", "scala_repositories") scala_repositories() load( "@io_bazel_rules_docker//scala:image.bzl", _scala_image_repos = "repositories", ) _scala_image_repos() ``` Then in your `BUILD` file, simply rewrite `scala_binary` to `scala_image` with the following import: ```python load("@io_bazel_rules_docker//scala:image.bzl", "scala_image") scala_image( name = "scala_image", srcs = ["Binary.scala"], main_class = "examples.images.Binary", ) ``` ### groovy_image To use `groovy_image`, add the following to `WORKSPACE`: ```python # You *must* import the Groovy rules before setting up the groovy_image rules. git_repository( name = "io_bazel_rules_groovy", commit = "{HEAD}", remote = "https://github.com/bazelbuild/rules_groovy.git", ) load("@io_bazel_rules_groovy//groovy:groovy.bzl", "groovy_repositories") groovy_repositories() load( "@io_bazel_rules_docker//groovy:image.bzl", _groovy_image_repos = "repositories", ) _groovy_image_repos() ``` Then in your `BUILD` file, simply rewrite `groovy_binary` to `groovy_image` with the following import: ```python load("@io_bazel_rules_docker//groovy:image.bzl", "groovy_image") groovy_image( name = "groovy_image", srcs = ["Binary.groovy"], main_class = "examples.images.Binary", ) ``` ### rust_image To use `rust_image`, add the following to `WORKSPACE`: ```python # You *must* import the Rust rules before setting up the rust_image rules. git_repository( name = "io_bazel_rules_rust", commit = "{HEAD}", remote = "https://github.com/bazelbuild/rules_rust.git", ) load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repositories") rust_repositories() load( "@io_bazel_rules_docker//rust:image.bzl", _rust_image_repos = "repositories", ) _rust_image_repos() ``` Then in your `BUILD` file, simply rewrite `rust_binary` to `rust_image` with the following import: ```python load("@io_bazel_rules_docker//rust:image.bzl", "rust_image") rust_image( name = "rust_image", srcs = ["main.rs"], ) ``` ### d_image To use `d_image`, add the following to `WORKSPACE`: ```python # You *must* import the D rules before setting up the d_image rules. git_repository( name = "io_bazel_rules_d", commit = "{HEAD}", remote = "https://github.com/bazelbuild/rules_d.git", ) load("@io_bazel_rules_d//d:d.bzl", "d_repositories") d_repositories() load( "@io_bazel_rules_docker//d:image.bzl", _d_image_repos = "repositories", ) _d_image_repos() ``` Then in your `BUILD` file, simply rewrite `d_binary` to `d_image` with the following import: ```python load("@io_bazel_rules_docker//d:image.bzl", "d_image") d_image( name = "d_image", srcs = ["main.d"], ) ``` ### container_bundle ```python container_bundle( name = "bundle", images = { # A set of images to bundle up into a single tarball. "gcr.io/foo/bar:bazz": ":app", "gcr.io/foo/bar:blah": "//my:sidecar", "gcr.io/foo/bar:booo": "@your//random:image", } ) ``` ### container_pull In `WORKSPACE`: ```python container_pull( name = "base", registry = "gcr.io", repository = "my-project/my-base", # 'tag' is also supported, but digest is encouraged for reproducibility. digest = "sha256:deadbeef", ) ``` This can then be referenced in `BUILD` files as `@base//image`. ### container_push This target pushes on `bazel run :push_foo`: ``` python container_push( name = "push_foo", image = ":foo", format = "Docker", registry = "gcr.io", repository = "my-project/my-image", tag = "dev", ) ``` We also support the `docker_push` (from `docker/docker.bzl`) and `oci_push` (from `oci/oci.bzl`) aliases, which bake in the `format = "..."` attribute. ### container_pull (DockerHub) In `WORKSPACE`: ```python container_pull( name = "official_ubuntu", registry = "index.docker.io", repository = "library/ubuntu", tag = "14.04", ) ``` This can then be referenced in `BUILD` files as `@official_ubuntu//image`. ### container_pull (Quay.io) In `WORKSPACE`: ```python container_pull( name = "etcd", registry = "quay.io", repository = "coreos/etcd", tag = "latest", ) ``` This can then be referenced in `BUILD` files as `@etcd//image`. ### container_pull (Bintray.io) In `WORKSPACE`: ```python container_pull( name = "artifactory", registry = "docker.bintray.io", repository = "jfrog/artifactory-pro", ) ``` This can then be referenced in `BUILD` files as `@artifactory//image`. ### container_pull (Gitlab) In `WORKSPACE`: ```python container_pull( name = "gitlab", registry = "registry.gitlab.com", repository = "username/project/image", tag = "tag", ) ``` This can then be referenced in `BUILD` files as `@gitlab//image`. **NOTE:** This will only work on systems with Python >2.7.6 ## Updating the `distroless` base images. The digest references to the `distroless` base images must be updated over time to pick up bug fixes and security patches. To facilitate this, the files containing the digest references are generated by `tools/update_deps.py`. To update all of the dependencies, please run (from the root of the repository): ```shell ./update_deps.sh ``` Image references should not be update individually because these images have shared layers and letting them diverge could result in sub-optimal push and pull performance. ## container_pull ```python container_pull(name, registry, repository, digest, tag) ``` A repository rule that pulls down a Docker base image in a manner suitable for use with `container_image`'s `base` attribute.
Attributes | |
---|---|
name |
Unique name for this repository rule. |
registry |
The registry from which to pull the base image. |
repository |
The `repository` of images to pull from. |
digest |
The `digest` of the Docker image to pull from the specified `repository`. Note: For reproducible builds, use of `digest` is recommended. |
tag |
The `tag` of the Docker image to pull from the specified `repository`. If neither this nor `digest` is specified, this attribute defaults to `latest`. If both are specified, then `tag` is ignored. Note: For reproducible builds, use of `digest` is recommended. |
Attributes | |
---|---|
name |
Unique name for this rule. |
format |
The desired format of the published image. Currently, this supports
|
image |
The label containing a Docker image to publish. |
registry |
The registry to which to publish the image. This field supports stamp variables. |
repository |
The `repository` of images to which to push. This field supports stamp variables. |
tag |
The `tag` of the Docker image to push to the specified `repository`. This attribute defaults to `latest`. This field supports stamp variables. |
stamp |
If true, enable use of workspace status variables
(e.g. These fields are specified in the tag using using Python format
syntax, e.g.
|
Implicit output targets | |
---|---|
name.tar |
The full Docker image
A full Docker image containing all the layers, identical to
what |
name-layer.tar |
An image of the current layer
A Docker image containing only the layer corresponding to that target. It is used for incremental loading of the layer. Note: this target is not suitable for direct consumption. It is used for incremental loading and non-docker rules should depends on the Docker image (name.tar) instead. |
name |
Incremental image loader
The incremental image loader. It will load only changed layers inside the Docker registry. |
Attributes | |
---|---|
name |
Name, required
A unique name for this rule. |
base |
File, optional
The base layers on top of which to overlay this layer, equivalent to FROM. |
data_path |
String, optional
Root path of the files. The directory structure from the files is preserved inside the Docker image, but a prefix path determined by `data_path` is removed from the directory structure. This path can be absolute from the workspace root if starting with a `/` or relative to the rule's directory. A relative path may starts with "./" (or be ".") but cannot use go up with "..". By default, the `data_path` attribute is unused, and all files should have no prefix. |
directory |
String, optional
Target directory. The directory in which to expand the specified files, defaulting to '/'. Only makes sense accompanying one of files/tars/debs. |
files |
List of files, optional
File to add to the layer. A list of files that should be included in the Docker image. |
legacy_repository_naming |
Bool, default to False
Whether to use the legacy strategy for setting the repository name
embedded in the resulting tarball.
e.g. |
mode |
String, default to 0555
Set the mode of files added by the |
tars |
List of files, optional
Tar file to extract in the layer. A list of tar files whose content should be in the Docker image. |
debs |
List of files, optional
Debian package to install. A list of debian packages that will be installed in the Docker image. |
symlinks |
Dictionary, optional
Symlinks to create in the Docker image.
|
user |
String, optional
The user that the image should run as. Because building the image never happens inside a Docker container, this user does not affect the other actions (e.g., adding files). This field supports stamp variables. |
entrypoint |
String or string list, optional
List of entrypoints to add in the image. This field supports stamp variables. |
cmd |
String or string list, optional
List of commands to execute in the image. This field supports stamp variables. |
env |
Dictionary from strings to strings, optional
Dictionary from environment variable names to their values when running the Docker image.
The values of this field support stamp variables. |
labels |
Dictionary from strings to strings, optional
The values of this field support stamp variables. |
ports |
String list, optional
|
volumes |
String list, optional
|
workdir |
String, optional
Initial working directory when running the Docker image. Because building the image never happens inside a Docker container, this working directory does not affect the other actions (e.g., adding files). This field supports stamp variables. |
repository |
String, default to `bazel`
The repository for the default tag for the image. Images generated by `container_image` are tagged by default to `bazel/package_name:target` for a `container_image` target at `//package/name:target`. Setting this attribute to `gcr.io/dummy` would set the default tag to `gcr.io/dummy/package_name:target`. |
stamp |
If true, enable use of workspace status variables
(e.g. These fields are specified in attributes using using Python format
syntax, e.g. |
Attributes | |
---|---|
name |
Unique name for this rule. |
images |
A collection of the images to save into the tarball. The keys are the tags with which to alias the image specified by the
value. These tags may contain make variables ( The values may be the output of |
stamp |
If true, enable use of workspace status variables
(e.g. These fields are specified in the tag using using Python format
syntax, e.g.
|
Attributes | |
---|---|
name |
Unique name for this rule. |
config |
A json configuration file containing the image's metadata. This appears in `docker save` tarballs as ` |
layers |
The list of layer |
Attributes | |
---|---|
name |
Unique name for this rule. |
file |
A label targetting a single file which is a compressed or uncompressed tar, as obtained through `docker save IMAGE`. |