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 builds 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:
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 layer metadata 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 metadata, and ways to construct layers, 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. 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.
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
Nota Bene: the docker images command will show a really old timestamp because docker_build remove 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("/tools/build_defs/docker/docker", "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("/tools/build_defs/docker/docker", "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"], )
docker_builddocker_build(name, base, data_path, directory, files, tars, debs, symlinks, entrypoint, cmd, env, ports, volumes)
In the future, we would like to provide better integration with docker repositories: pull and push docker image.