Skip to content

Rules for building and handling Docker images with Bazel

License

Notifications You must be signed in to change notification settings

drigz/rules_docker

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bazel Docker Rules

Travis CI Bazel CI
Build Status Build Status

Rules

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 Docker builds, the Docker images produced by docker_build are deterministic / reproducible.

NOTE: docker_push and docker_pull make use of google/containerregistry for registry interactions.

Setup

Add the following to your WORKSPACE file to add the external repositories:

git_repository(
    name = "io_bazel_rules_docker",
    remote = "https://github.com/bazelbuild/rules_docker.git",
    tag = "v0.1.0",
)

load(
  "@io_bazel_rules_docker//docker:docker.bzl",
  "docker_repositories", "docker_pull"
)
docker_repositories()

docker_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 docker_build target //my/image:helloworld:

docker_build(
    name = "helloworld",
    ...
)

You can load this into your local Docker client by running: bazel run my/image:helloworld.

Alternately, 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 docker_build and docker_bundle. For docker_build the image name will be bazel/my/image:helloworld. For docker_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 credential helper:

$ gcloud components install docker-credential-gcr

$ docker-credential-gcr configure-docker

Varying image names

A common request from folks using docker_push or docker_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.

# A common pattern when users want to avoid trampling
# on each other's images during development.
docker_push(
  name = "publish",

  # 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:

$ 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.

Make variables

The second option is to employ Makefile-style variables:

docker_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:

   bazel build --define project=blah //path/to:bundle

Examples

docker_build

docker_build(
    name = "app",
    # References docker_pull from WORKSPACE (above)
    base = "@java_base//image",
    files = ["//java/com/example/app:Hello_deploy.jar"],
    cmd = ["Hello_deploy.jar"]
)

docker_bundle

docker_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",
    }
)

docker_pull

In WORKSPACE:

docker_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.

docker_push

This target pushes on bazel run :push_foo:

docker_push(
   name = "push_foo",
   image = ":foo",
   registry = "gcr.io",
   repository = "my-project/my-image",
   tag = "dev",
)

docker_pull (DockerHub)

In WORKSPACE:

docker_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.

docker_pull (Quay.io)

In WORKSPACE:

docker_pull(
    name = "etcd",
    registry = "quay.io",
    repository = "coreos/etcd",
    tag = "latest",
)

This can then be referenced in BUILD files as @etcd//image.

docker_pull (Bintray.io)

In WORKSPACE:

docker_pull(
    name = "artifactory",
    registry = "docker.bintray.io",
    repository = "jfrog/artifactory-pro",
)

This can then be referenced in BUILD files as @artifactory//image.

docker_pull (Gitlab)

In WORKSPACE:

docker_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

docker_pull

docker_pull(name, registry, repository, digest, tag)

A repository rule that pulls down a Docker base image in a manner suitable for use with docker_build's base attribute.

Attributes
name

Name, required

Unique name for this repository rule.

registry

Registry Domain; required

The registry from which to pull the base image.

repository

Repository; required

The `repository` of images to pull from.

digest

string; optional

The `digest` of the Docker image to pull from the specified `repository`.

Note: For reproducible builds, use of `digest` is recommended.

tag

string; optional

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.

docker_push

docker_push(name, image, registry, repository, tag)

An executable rule that pushes a Docker image to a Docker registry on bazel run.

Attributes
name

Name, required

Unique name for this rule.

image

Label; required

The label containing a Docker image to publish.

registry

Registry Domain; required

The registry to which to publish the image.

repository

Repository; required

The `repository` of images to which to push.

tag

string; optional

The `tag` of the Docker image to push to the specified `repository`. This attribute defaults to `latest`.

stamp

Bool; optional

If true, enable use of workspace status variables (e.g. BUILD_USER, BUILD_EMBED_LABEL, and custom values set using --workspace_status_command) in tags.

These fields are specified in the tag using using Python format syntax, e.g. example.org/{BUILD_USER}/image:{BUILD_EMBED_LABEL}.

docker_build

docker_build(name, base, data_path, directory, files, legacy_repository_naming, mode, tars, debs, symlinks, entrypoint, cmd, env, labels, ports, volumes, workdir, repository)
Implicit output targets
name.tar The full Docker image

A full Docker image containing all the layers, identical to what docker save would return. This is only generated on demand.

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. bazel/{target.replace('/', '_')} vs. bazel/{target}

mode String, default to 0555

Set the mode of files added by the files attribute.

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.

symlinks = { "/path/to/link": "/path/to/target", ... },

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).

entrypoint String or string list, optional

List of entrypoints to add in the image.

cmd String or string list, optional

List of commands to execute in the image.

env Dictionary from strings to strings, optional

Dictionary from environment variable names to their values when running the Docker image.

env = { "FOO": "bar", ... },

labels Dictionary from strings to strings, optional

Dictionary from custom metadata names to their values. You can also put a file name prefixed by '@' as a value. Then the value is replaced with the contents of the file.

labels = { "com.example.foo": "bar", "com.example.baz": "@metadata.json", ... },

ports String list, optional

List of ports to expose.

volumes String list, optional

List of volumes to mount.

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).

repository String, default to `bazel`

The repository for the default tag for the image.

Images generated by `docker_build` are tagged by default to `bazel/package_name:target` for a `docker_build` target at `//package/name:target`. Setting this attribute to `gcr.io/dummy` would set the default tag to `gcr.io/dummy/package_name:target`.

docker_bundle

docker_bundle(name, images)

A rule that aliases and saves N images into a single docker save tarball.

Attributes
name

Name, required

Unique name for this rule.

images

Map of Tag to image Label; required

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 ($FOO), and if stamp is set to true, may also contain workspace status variables ({BAR}).

The values may be the output of docker_pull, docker_build, or a docker save tarball.

stamp

Bool; optional

If true, enable use of workspace status variables (e.g. BUILD_USER, BUILD_EMBED_LABEL, and custom values set using --workspace_status_command) in tags.

These fields are specified in the tag using using Python format syntax, e.g. example.org/{BUILD_USER}/image:{BUILD_EMBED_LABEL}.

docker_import

docker_import(name, config, layers)

A rule that imports a docker image into our intermediate form.

Attributes
name

Name, required

Unique name for this rule.

config

The v2.2 image's json configuration; required

A json configuration file containing the image's metadata.

This appears in `docker save` tarballs as `.json` and is referenced by `manifest.json` in the config field.

layers

The list of layer `.tar.gz`s; required

The list of layer `.tar.gz` files in the order they appear in the `config.json`'s layer section, or in the order that they appear in `docker save` tarballs' `manifest.json` `Layers` field (although these are gzipped).

About

Rules for building and handling Docker images with Bazel

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 68.1%
  • Shell 28.9%
  • Java 1.5%
  • C++ 1.1%
  • Go 0.4%