Files
node/scripts/build_image.sh
T

124 lines
5.5 KiB
Bash
Raw Normal View History

#!/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