#!/usr/bin/env bash set -euo pipefail # e.g., # ./scripts/build_image.sh # Build local single-arch image # ./scripts/build_image.sh --no-cache # All arguments are provided to `docker buildx build` # SKIP_BUILD_RACE=1 ./scripts/build_image.sh # Build local single-arch image but skip building -r image # DOCKER_IMAGE=mynode ./scripts/build_image.sh # Build local single arch image with a custom image name # DOCKER_IMAGE=avaplatform/node ./scripts/build_image.sh # Build and push multi-arch image to docker hub # DOCKER_IMAGE=localhost:5001/node ./scripts/build_image.sh # Build and push multi-arch image to private registry # DOCKER_IMAGE=localhost:5001/node FORCE_TAG_LATEST=1 ./scripts/build_image.sh # Build and push image to private registry with tag `latest` # Multi-arch builds require Docker Buildx and QEMU. buildx should be enabled by # default in the version of docker included with Ubuntu 22.04, and qemu can be # installed as follows: # # sudo apt-get install qemu qemu-user-static # # After installing qemu, it will also be necessary to start a new builder that # supports multiplatform builds and can use the host's network: # # docker buildx create --use --driver-opt network=host # # Without `network=host`, the builder will timeout running `go mod download`. # # Reference: https://docs.docker.com/buildx/working-with-buildx/ # Directory above this script NODE_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd ) # Skip building the race image SKIP_BUILD_RACE="${SKIP_BUILD_RACE:-}" # Force tagging as latest even if not the master branch FORCE_TAG_LATEST="${FORCE_TAG_LATEST:-}" # Load the constants source "$NODE_PATH"/scripts/constants.sh source "$NODE_PATH"/scripts/git_commit.sh source "$NODE_PATH"/scripts/image_tag.sh if [[ -z "${SKIP_BUILD_RACE}" && $image_tag == *"-r" ]]; then echo "Branch name must not end in '-r'" exit 1 fi # The published name should be 'luxfi/node', but to avoid unintentional # pushes it is defaulted to 'node' (without a repo or registry name) which can # only be used to create local images. DOCKER_IMAGE="${DOCKER_IMAGE:-node}" # If set to non-empty, prompts the building of a multi-arch image when the image # name indicates use of a registry. # # A registry is required to build a multi-arch image since a multi-arch image is # not really an image at all. A multi-arch image (also called a manifest) is # basically a list of arch-specific images available from the same registry that # hosts the manifest. Manifests are not supported for local images. # # Reference: https://docs.docker.com/build/building/multi-platform/ BUILD_MULTI_ARCH="${BUILD_MULTI_ARCH:-}" # buildx (BuildKit) improves the speed and UI of builds over the legacy builder and # simplifies creation of multi-arch images. # # Reference: https://docs.docker.com/build/buildkit/ DOCKER_CMD="docker buildx build ${*}" # The dockerfile doesn't specify the golang version to minimize the # changes required to bump the version. Instead, the golang version is # provided as an argument. GO_VERSION="$(go list -m -f '{{.GoVersion}}')" DOCKER_CMD="${DOCKER_CMD} --build-arg GO_VERSION=${GO_VERSION}" # Provide the git commit as a build argument to avoid requiring this # to be discovered within the image. This enables image builds from # git worktrees since a non-primary worktree won't have a .git # directory to copy into the image. DOCKER_CMD="${DOCKER_CMD} --build-arg LUXD_COMMIT=${git_commit}" if [[ "${DOCKER_IMAGE}" == *"/"* ]]; then # Default to pushing when the image name includes a slash which indicates the # use of a registry e.g. # # - dockerhub: [repo]/[image name]:[tag] # - private registry: [private registry hostname]/[image name]:[tag] DOCKER_CMD="${DOCKER_CMD} --push" # Build a multi-arch image if requested if [[ -n "${BUILD_MULTI_ARCH}" ]]; then DOCKER_CMD="${DOCKER_CMD} --platform=${PLATFORMS:-linux/amd64,linux/arm64}" fi # A populated DOCKER_USERNAME env var triggers login if [[ -n "${DOCKER_USERNAME:-}" ]]; then echo "$DOCKER_PASS" | docker login --username "$DOCKER_USERNAME" --password-stdin fi else # Build a single-arch image since the image name does not include a slash which # indicates that a registry is not available. # # Building a single-arch image with buildx and having the resulting image show up # in the local store of docker images (ala 'docker build') requires explicitly # loading it from the buildx store with '--load'. DOCKER_CMD="${DOCKER_CMD} --load" fi echo "Building Docker Image with tags: $DOCKER_IMAGE:$commit_hash , $DOCKER_IMAGE:$image_tag" ${DOCKER_CMD} -t "$DOCKER_IMAGE:$commit_hash" -t "$DOCKER_IMAGE:$image_tag" \ "$NODE_PATH" -f "$NODE_PATH/Dockerfile" if [[ -z "${SKIP_BUILD_RACE}" ]]; then echo "Building Docker Image with tags (race detector): $DOCKER_IMAGE:$commit_hash-r , $DOCKER_IMAGE:$image_tag-r" ${DOCKER_CMD} --build-arg="RACE_FLAG=-r" -t "$DOCKER_IMAGE:$commit_hash-r" -t "$DOCKER_IMAGE:$image_tag-r" \ "$NODE_PATH" -f "$NODE_PATH/Dockerfile" fi # Only tag the latest image for the master branch when images are pushed to a registry if [[ "${DOCKER_IMAGE}" == *"/"* && ($image_tag == "master" || -n "${FORCE_TAG_LATEST}") ]]; then echo "Tagging current node images as $DOCKER_IMAGE:latest" docker buildx imagetools create -t "$DOCKER_IMAGE:latest" "$DOCKER_IMAGE:$commit_hash" fi