These build rules are used for building Docker images. Such images are easy to modify and deploy system image for deploying application easily on cloud providers.
As traditional Dockerfile-based docker build
s effectively execute a series of commands inside of Docker containers, saving the intermediate results as layers; this approach is unsuitable for use in Bazel for a variety of reasons.
The docker_build rule constructs a tarball that is compatible with docker save/load
, and creates a single layer out of each BUILD rule in the chain.
Consider the following BUILD file in //third_party/debian
:
load("@bazel_tools//tools/build_defs/docker:docker.bzl", "docker_build") filegroup( name = "ca_certificates", srcs = ["ca_certificates.deb"], ) # Example when you have all your dependencies in your repository. # We have an example on how to fetch them from the web later in this # document. filegroup( name = "openjdk-7-jre-headless", srcs = ["openjdk-7-jre-headless.deb"], ) docker_build( name = "wheezy", tars = ["wheezy.tar"], )
The wheezy
target in that BUILD file roughly corresponds to the Dockerfile:
FROM scratch ADD wheezy.tar /
You can then build up subsequent layers via:
docker_build( name = "base", base = "//third_party/debian:wheezy", debs = ["//third_party/debian:ca_certificates"], ) docker_build( name = "java", base = ":base", debs = ["//third_party/debian:openjdk-7-jre-headless"], )
You can set image configuration on these same rules by simply adding (supported) arguments to the rule, for instance:
docker_build( name = "my-layer", entrypoint = ["foo", "bar", "baz"], ... )
Will have a similar effect as the Dockerfile construct:
ENTRYPOINT ["foo", "bar", "baz"]
For the set of supported configuration options see here
Suppose you have a docker_build
target //my/image:helloworld
:
docker_build( name = "helloworld", ... )
You can build this with bazel build my/image:helloworld.tar
. This will produce the file bazel-genfiles/my/image/helloworld.tar
. You can load this into my local Docker client by running docker load -i bazel-genfiles/my/image/helloworld.tar
, or simply bazel run my/image:helloworld
(this last command only update the changed layers and thus is faster).
Upon success you should be able to run docker images
and see:
REPOSITORY TAG IMAGE ID ... bazel/my_image helloworld d3440d7f2bde ...
You can now use this docker image with the name bazel/my_image:helloworld
or tag it with another name, for example: docker tag bazel/my_image:helloworld gcr.io/my-project/my-awesome-image:v0.9
You can do all that at once with specifying the tag on the command line of bazel run
:
bazel run my/image:helloworld gcr.io/my-project/my-awesome-image:v0.9
Nota Bene: the docker images
command will show a really old timestamp because docker_build
removes all timestamps from the build to make it reproducible.
If you do not want to check in base image in your repository, you can use external repositories. For instance, you could create various layer with external
labels:
load("@bazel_tools//tools/build_defs/docker:docker.bzl", "docker_build") docker_build( name = "java", base = "@docker_debian//:wheezy", debs = ["@openjdk_7_jre_headless//file"], )
Using the WORKSPACE file to add the actual files:
new_http_archive( name = "docker_debian", url = "https://codeload.github.com/tianon/docker-brew-debian/zip/e9bafb113f432c48c7e86c616424cb4b2f2c7a51", build_file = "debian.BUILD", type = "zip", sha256 = "515d385777643ef184729375bc5cb996134b3c1dc15c53acf104749b37334f68", ) http_file( name = "openjdk_7_jre_headless", url = "http://security.debian.org/debian-security/pool/updates/main/o/openjdk-7/openjdk-7-jre-headless_7u79-2.5.5-1~deb7u1_amd64.deb", sha256 = "b632f0864450161d475c012dcfcc37a1243d9ebf7ff9d6292150955616d71c23", )
With the following debian.BUILD
file:
load("@bazel_tools//tools/build_defs/docker:docker.bzl", "docker_build") # Extract .xz files genrule( name = "wheezy_tar", srcs = ["docker-brew-debian-e9bafb113f432c48c7e86c616424cb4b2f2c7a51/wheezy/rootfs.tar.xz"], outs = ["wheezy_tar.tar"], cmd = "cat $< | xzcat >$@", ) docker_build( name = "wheezy", tars = [":wheezy_tar"], visibility = ["//visibility:public"], )
In the future, we would like to provide better integration with docker repositories: pull and push docker image.
docker_build(name, base, data_path, directory, files, legacy_repository_naming, mode, tars, debs, symlinks, entrypoint, cmd, env, labels, ports, volumes, workdir, repository)