From 9f68453bdaf50e2d7a603ef321972d70e1cc862c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis?= <36898551+MrZeLee@users.noreply.github.com> Date: Sun, 6 Apr 2025 05:40:32 +0100 Subject: [PATCH] Multi-arch builds (#32) * feat: enable multi-arch builds and add tor and i2p images This commit introduces multi-architecture support (amd64 & arm64) for Docker image builds using Docker Buildx. It also adds new images for tor and i2p services. The release script is updated to handle these new images and to accept a Docker Hub username as an argument. The publish workflow is updated to use the new release script and to set up QEMU and Docker Buildx. * feat(publish.yaml): add workflow_dispatch trigger to publish workflow feat(publish.yaml): allow publish workflow to run when workflow_dispatch event is triggered * feat(dockerfiles/monero): add support for ARM64 architecture * build(dockerfiles/monero): remove duplicate FROM instruction release(monero) --- .github/workflows/publish.yaml | 118 +++++++++++++++++++++++++++++---- dockerfiles/i2p | 23 +++++-- dockerfiles/monero | 46 +++++++++---- release.sh | 79 ++++++++++++++-------- 4 files changed, 206 insertions(+), 60 deletions(-) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index e4d43f6..b541ef4 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -8,27 +8,117 @@ env: DH_USER: lalanza808 jobs: - publish_images: + nodemapper: + name: Publish nodemapper image runs-on: ubuntu-latest - name: Publish selected Docker image to Dockerhub - if: contains(github.event.head_commit.message, 'release(') + if: contains(github.event.head_commit.message, 'release(nodemapper)') steps: - name: Authenticate to Dockerhub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Checkout repository uses: actions/checkout@v4 - - name: Build and push new nodemapper image - if: contains(github.event.head_commit.message, 'release(nodemapper)') - run: bash release.sh nodemapper - - name: Build and push new monerod image - if: contains(github.event.head_commit.message, 'release(monerod)') - run: bash release.sh monerod - - name: Build and push new exporter image - if: contains(github.event.head_commit.message, 'release(exporter)') - run: bash release.sh exporter - - + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and push nodemapper image + run: bash release.sh nodemapper ${{ env.DH_USER }} + + monero: + name: Publish monero image + runs-on: ubuntu-latest + if: contains(github.event.head_commit.message, 'release(monero)') + steps: + - name: Authenticate to Dockerhub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and push monero image + run: bash release.sh monero ${{ env.DH_USER }} + + exporter: + name: Publish exporter image + runs-on: ubuntu-latest + if: contains(github.event.head_commit.message, 'release(exporter)') + steps: + - name: Authenticate to Dockerhub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and push exporter image + run: bash release.sh exporter ${{ env.DH_USER }} + + tor: + name: Publish tor image + runs-on: ubuntu-latest + if: contains(github.event.head_commit.message, 'release(tor)') + steps: + - name: Authenticate to Dockerhub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and push tor image + run: bash release.sh tor ${{ env.DH_USER }} + + i2p: + name: Publish i2p image + runs-on: ubuntu-latest + if: contains(github.event.head_commit.message, 'release(i2p)') + steps: + - name: Authenticate to Dockerhub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and push i2p image + run: bash release.sh i2p ${{ env.DH_USER }} diff --git a/dockerfiles/i2p b/dockerfiles/i2p index f62fee2..6dbb352 100644 --- a/dockerfiles/i2p +++ b/dockerfiles/i2p @@ -1,12 +1,23 @@ FROM ubuntu:22.04 -ENV DEBIAN_FRONTEND noninteractive +ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && \ - apt-get install wget sudo -y -RUN wget https://github.com/PurpleI2P/i2pd/releases/download/2.54.0/i2pd_2.54.0-1jammy1_amd64.deb -O i2pd.deb -q -RUN apt install ./i2pd.deb -y -RUN rm -rf i2p.deb && \ +RUN apt-get update && apt-get install -y wget sudo + +# Detect architecture and use it immediately to download and install the corresponding i2pd package. +RUN set -ex; \ + arch=$(uname -m); \ + if [ "$arch" = "x86_64" ]; then \ + ARCH="amd64"; \ + elif [ "$arch" = "aarch64" ]; then \ + ARCH="arm64"; \ + else \ + echo "Unsupported architecture: $arch" && exit 1; \ + fi; \ + echo "Using architecture: $ARCH"; \ + wget "https://github.com/PurpleI2P/i2pd/releases/download/2.54.0/i2pd_2.54.0-1jammy1_${ARCH}.deb" -O i2pd.deb -q && \ + apt install ./i2pd.deb -y && \ + rm -rf i2pd.deb && \ apt clean all && \ apt autoremove -y diff --git a/dockerfiles/monero b/dockerfiles/monero index 6216d38..edeea49 100644 --- a/dockerfiles/monero +++ b/dockerfiles/monero @@ -1,9 +1,14 @@ FROM ubuntu:22.04 AS og -ENV MONERO_HASH 51ba03928d189c1c11b5379cab17dd9ae8d2230056dc05c872d0f8dba4a87f1d -ENV MONERO_DL_URL https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.3.4.tar.bz2 -ENV MONERO_DL_FILE monero.tar.bz2 -ENV MONERO_SUMS_FILE sha256sums +# Define the Monero version +ENV MONERO_VERSION=0.18.3.4 + +ENV MONERO_HASH_X64=51ba03928d189c1c11b5379cab17dd9ae8d2230056dc05c872d0f8dba4a87f1d +ENV MONERO_DL_URL_X64=https://downloads.getmonero.org/cli/monero-linux-x64-v${MONERO_VERSION}.tar.bz2 +ENV MONERO_HASH_ARMV8=33ca2f0055529d225b61314c56370e35606b40edad61c91c859f873ed67a1ea7 +ENV MONERO_DL_URL_ARMV8=https://downloads.getmonero.org/cli/monero-linux-armv8-v${MONERO_VERSION}.tar.bz2 +ENV MONERO_DL_FILE=monero.tar.bz2 +ENV MONERO_SUMS_FILE=sha256sums WORKDIR /opt/monero @@ -16,20 +21,33 @@ RUN apt-get update \ # Confirm hashes match # Install daemon binary # Clean up -RUN wget -qO ${MONERO_DL_FILE} ${MONERO_DL_URL} \ - && echo "${MONERO_HASH} ${MONERO_DL_FILE}" > ${MONERO_SUMS_FILE} \ - && sha256sum -c ${MONERO_SUMS_FILE}; \ - if [ "$?" -eq 0 ]; \ - then \ +RUN \ + # Detect architecture and set URL/hash accordingly \ + if [ "$(uname -m)" = "x86_64" ]; then \ + echo "Architecture x86_64 detected"; \ + export MONERO_DL_URL=${MONERO_DL_URL_X64}; \ + export MONERO_HASH=${MONERO_HASH_X64}; \ + elif [ "$(uname -m)" = "aarch64" ]; then \ + echo "Architecture ARM64 detected"; \ + export MONERO_DL_URL=${MONERO_DL_URL_ARMV8}; \ + export MONERO_HASH=${MONERO_HASH_ARMV8}; \ + else \ + echo "Unsupported architecture: $(uname -m)"; exit 1; \ + fi && \ + echo "Using URL: ${MONERO_DL_URL}" && \ + wget -qO ${MONERO_DL_FILE} ${MONERO_DL_URL} && \ + echo "${MONERO_HASH} ${MONERO_DL_FILE}" > ${MONERO_SUMS_FILE} && \ + sha256sum -c ${MONERO_SUMS_FILE}; \ + if [ "$?" -eq 0 ]; then \ echo -e "[+] Hashes match - proceeding with container build"; \ else \ echo -e "[!] Hashes do not match - exiting"; \ exit 5; \ - fi \ - && mkdir ./tmp \ - && tar xjf ${MONERO_DL_FILE} -C ./tmp --strip 1 \ - && mv ./tmp/* /usr/local/bin/ \ - && rm -rf ./tmp ${MONERO_SUMS_FILE} ${MONERO_DL_FILE} + fi && \ + mkdir ./tmp && \ + tar xjf ${MONERO_DL_FILE} -C ./tmp --strip 1 && \ + mv ./tmp/* /usr/local/bin/ && \ + rm -rf ./tmp ${MONERO_SUMS_FILE} ${MONERO_DL_FILE} # Download ban list RUN wget -qO /tmp/ban_list.txt "https://raw.githubusercontent.com/Boog900/monero-ban-list/main/ban_list.txt" diff --git a/release.sh b/release.sh index 1e677e1..db882f7 100644 --- a/release.sh +++ b/release.sh @@ -1,43 +1,70 @@ -#!/bin/bash +#!/usr/bin/env bash -# Build and tag container images for each service based upon passed argument; monerod, nodemapper, or exporter -# All are manually tagged since some do not update as frequently as others. Bump the script -# to bump the image stored on Dockerhub. +# Build and tag container images for each service based upon the passed argument. +# This version builds multi-arch images (linux/amd64 and linux/arm64) using Docker Buildx. +# Make sure you have set up buildx and QEMU emulation (if building on a different arch). +# +# Example usage: +# ./release.sh monero +# ./release.sh exporter set -ex IMAGE=${1} -DH_USER=lalanza808 +DH_USER=${2:-lalanza808} MONERO_VERSION=v0.18.3.4 MONERO_BASE=${DH_USER}/monero EXPORTER_VERSION=1.0.0 EXPORTER_BASE=${DH_USER}/exporter NODEMAPPER_VERSION=1.0.3 NODEMAPPER_BASE=${DH_USER}/nodemapper +TOR_VERSION=$(sed -n 's/^FROM ubuntu:\(.*\) *$/\1/p' dockerfiles/tor) +TOR_BASE=${DH_USER}/tor +I2P_VERSION=$(sed -n 's/^FROM ubuntu:\(.*\) *$/\1/p' dockerfiles/i2p) +I2P_BASE=${DH_USER}/i2p -if [[ "${IMAGE}" == "nodemapper" ]] -then - echo -e "[+] Building nodemapper" - docker build -t "${NODEMAPPER_BASE}:${NODEMAPPER_VERSION}" -f dockerfiles/nodemapper . - docker tag "${NODEMAPPER_BASE}:${NODEMAPPER_VERSION}" "${NODEMAPPER_BASE}:latest" - docker push "${NODEMAPPER_BASE}:${NODEMAPPER_VERSION}" - docker push "${NODEMAPPER_BASE}:latest" +if [[ "${IMAGE}" == "nodemapper" ]]; then + echo -e "[+] Building nodemapper multi-arch (amd64 & arm64)" + docker buildx build --platform linux/amd64,linux/arm64 \ + -t "${NODEMAPPER_BASE}:${NODEMAPPER_VERSION}" \ + -t "${NODEMAPPER_BASE}:latest" \ + -f dockerfiles/nodemapper . \ + --push fi -if [[ "${IMAGE}" == "exporter" ]] -then - echo -e "[+] Building exporter" - docker build -t "${EXPORTER_BASE}:${EXPORTER_VERSION}" -f dockerfiles/exporter . - docker tag "${EXPORTER_BASE}:${EXPORTER_VERSION}" "${EXPORTER_BASE}:latest" - docker push "${EXPORTER_BASE}:${EXPORTER_VERSION}" - docker push "${EXPORTER_BASE}:latest" +if [[ "${IMAGE}" == "exporter" ]]; then + echo -e "[+] Building exporter multi-arch (amd64 & arm64)" + docker buildx build --platform linux/amd64,linux/arm64 \ + -t "${EXPORTER_BASE}:${EXPORTER_VERSION}" \ + -t "${EXPORTER_BASE}:latest" \ + -f dockerfiles/exporter . \ + --push fi -if [[ "${IMAGE}" == "monero" ]] -then - echo -e "[+] Building monero" - docker build -t "${MONERO_BASE}:${MONERO_VERSION}" -f dockerfiles/monero . - docker tag "${MONERO_BASE}:${MONERO_VERSION}" "${MONERO_BASE}:latest" - docker push "${MONERO_BASE}:${MONERO_VERSION}" - docker push "${MONERO_BASE}:latest" +if [[ "${IMAGE}" == "monero" ]]; then + echo -e "[+] Building monero multi-arch (amd64 & arm64)" + docker buildx build --platform linux/amd64,linux/arm64 \ + -t "${MONERO_BASE}:${MONERO_VERSION}" \ + -t "${MONERO_BASE}:latest" \ + -f dockerfiles/monero . \ + --push fi + +if [[ "${IMAGE}" == "tor" ]]; then + echo -e "[+] Building tor multi-arch (amd64 & arm64)" + docker buildx build --platform linux/amd64,linux/arm64 \ + -t "${TOR_BASE}:${TOR_VERSION}" \ + -t "${TOR_BASE}:latest" \ + -f dockerfiles/tor . \ + --push +fi + +if [[ "${IMAGE}" == "i2p" ]]; then + echo -e "[+] Building i2p multi-arch (amd64 & arm64)" + docker buildx build --platform linux/amd64,linux/arm64 \ + -t "${I2P_BASE}:${I2P_VERSION}" \ + -t "${I2P_BASE}:latest" \ + -f dockerfiles/i2p . \ + --push +fi +