Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docker image for example MorpheusVM #1915

Merged
merged 5 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.ci
.github
.gitignore
.golangci.yml

.idea
.vscode

LICENSE
*.md

# Ignore all dockerfiles not just the main one
Dockerfile*
13 changes: 13 additions & 0 deletions .github/workflows/hypersdk-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ jobs:
- shell: bash
run: scripts/tests.clean.sh

build_image:
Copy link

@maru-ava maru-ava Feb 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(No action required) Did you mean to add a publish script in addition to this CI test? That would be a likely precondition for performing kube-based scale testing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet, I didn't have permission to create a new DockerHub repo, so was blocked on this and just wanted to add some check to make sure this didn't break.

name: Image build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install qemu (required for cross-platform builds)
run: |
sudo apt update
sudo apt -y install qemu-system qemu-user-static
- name: Build MorpheusVM Docker Image
shell: bash
run: bash -x scripts/build_docker_image.sh
Copy link

@maru-ava maru-ava Feb 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend validating image build since, by itself, executing this script without error provides no guarantee of the viability of the images produced.

Example from avalanchego: https://github.com/ava-labs/avalanchego/blob/master/scripts/tests.build_image.sh


hypersdk-lint:
runs-on: ubuntu-latest
steps:
Expand Down
32 changes: 32 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# syntax=docker/dockerfile:experimental

# ============= Setting up base Stage ================
# AVALANCHEGO_NODE_IMAGE needs to identify an existing node image and should include the tag
ARG AVALANCHEGO_NODE_IMAGE
ARG VM_ID
ARG VM_COMMIT
ARG CURRENT_BRANCH

# ============= Compilation Stage ================
FROM --platform=$BUILDPLATFORM golang:1.22.8-bullseye AS builder
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifying BUILDPLATFORM here without enabling cross-compilation is unlikely to result in a viable image when TARGETPLATFORM differs. For example, when BUILDPLATFORM=arm64 and TARGETPLATFORM=amd64, the resulting image will contain an arm64 binary instead of the desired amd64 one.

Note also that there are two steps in enabling cross compilation:


WORKDIR /build

# Copy the code into the container
COPY . .

ARG VM_NAME

WORKDIR /build/examples/$VM_NAME/

