Dockerfile / docker build workflow. It is more reproducible, and much higher performance since individual layers can be built in parallel.
Build a container with a Go binary
The Go starter template includes support for OCI containers. When you runaspect gazelle you should see a go_image rule was automatically written in each BUILD file next to the go_binary target. Of course, it’s also possible to write this target by hand.
By default, go_image uses the base image from the Distroless project, to minimize dependencies and reduce your exposure to vulnerabilities. See the oci.pull call in MODULE.bazel.
bazel-out, as a directory following the OCI image layout specification:
Q. Why does it produce a folder rather than a .tar file?
A. This is because container images can be large, and when a Bazel action produces a large output, it will be stored in the remote cache. This causes expensive and slow network transfer, especially when a large number of image cache entries are invalidated by some code changes.
Running a local container
We’ll load the image data into a locally running daemon, like with Docker or Podman. Make sure you have a container daemon running, and maybe set theDOCKER_HOST environment variable so that it can be located by commands like docker load.
The go_image macro in our BUILD file expands to several targets, which you can inspect with bazel query. One is oci_load rule //cmd/hello:image.load which is executable, so we can load our image by running it.
docker or podman command like you’d use outside of Bazel, for example:
Pushing to a remote registry
To run the application in a remote environment like on a Cloud service, we’ll need to run apush command. The oci_push rule creates an executable target that can be used with bazel run. See https://github.com/bazel-contrib/rules_oci/blob/main/docs/push.md
However we would need credentials for a registry to perform a push, so this lesson doesn’t include that.
Continuous Delivery
Ideally ourgo_image should be pushed to the remote registry any time we’ve landed code changes that affect the binary. This way the developer workflow is simply to merge changes, then run a deployment command that promotes a binary built during CI. This is better than running a push command locally, because we are guaranteed that the container image is exactly the one that passed all the tests.
See Selective delivery for our recommended approach.
