diff --git a/.github/workflows/publish_docker.yml b/.github/workflows/publish_docker.yml index 5a16349cf5..d1764edc66 100644 --- a/.github/workflows/publish_docker.yml +++ b/.github/workflows/publish_docker.yml @@ -17,13 +17,17 @@ on: jobs: publish_docker_image: - name: Publish Docker Image - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Publish image to Dockerhub + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + - name: Build and publish images to DockerHub env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASS: ${{ secrets.DOCKER_PASS }} DOCKER_REPO: "avaplatform/subnet-evm" - run: .github/workflows/publish_docker_image.sh ${{ inputs.vm_id }} + VM_ID: ${{ inputs.vm_id }} + PUBLISH: 1 + PLATFORMS: "linux/amd64,linux/arm64" + run: scripts/build_docker_image.sh diff --git a/.github/workflows/publish_docker_image.sh b/.github/workflows/publish_docker_image.sh deleted file mode 100755 index 71bce26c12..0000000000 --- a/.github/workflows/publish_docker_image.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -# If this is not a trusted build (Docker Credentials are not set) -if [[ -z "$DOCKER_USERNAME" ]]; then - exit 0; -fi - -# Avalanche root directory -SUBNET_EVM_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd ../.. && pwd ) - -# Load the versions -source "$SUBNET_EVM_PATH"/scripts/versions.sh - -# Set the vm id if provided -if [[ $# -eq 1 ]]; then - VM_ID=$1 -fi - -# Buld the docker image -source "$SUBNET_EVM_PATH"/scripts/build_docker_image.sh - -if [[ $CURRENT_BRANCH == "master" ]]; then - echo "Tagging current image as $DOCKERHUB_REPO:latest" - docker tag "$DOCKERHUB_REPO:$BUILD_IMAGE_ID" "$DOCKERHUB_REPO:latest" -fi - -echo "Pushing $DOCKERHUB_REPO:$BUILD_IMAGE_ID" - -echo "$DOCKER_PASS" | docker login --username "$DOCKER_USERNAME" --password-stdin - -docker push -a "$DOCKERHUB_REPO" diff --git a/scripts/build_docker_image.sh b/scripts/build_docker_image.sh index 9de30cd7e7..93474e4a36 100755 --- a/scripts/build_docker_image.sh +++ b/scripts/build_docker_image.sh @@ -2,8 +2,25 @@ set -euo pipefail +# 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/ +PLATFORMS="${PLATFORMS:-}" + +# If set to non-empty, the image will be published to the registry. +PUBLISH="${PUBLISH:-}" + # Directory above this script -SUBNET_EVM_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd ) +SUBNET_EVM_PATH=$( + cd "$(dirname "${BASH_SOURCE[0]}")" + cd .. && pwd +) # Load the constants source "$SUBNET_EVM_PATH"/scripts/constants.sh @@ -14,8 +31,30 @@ source "$SUBNET_EVM_PATH"/scripts/versions.sh # WARNING: this will use the most recent commit even if there are un-committed changes present BUILD_IMAGE_ID=${BUILD_IMAGE_ID:-"${CURRENT_BRANCH}"} +# 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" + +if [[ -n "${PUBLISH}" ]]; then + DOCKER_CMD="${DOCKER_CMD} --push" + + echo "Pushing $DOCKERHUB_REPO:$BUILD_IMAGE_ID" + + # A populated DOCKER_USERNAME env var triggers login + if [[ -n "${DOCKER_USERNAME:-}" ]]; then + echo "$DOCKER_PASS" | docker login --username "$DOCKER_USERNAME" --password-stdin + fi +fi + +# Build a multi-arch image if requested +if [[ -n "${PLATFORMS}" ]]; then + DOCKER_CMD="${DOCKER_CMD} --platform=${PLATFORMS}" +fi + VM_ID=${VM_ID:-"${DEFAULT_VM_ID}"} -if [[ "${VM_ID}" != "${DEFAULT_VM_ID}" ]]; then +if [[ "${VM_ID}" != "${DEFAULT_VM_ID}" ]]; then DOCKERHUB_TAG="${VM_ID}-${DOCKERHUB_TAG}" fi @@ -23,9 +62,14 @@ fi AVALANCHEGO_NODE_IMAGE="${AVALANCHEGO_NODE_IMAGE:-${AVALANCHEGO_IMAGE_NAME}:${AVALANCHE_VERSION}}" echo "Building Docker Image: $DOCKERHUB_REPO:$BUILD_IMAGE_ID based of AvalancheGo@$AVALANCHE_VERSION" -docker build -t "$DOCKERHUB_REPO:$BUILD_IMAGE_ID" -t "$DOCKERHUB_REPO:${DOCKERHUB_TAG}" \ - "$SUBNET_EVM_PATH" -f "$SUBNET_EVM_PATH/Dockerfile" \ +${DOCKER_CMD} -t "$DOCKERHUB_REPO:$BUILD_IMAGE_ID" -t "$DOCKERHUB_REPO:${DOCKERHUB_TAG}" \ + "$SUBNET_EVM_PATH" -f "$SUBNET_EVM_PATH/Dockerfile" \ --build-arg AVALANCHEGO_NODE_IMAGE="$AVALANCHEGO_NODE_IMAGE" \ --build-arg SUBNET_EVM_COMMIT="$SUBNET_EVM_COMMIT" \ --build-arg CURRENT_BRANCH="$CURRENT_BRANCH" \ --build-arg VM_ID="$VM_ID" + +if [[ -n "${PUBLISH}" && $CURRENT_BRANCH == "master" ]]; then + echo "Tagging current image as $DOCKERHUB_REPO:latest" + docker buildx imagetools create -t "$DOCKERHUB_REPO:latest" "$DOCKERHUB_REPO:$BUILD_IMAGE_ID" +fi