diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..3922cff11 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +**/* +!rust-toolchain.toml +!Cargo.toml +!Cargo.lock +!.cargo +!crates +!depversions.sh +!.git +.git/hooks/**/* +.git/info/**/* +.git/logs/**/* diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 772790d63..d3822aaef 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -26,12 +26,51 @@ jobs: uses: actions/checkout@v6 timeout-minutes: 5 - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 + - name: Docker meta for humanode-peer + id: meta-humanode-peer + uses: docker/metadata-action@v6 with: + bake-target: docker-metadata-action-humanode-peer images: | ghcr.io/${{ github.repository }} + labels: | + org.opencontainers.image.title=${{ github.repository }}-humanode-peer + tags: | + type=schedule + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + + - name: Docker meta for robonode-server + id: meta-robonode-server + uses: docker/metadata-action@v6 + with: + bake-target: docker-metadata-action-robonode-server + images: | + ghcr.io/${{ github.repository }}/robonode-server + labels: | + org.opencontainers.image.title=${{ github.repository }}-robonode-server + tags: | + type=schedule + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + + - name: Docker meta for robonode-keygen + id: meta-robonode-keygen + uses: docker/metadata-action@v6 + with: + bake-target: docker-metadata-action-robonode-keygen + images: | + ghcr.io/${{ github.repository }}/robonode-keygen + labels: | + org.opencontainers.image.title=${{ github.repository }}-robonode-keygen tags: | type=schedule type=ref,event=branch @@ -42,36 +81,27 @@ jobs: type=sha - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to GitHub Container Registry if: github.event_name != 'pull_request' - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Cache code build - uses: actions/cache@v5 + - name: Build and push + uses: docker/bake-action@v7 with: - path: | - target/docker/*/*/rustup/ - !target/docker/*/*/rustup/tmp/ - !target/docker/*/*/rustup/downloads/ - target/docker/*/*/cargo/bin/ - target/docker/*/*/cargo/registry/index/ - target/docker/*/*/cargo/registry/cache/ - target/docker/*/*/cargo/git/db/ - target/docker/*/*/target/ - key: docker-cargo-${{ hashFiles('rust-toolchain.toml', 'Cargo.lock', 'docker/Dockerfile.*', 'docker/build.sh') }} - - - name: Build the code and docker image - run: docker/build.sh - - - name: Tag and push - if: github.event_name != 'pull_request' - run: | - xargs docker/tag-and-push.sh humanode <>~/.ssh/known_hosts + +FROM ${RUNTIME_BASE} AS runtime + +RUN apt-get update \ + && apt-get install -y \ + libssl3 \ + ca-certificates \ + jq \ + curl \ + && rm -rf /var/lib/apt/lists/* + +FROM builder AS build + +WORKDIR /worktree + +# Install rust. +RUN \ + --mount=type=bind,target=rust-toolchain.toml,source=rust-toolchain.toml \ + --mount=type=cache,target=/usr/local/rustup \ + rustup install + +# Build the binaries. +RUN \ + --mount=type=bind,target=.,readwrite \ + --mount=type=cache,target=/usr/local/rustup \ + --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=target \ + --mount=type=ssh \ + RUST_BACKTRACE=1 \ + CARGO_TARGET_DIR=target/artifacts \ + cargo build --release --locked --workspace + +# Copy artifacts. +RUN \ + --mount=type=cache,target=target \ + cp -r target/artifacts /artifacts \ + && ls -la /artifacts + +FROM runtime AS robonode-server +COPY --from=build /artifacts/release/robonode-server /usr/local/bin +RUN ldd /usr/local/bin/robonode-server +CMD ["robonode-server"] + +FROM runtime AS robonode-keygen +COPY --from=build /artifacts/release/robonode-keygen /usr/local/bin +RUN ldd /usr/local/bin/robonode-keygen +CMD ["robonode-keygen"] + +# Keep the peer last as the default target. +FROM runtime AS humanode-peer +COPY --from=build /artifacts/release/humanode-peer /usr/local/bin +RUN ldd /usr/local/bin/humanode-peer +CMD ["humanode-peer"] diff --git a/docker-bake.hcl b/docker-bake.hcl new file mode 100644 index 000000000..6b5a97311 --- /dev/null +++ b/docker-bake.hcl @@ -0,0 +1,31 @@ +variable "TARGETS" { + type = list(string) + default = ["humanode-peer", "robonode-server", "robonode-keygen"] +} + +group "default" { + targets = TARGETS +} + +target "base" { + dockerfile = "Dockerfile" + # ssh = ["default"] +} + +target "main" { + matrix = { + tgt = TARGETS + } + name = tgt + inherits = ["base", "docker-metadata-action-${tgt}"] + target = tgt +} + +# Targets to allow injecting customizations from Github Actions. + +target "docker-metadata-action" { + matrix = { + tgt = TARGETS + } + name = "docker-metadata-action-${tgt}" +} diff --git a/docker/Dockerfile.builder b/docker/Dockerfile.builder deleted file mode 100644 index e541dc63f..000000000 --- a/docker/Dockerfile.builder +++ /dev/null @@ -1,17 +0,0 @@ -# syntax=docker/dockerfile:1.2 - -ARG BASE - -FROM ${BASE} - -RUN apt-get update \ - && apt-get install -y \ - clang \ - unzip \ - && rm -rf /var/lib/apt/lists/* - -ARG PROTOC_VERSION -RUN curl -Lo protoc.zip "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" \ - && unzip -q protoc.zip bin/protoc -d /usr/local \ - && chmod a+x /usr/local/bin/protoc \ - && rm -rf protoc.zip diff --git a/docker/Dockerfile.runtime b/docker/Dockerfile.runtime deleted file mode 100644 index ea7d6aeed..000000000 --- a/docker/Dockerfile.runtime +++ /dev/null @@ -1,15 +0,0 @@ -# syntax=docker/dockerfile:1.2 - -ARG BASE - -FROM ${BASE} - -RUN apt-get update \ - && apt-get install -y \ - libssl3 \ - ca-certificates \ - jq \ - curl \ - && rm -rf /var/lib/apt/lists/* - -COPY . /usr/local/bin diff --git a/docker/build.sh b/docker/build.sh deleted file mode 100755 index 71ecec52a..000000000 --- a/docker/build.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Change directory to the project root. -cd "$(dirname "${BASH_SOURCE[0]}")"/.. - -source depversions.sh - -# Build parameters. -PLATFORM="linux/amd64" -BUILDER_CONTAINER_BASE="rust:bookworm" -RUNTIME_CONTAINER_BASE="debian:bookworm" -BUILDER_CONTAINER_TAG="humanode-builder" -RUNTIME_CONTAINER_TAG="humanode" -BUILD_VOLUMES_PATH="$(pwd)/target/docker/$PLATFORM" -HOST_TARGET="${BUILD_VOLUMES_PATH}/target" - -# Enable BuildKit. -export DOCKER_BUILDKIT=1 - -# Prepare the docker context for the build environment. -TMP_BUILDER_DATA_DIR="$(mktemp -d)" -trap 'rm -rf "$TMP_BUILDER_DATA_DIR"' EXIT - -# Prepare the build environment image. -docker build \ - --platform "$PLATFORM" \ - --build-arg BASE="$BUILDER_CONTAINER_BASE" \ - --build-arg PROTOC_VERSION="$PROTOC_VERSION" \ - --file docker/Dockerfile.builder \ - --tag "$BUILDER_CONTAINER_TAG" \ - "$TMP_BUILDER_DATA_DIR" - -# Prepare the host paths so that they are owned by the proper user. -mkdir -p \ - "${BUILD_VOLUMES_PATH}/cargo" \ - "${BUILD_VOLUMES_PATH}/rustup" \ - "${HOST_TARGET}" - -# Run the build in the docker environment. -docker run \ - --rm \ - -i \ - --platform "$PLATFORM" \ - --init \ - --mount "type=bind,src=$(pwd),dst=/build" \ - --volume "${BUILD_VOLUMES_PATH}/cargo:/cargo-host:rw" \ - --volume "${BUILD_VOLUMES_PATH}/rustup:/rustup-host:rw" \ - --volume "${HOST_TARGET}:/build/target:rw" \ - --env CARGO_HOME=/cargo-host \ - --env RUSTUP_HOME=/rustup-host \ - --workdir /build \ - --user "$(id -u):$(id -g)" \ - "$BUILDER_CONTAINER_TAG" \ - /bin/sh -c 'rustup toolchain install && cargo build --release' - -# Prepare artifacts. -TMP_ARTIFACTS_DIR="$(mktemp -d)" -trap 'rm -rf "$TMP_ARTIFACTS_DIR"' EXIT - -# Define a list of all the binary targets to copy over. -BIN_TARGETS=( - humanode-peer - robonode-server - robonode-keygen -) - -# Populate the context for the runtime image build. -for TARGET in "${BIN_TARGETS[@]}"; do - cp -t "$TMP_ARTIFACTS_DIR" "$HOST_TARGET/release/${TARGET}" -done - -# Build docker image. -docker build \ - --platform "$PLATFORM" \ - --build-arg BASE="$RUNTIME_CONTAINER_BASE" \ - --file docker/Dockerfile.runtime \ - --tag "$RUNTIME_CONTAINER_TAG" \ - "$TMP_ARTIFACTS_DIR" diff --git a/docker/tag-and-push.sh b/docker/tag-and-push.sh deleted file mode 100755 index cfb7ebecb..000000000 --- a/docker/tag-and-push.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -euo pipefail - -SRC="$1" -shift - -for DST in "$@"; do - docker tag "$SRC" "$DST" -done - -for TAG in "$@"; do - docker push "$TAG" -done