Build Docker images
Prysm has no Dockerfile. Bazel builds the container images straight from the compiled binaries with rules_oci, through the prysm_image_upload macro in tools/prysm_image.bzl. Build an image when you want to run your change in Docker or in a devnet.
Before you begin
- The Build with Bazel quickstart works on your machine.
- Docker (or Podman) installed and running.
bazel runon an image tarball; load it withdocker load, orpodman loadif Docker isn't installed.
Build and load an image
-
Build the images and load them into Docker.
--platformssets the Linux platform the binary is built for, so the image runs the same way whether you build on Linux or macOS. Pick the one that matches the machine that will run the container:- arm64
- amd64
For Apple Silicon Macs and other arm64 machines:
bazel run //cmd/beacon-chain:oci_image_tarball --platforms=@io_bazel_rules_go//go/toolchain:linux_arm64_cgobazel run //cmd/validator:oci_image_tarball --platforms=@io_bazel_rules_go//go/toolchain:linux_arm64_cgoFor x86-64 machines:
bazel run //cmd/beacon-chain:oci_image_tarball --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64_cgobazel run //cmd/validator:oci_image_tarball --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64_cgo -
Check that the image is in Docker:
docker image ls gcr.io/offchainlabs/prysm/beacon-chain -
Give it a local tag, so it can't be confused with the upstream
latestimage:docker tag gcr.io/offchainlabs/prysm/beacon-chain:latest prysm-beacon-chain:localdocker tag gcr.io/offchainlabs/prysm/validator:latest prysm-validator:local
Add other build options the same way. For example, an optimized release image:
- arm64
- amd64
bazel run //cmd/beacon-chain:oci_image_tarball --config=release --platforms=@io_bazel_rules_go//go/toolchain:linux_arm64_cgo
bazel run //cmd/beacon-chain:oci_image_tarball --config=release --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64_cgo
To build the tarball without loading it, use bazel build instead of bazel run with the same target and --platforms. The file is at bazel-bin/cmd/beacon-chain/oci_image_tarball/tarball.tar, and you can load it later with:
docker load --input <FILE>
Image targets
cmd/beacon-chain, cmd/validator, and cmd/prysmctl each define the same targets:
| Target | What it builds |
|---|---|
:oci_image | The image, as an OCI layout, for the platform set with --platforms. |
:oci_image_tarball | A tarball of :oci_image; bazel run loads it. |
:oci_image_tarball_e2e | A tarball of the image built for Linux on the host's CPU (linux/amd64 or linux/arm64); bazel run loads it. The Kurtosis end-to-end test uses it. |
:oci_image_index | A multi-arch image index for linux/amd64 and linux/arm64. |
:push_images | Pushes :oci_image_index to a registry. |
The tarballs are tagged latest in these repositories:
| Package | Tag |
|---|---|
//cmd/beacon-chain | gcr.io/offchainlabs/prysm/beacon-chain:latest |
//cmd/validator | gcr.io/offchainlabs/prysm/validator:latest |
//cmd/prysmctl | gcr.io/offchainlabs/prysm/cmd/prysmctl:latest |
What's in the image
- A distroless Debian 11 base with the C runtime (
gcr.io/prysmaticlabs/distroless/cc-debian11, pinned by digest inWORKSPACE), plusbashandcoreutils. - An
/etc/passwdwithroot(UID 0) andnonroot(UID 1001). The image doesn't set a user, so containers run as root unless you pass--user. - The binary is at
/beacon-chain,/validator, or/prysmctl, which is also the entrypoint. A symlink keeps the old path/app/cmd/<NAME>/<NAME>working.
Because the entrypoint is the binary, arguments to docker run go straight to it.
Build multi-arch images
:oci_image_index builds the binary once for each Linux platform and combines the two images into one index. The Linux C toolchain is hermetic, so you don't need a cross-compiler:
bazel build --config=release //cmd/beacon-chain:oci_image_index
To publish it, push to a registry you control. :push_images defaults to the gcr.io/offchainlabs/prysm/… repository, so override it and set a tag:
bazel run --config=release //cmd/beacon-chain:push_images -- \
--repository=<REGISTRY>/prysm-beacon-chain \
--tag=<TAG>
Replace <REGISTRY> with your registry and namespace, for example ghcr.io/<YOUR_USER>. Log in first:
docker login
Check that it works
docker run --rm prysm-beacon-chain:local --version
docker run --rm prysm-validator:local --version
Each prints the version string of your build.
Troubleshooting
The container stops right after it starts with:
exec format error
The image was built for the other CPU architecture, or without --platforms on macOS (which puts a macOS binary into a Linux image). Rebuild with the --platforms value that matches the machine running the container.
bazel run on a tarball target fails with:
Neither docker or podman could be found.
It needs one of them on your PATH.
The container runs an old build. A runtime that pulls images may prefer the registry's …:latest over yours. Use the local tag from step 3, and compare image IDs with:
docker image ls