From 49812e94c06c6a8f7e1df85521182dc9a36baffe Mon Sep 17 00:00:00 2001 From: JustMe Date: Sat, 10 Oct 2026 15:45:45 +0800 Subject: [PATCH] ci: cross-build dev images with AotAnywhere [CI] [SKIP TESTS] Signed-off-by: JustMe --- ci/build-dev-image.sh | 9 ++++++- .../container/Agent.NativeBuild.Containerfile | 27 ++++++++++++------- .../container/Probe.NativeBuild.Containerfile | 27 ++++++++++++------- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/ci/build-dev-image.sh b/ci/build-dev-image.sh index 0c0aba8..7e9e21c 100644 --- a/ci/build-dev-image.sh +++ b/ci/build-dev-image.sh @@ -59,12 +59,19 @@ context="$work/$component" local_image="localhost/moshiro-$component:dev-$arch-check" node_rid="linux-musl-x64" [[ "$arch" == arm64 ]] && node_rid="linux-musl-arm64" +nuget_cache="${NUGET_PACKAGES:-/home/justme/.nuget/packages}" +mkdir -p "$nuget_cache" + +# A stable timestamp lets a retry of the same commit reuse the publish layer. +commit_epoch="$(git -C "$root" show -s --format=%ct "$CI_COMMIT_SHA")" +built_at="$(date -u -d "@$commit_epoch" +%Y-%m-%dT%H:%M:%SZ)" python3 "$root/ci/stage-node-image.py" "$component" "$context" buildah bud --layers --network host --tls-verify=true --arch "$arch" \ + --volume "$nuget_cache:/root/.nuget/packages:rw" \ --build-arg "APP_VERSION=$image_version" \ --build-arg "NODE_RID=$node_rid" \ - --build-arg "MOSHIRO_TAG=$MOSHIRO_TAG" --build-arg "MOSHIRO_COMMIT=${CI_COMMIT_SHA:0:10}" --build-arg "MOSHIRO_BUILT_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + --build-arg "MOSHIRO_TAG=$MOSHIRO_TAG" --build-arg "MOSHIRO_COMMIT=${CI_COMMIT_SHA:0:10}" --build-arg "MOSHIRO_BUILT_AT=$built_at" \ -f "$context/Containerfile" \ -t "$local_image" "$context" diff --git a/packaging/container/Agent.NativeBuild.Containerfile b/packaging/container/Agent.NativeBuild.Containerfile index 0f88a06..14e553e 100644 --- a/packaging/container/Agent.NativeBuild.Containerfile +++ b/packaging/container/Agent.NativeBuild.Containerfile @@ -1,11 +1,23 @@ -FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine-aot AS build +# Run all build commands on the native amd64 runner. AotAnywhere cross-links +# the NativeAOT output, so an ARM64 build never needs QEMU. +FROM --platform=linux/amd64 mcr.microsoft.com/dotnet/sdk:10.0-alpine-aot AS build WORKDIR /src/backend COPY restore/backend/ ./ ARG NODE_RID=linux-musl-x64 +ENV NUGET_PACKAGES=/root/.nuget/packages # restore 也要带 PublishAot:不然不会还原 ILCompiler,之后 --no-restore 的发布就悄悄变成「裁剪过的框架依赖程序」 -RUN dotnet restore agent/src/MoShiro.Agent -r "$NODE_RID" -p:PublishAot=true --artifacts-path /artifacts \ - && dotnet restore fleet/tools/fleet-enroll -r "$NODE_RID" -p:PublishAot=true --artifacts-path /artifacts +RUN dotnet restore agent/src/MoShiro.Agent -r "$NODE_RID" -p:PublishAot=true -p:UseAotAnywhere=true --artifacts-path /artifacts \ + && dotnet restore fleet/tools/fleet-enroll -r "$NODE_RID" -p:PublishAot=true -p:UseAotAnywhere=true --artifacts-path /artifacts + +# Fetch target-musl runtime libraries on the native builder before copying +# application sources. This layer stays reusable when only app code changes. +RUN apk_arch=x86_64; \ + case "$NODE_RID" in *arm64) apk_arch=aarch64 ;; esac; \ + mkdir -p /tmp/runtime-apks /tmp/runtime-root /out/runtime; \ + apk --arch "$apk_arch" fetch --recursive --output /tmp/runtime-apks libmsquic numactl lttng-ust zlib; \ + for package in /tmp/runtime-apks/*.apk; do tar -xzf "$package" -C /tmp/runtime-root; done; \ + cp -a /tmp/runtime-root/usr/lib/*.so* /out/runtime/ COPY source/backend/ ./ # 构建信息:CI 通过 --build-arg 传入;不传就是空(放在 restore 之后,每次构建都变的时间不会让依赖还原的缓存失效) @@ -14,11 +26,11 @@ ARG MOSHIRO_COMMIT= ARG MOSHIRO_BUILT_AT= ENV MOSHIRO_TAG=$MOSHIRO_TAG MOSHIRO_COMMIT=$MOSHIRO_COMMIT MOSHIRO_BUILT_AT=$MOSHIRO_BUILT_AT RUN dotnet publish agent/src/MoShiro.Agent -m:3 -c Release -r "$NODE_RID" \ - --self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=false \ + --self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=true \ -p:UseAppHost=true -p:StripSymbols=true \ -p:DebugType=none -p:DebugSymbols=false --artifacts-path /artifacts -o /out/agent \ && dotnet publish fleet/tools/fleet-enroll -m:3 -c Release -r "$NODE_RID" \ - --self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=false \ + --self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=true \ -p:UseAppHost=true -p:StripSymbols=true \ -p:DebugType=none -p:DebugSymbols=false --artifacts-path /artifacts -o /out/enroll # 原生程序有几 MB;几十 KB 的是只会去找 .dll 的启动器 @@ -27,10 +39,6 @@ RUN test -x /out/agent/moshiro-agent && test -x /out/enroll/fleet-enroll \ FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine -# Include MsQuic and its musl runtime dependencies in the resulting image. -RUN apk add --no-cache libmsquic numactl lttng-ust zlib \ - && cp -a /usr/lib/libmsquic.so* /usr/lib/libnuma.so* /usr/lib/liblttng-ust*.so* /usr/lib/libz.so* /usr/local/bin/ - ARG APP_VERSION=main LABEL org.opencontainers.image.title="MoShiro Agent" \ org.opencontainers.image.description="MoShiro node agent for Linux" \ @@ -39,6 +47,7 @@ LABEL org.opencontainers.image.title="MoShiro Agent" \ COPY --chown=1654:1654 --from=build /out/agent/moshiro-agent /usr/local/bin/moshiro-agent COPY --chown=1654:1654 --from=build /out/enroll/fleet-enroll /usr/local/bin/fleet-enroll +COPY --from=build /out/runtime/ /usr/local/bin/ COPY --chown=1654:1654 config/ /etc/moshiro/ COPY --chown=1654:1654 --chmod=0755 entrypoint.sh /usr/local/bin/moshiro-entrypoint diff --git a/packaging/container/Probe.NativeBuild.Containerfile b/packaging/container/Probe.NativeBuild.Containerfile index ca54cb5..ce7dad6 100644 --- a/packaging/container/Probe.NativeBuild.Containerfile +++ b/packaging/container/Probe.NativeBuild.Containerfile @@ -1,11 +1,23 @@ -FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine-aot AS build +# Run all build commands on the native amd64 runner. AotAnywhere cross-links +# the NativeAOT output, so an ARM64 build never needs QEMU. +FROM --platform=linux/amd64 mcr.microsoft.com/dotnet/sdk:10.0-alpine-aot AS build WORKDIR /src/backend COPY restore/backend/ ./ ARG NODE_RID=linux-musl-x64 +ENV NUGET_PACKAGES=/root/.nuget/packages # restore 也要带 PublishAot:不然不会还原 ILCompiler,之后 --no-restore 的发布就悄悄变成「裁剪过的框架依赖程序」 -RUN dotnet restore probe/src/MoShiro.Probe -r "$NODE_RID" -p:PublishAot=true --artifacts-path /artifacts \ - && dotnet restore fleet/tools/fleet-enroll -r "$NODE_RID" -p:PublishAot=true --artifacts-path /artifacts +RUN dotnet restore probe/src/MoShiro.Probe -r "$NODE_RID" -p:PublishAot=true -p:UseAotAnywhere=true --artifacts-path /artifacts \ + && dotnet restore fleet/tools/fleet-enroll -r "$NODE_RID" -p:PublishAot=true -p:UseAotAnywhere=true --artifacts-path /artifacts + +# Fetch target-musl runtime libraries on the native builder before copying +# application sources. This layer stays reusable when only app code changes. +RUN apk_arch=x86_64; \ + case "$NODE_RID" in *arm64) apk_arch=aarch64 ;; esac; \ + mkdir -p /tmp/runtime-apks /tmp/runtime-root /out/runtime; \ + apk --arch "$apk_arch" fetch --recursive --output /tmp/runtime-apks libmsquic numactl lttng-ust zlib; \ + for package in /tmp/runtime-apks/*.apk; do tar -xzf "$package" -C /tmp/runtime-root; done; \ + cp -a /tmp/runtime-root/usr/lib/*.so* /out/runtime/ COPY source/backend/ ./ # 构建信息:CI 通过 --build-arg 传入;不传就是空(放在 restore 之后,每次构建都变的时间不会让依赖还原的缓存失效) @@ -14,11 +26,11 @@ ARG MOSHIRO_COMMIT= ARG MOSHIRO_BUILT_AT= ENV MOSHIRO_TAG=$MOSHIRO_TAG MOSHIRO_COMMIT=$MOSHIRO_COMMIT MOSHIRO_BUILT_AT=$MOSHIRO_BUILT_AT RUN dotnet publish probe/src/MoShiro.Probe -m:3 -c Release -r "$NODE_RID" \ - --self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=false \ + --self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=true \ -p:UseAppHost=true -p:StripSymbols=true \ -p:DebugType=none -p:DebugSymbols=false --artifacts-path /artifacts -o /out/probe \ && dotnet publish fleet/tools/fleet-enroll -m:3 -c Release -r "$NODE_RID" \ - --self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=false \ + --self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=true \ -p:UseAppHost=true -p:StripSymbols=true \ -p:DebugType=none -p:DebugSymbols=false --artifacts-path /artifacts -o /out/enroll # 原生程序有几 MB;几十 KB 的是只会去找 .dll 的启动器 @@ -27,10 +39,6 @@ RUN test -x /out/probe/moshiro-probe && test -x /out/enroll/fleet-enroll \ FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine -# Include MsQuic and its musl runtime dependencies in the resulting image. -RUN apk add --no-cache libmsquic numactl lttng-ust zlib \ - && cp -a /usr/lib/libmsquic.so* /usr/lib/libnuma.so* /usr/lib/liblttng-ust*.so* /usr/lib/libz.so* /usr/local/bin/ - ARG APP_VERSION=main LABEL org.opencontainers.image.title="MoShiro Probe" \ org.opencontainers.image.description="MoShiro network measurement probe for Linux" \ @@ -39,6 +47,7 @@ LABEL org.opencontainers.image.title="MoShiro Probe" \ COPY --chown=1654:1654 --from=build /out/probe/moshiro-probe /usr/local/bin/moshiro-probe COPY --chown=1654:1654 --from=build /out/enroll/fleet-enroll /usr/local/bin/fleet-enroll +COPY --from=build /out/runtime/ /usr/local/bin/ COPY --chown=1654:1654 config/ /etc/moshiro/ COPY --chown=1654:1654 --chmod=0755 entrypoint.sh /usr/local/bin/moshiro-entrypoint