# Ensure pre-existing builds are not available for inclusion in the final image
RUN [ -d ./build ] && rm -rf ./build/* || true

RUN export VM_COMMIT=$VM_COMMIT && export CURRENT_BRANCH=$CURRENT_BRANCH && ./scripts/build.sh /build/build/vm

# ============= Cleanup Stage ================
FROM $AVALANCHEGO_NODE_IMAGE AS builtImage

# Copy the evm binary into the correct location in the container
ARG VM_ID
COPY --from=builder /build/build/vm /avalanchego/build/plugins/$VM_ID
19 changes: 8 additions & 11 deletions examples/morpheusvm/scripts/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,34 @@ source ../../scripts/constants.sh
# shellcheck source=/scripts/common/utils.sh
source ../../scripts/common/utils.sh

VERSION=13c08681c17d0790a94ed8c8ef8a3c88f8bb196d

############################
# build avalanchego
# https://github.com/ava-labs/avalanchego/releases
HYPERSDK_DIR=$HOME/.hypersdk

echo "working directory: $HYPERSDK_DIR"

AVALANCHEGO_PATH=${HYPERSDK_DIR}/avalanchego-${VERSION}/avalanchego
AVALANCHEGO_PLUGIN_DIR=${HYPERSDK_DIR}/avalanchego-${VERSION}/plugins
AVALANCHEGO_PATH=${HYPERSDK_DIR}/avalanchego-${AVALANCHE_VERSION}/avalanchego
AVALANCHEGO_PLUGIN_DIR=${HYPERSDK_DIR}/avalanchego-${AVALANCHE_VERSION}/plugins

if [ ! -f "$AVALANCHEGO_PATH" ]; then
echo "building avalanchego"
CWD=$(pwd)

# Clear old folders
rm -rf "${HYPERSDK_DIR}"/avalanchego-"${VERSION}"
mkdir -p "${HYPERSDK_DIR}"/avalanchego-"${VERSION}"
rm -rf "${HYPERSDK_DIR}"/avalanchego-"${AVALANCHE_VERSION}"
mkdir -p "${HYPERSDK_DIR}"/avalanchego-"${AVALANCHE_VERSION}"
rm -rf "${HYPERSDK_DIR}"/avalanchego-src
mkdir -p "${HYPERSDK_DIR}"/avalanchego-src

# Download src
cd "${HYPERSDK_DIR}"/avalanchego-src
git clone https://github.com/ava-labs/avalanchego.git
cd avalanchego
git checkout "${VERSION}"
git checkout "${AVALANCHE_VERSION}"

# Build avalanchego
./scripts/build.sh
mv build/avalanchego "${HYPERSDK_DIR}"/avalanchego-"${VERSION}"
mv build/avalanchego "${HYPERSDK_DIR}"/avalanchego-"${AVALANCHE_VERSION}"

cd "${CWD}"

Expand All @@ -62,11 +59,11 @@ fi
echo "building morpheusvm"

# delete previous (if exists)
rm -f "${HYPERSDK_DIR}"/avalanchego-"${VERSION}"/plugins/qCNyZHrs3rZX458wPJXPJJypPf6w423A84jnfbdP2TPEmEE9u
rm -f "${HYPERSDK_DIR}"/avalanchego-"${AVALANCHE_VERSION}"/plugins/qCNyZHrs3rZX458wPJXPJJypPf6w423A84jnfbdP2TPEmEE9u

# rebuild with latest code
go build \
-o "${HYPERSDK_DIR}"/avalanchego-"${VERSION}"/plugins/qCNyZHrs3rZX458wPJXPJJypPf6w423A84jnfbdP2TPEmEE9u \
-o "${HYPERSDK_DIR}"/avalanchego-"${AVALANCHE_VERSION}"/plugins/qCNyZHrs3rZX458wPJXPJJypPf6w423A84jnfbdP2TPEmEE9u \
./cmd/morpheusvm

############################
Expand Down
79 changes: 79 additions & 0 deletions scripts/build_docker_image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env bash
# Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
# See the file LICENSE for licensing terms.

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:-}"

# The name of the VM to build. Defaults to build morpheusvm in examples/morpheusvm/
VM_NAME=${VM_NAME:-"morpheusvm"}

# Directory above this script
HYPERSDK_PATH=$(
cd "$(dirname "${BASH_SOURCE[0]}")"
cd .. && pwd
)
VM_PATH=${VM_PATH:-"${HYPERSDK_PATH}/examples/${VM_NAME}"}

# Load the constants
source "$HYPERSDK_PATH"/scripts/constants.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
DOCKERHUB_TAG="${VM_ID}-${DOCKERHUB_TAG}"
fi

# Default to the release image. Will need to be overridden when testing against unreleased versions.
AVALANCHEGO_NODE_IMAGE="${AVALANCHEGO_NODE_IMAGE:-${AVALANCHEGO_IMAGE_NAME}:${AVALANCHE_DOCKER_VERSION}}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(No action required) Maybe support building the avalanchego image for an as-yet unmerged hash as per the example of https://github.com/ava-labs/subnet-evm/blob/master/scripts/build_antithesis_images.sh#L24?


echo "Building Docker Image: $DOCKERHUB_REPO:$BUILD_IMAGE_ID based off AvalancheGo@$AVALANCHE_DOCKER_VERSION"
${DOCKER_CMD} -t "$DOCKERHUB_REPO:$BUILD_IMAGE_ID" \
"$HYPERSDK_PATH" -f "$HYPERSDK_PATH/Dockerfile" \
--build-arg AVALANCHEGO_NODE_IMAGE="$AVALANCHEGO_NODE_IMAGE" \
--build-arg VM_COMMIT="$VM_COMMIT" \
--build-arg CURRENT_BRANCH="$CURRENT_BRANCH" \
--build-arg VM_ID="$VM_ID" \
--build-arg VM_NAME="$VM_NAME"

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
44 changes: 42 additions & 2 deletions scripts/constants.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,50 @@
#!/usr/bin/env bash
# Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
# See the file LICENSE for licensing terms.
# Ignore warnings about variables appearing unused since this file is not the consumer of the variables it defines.
# shellcheck disable=SC2034

set -euo pipefail

AVALANCHE_VERSION=${AVALANCHE_VERSION:-'13c08681c17d0790a94ed8c8ef8a3c88f8bb196d'}
# Optionally specify a separate version of AvalancheGo for building docker images
# Added to support the case there's no such docker image for the specified commit of AvalancheGo
AVALANCHE_DOCKER_VERSION=${AVALANCHE_DOCKER_VERSION:-'v1.12.2'}

# Set the PATHS
GOPATH="$(go env GOPATH)"
DEFAULT_VM_ID="pkEmJQuTUic3dxzg8EYnktwn4W7uCHofNcwiYo458vodAUbY7"

# Avalabs docker hub
# avaplatform/avalanchego - defaults to local as to avoid unintentional pushes
# You should probably set it - export DOCKER_REPO='avaplatform/subnet-evm'
DOCKERHUB_REPO=${DOCKER_REPO:-"morpheusvm"}

# Shared between ./scripts/build_docker_image.sh
AVALANCHEGO_IMAGE_NAME="${AVALANCHEGO_IMAGE_NAME:-avaplatform/avalanchego}"

# set git constants if available, otherwise set to empty string (say building from a release)
if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(No action required) Maybe follow the example of ava-labs/avalanchego#3660 to enable building the images in a non-primary worktree?

# Current branch
CURRENT_BRANCH=${CURRENT_BRANCH:-$(git describe --tags --exact-match 2>/dev/null || git symbolic-ref -q --short HEAD || git rev-parse --short HEAD || :)}

# Image build id
#
# Use an abbreviated version of the full commit to tag the image.
# WARNING: this will use the most recent commit even if there are un-committed changes present
VM_COMMIT="$(git rev-parse HEAD || :)"
else
CURRENT_BRANCH=""
VM_COMMIT=""
fi

# Shared between ./scripts/build_docker_image.sh
DOCKERHUB_TAG=${VM_COMMIT::8}

echo "Using branch: ${CURRENT_BRANCH}"

# Set the CGO flags to use the portable version of BLST
#
# We use "export" here instead of just setting a bash variable because we need
# to pass this flag to all child processes spawned by the shell.

export CGO_CFLAGS="-O -D__BLST_PORTABLE__"
export CGO_CFLAGS="-O2 -D__BLST_PORTABLE__"
Loading