fix: restore multi-arch api builds
This commit is contained in:
@@ -16,10 +16,10 @@
|
|||||||
#
|
#
|
||||||
# 1. ARM64 QEMU emulation is registered via binfmt_misc with the `F`
|
# 1. ARM64 QEMU emulation is registered via binfmt_misc with the `F`
|
||||||
# (fix-binary) flag so the kernel-held fd works inside build containers.
|
# (fix-binary) flag so the kernel-held fd works inside build containers.
|
||||||
# 2. Base images are pre-pulled into the local cache (resumable retries),
|
# 2. The SDK is pulled for the builder platform while runtime images are
|
||||||
# then the build runs with `--pull=false`.
|
# pulled for ARM64, then the build runs with `--pull=false`.
|
||||||
# 3. `dotnet restore` goes through the host proxy; apt uses the in-Dockerfile
|
# 3. `dotnet restore` goes through the host proxy; apt uses the in-Dockerfile
|
||||||
# Tsinghua mirror directly (NO_PROXY).
|
# Huawei Cloud mirror directly (NO_PROXY).
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# scripts/build-arm64-image.sh
|
# scripts/build-arm64-image.sh
|
||||||
@@ -46,6 +46,7 @@ DOTNET_SDK_IMAGE="${DOTNET_SDK_IMAGE:-mcr.m.daocloud.io/dotnet/sdk:8.0-bookworm-
|
|||||||
DOTNET_RUNTIME_IMAGE="${DOTNET_RUNTIME_IMAGE:-mcr.m.daocloud.io/dotnet/aspnet:8.0-bookworm-slim}"
|
DOTNET_RUNTIME_IMAGE="${DOTNET_RUNTIME_IMAGE:-mcr.m.daocloud.io/dotnet/aspnet:8.0-bookworm-slim}"
|
||||||
NGINX_IMAGE="${NGINX_IMAGE:-docker.m.daocloud.io/library/nginx:1.27-alpine}"
|
NGINX_IMAGE="${NGINX_IMAGE:-docker.m.daocloud.io/library/nginx:1.27-alpine}"
|
||||||
NO_PROXY_HOSTS="mirrors.tuna.tsinghua.edu.cn,.tsinghua.edu.cn,mirrors.huaweicloud.com,.huaweicloud.com,mcr.m.daocloud.io,docker.m.daocloud.io,.m.daocloud.io,localhost,127.0.0.1"
|
NO_PROXY_HOSTS="mirrors.tuna.tsinghua.edu.cn,.tsinghua.edu.cn,mirrors.huaweicloud.com,.huaweicloud.com,mcr.m.daocloud.io,docker.m.daocloud.io,.m.daocloud.io,localhost,127.0.0.1"
|
||||||
|
BUILD_PLATFORM="${BUILD_PLATFORM:-$(docker version --format '{{.Server.Os}}/{{.Server.Arch}}')}"
|
||||||
|
|
||||||
log() { printf '\n\033[1;36m[%s] %s\033[0m\n' "$(date +%H:%M:%S)" "$*"; }
|
log() { printf '\n\033[1;36m[%s] %s\033[0m\n' "$(date +%H:%M:%S)" "$*"; }
|
||||||
die() { printf '\n\033[1;31mERROR: %s\033[0m\n' "$*" >&2; exit 1; }
|
die() { printf '\n\033[1;31mERROR: %s\033[0m\n' "$*" >&2; exit 1; }
|
||||||
@@ -64,10 +65,10 @@ ensure_arm64_emulation() {
|
|||||||
for source_file in /etc/apt/sources.list /etc/apt/sources.list.d/*.sources; do
|
for source_file in /etc/apt/sources.list /etc/apt/sources.list.d/*.sources; do
|
||||||
[ -f "$source_file" ] || continue
|
[ -f "$source_file" ] || continue
|
||||||
sed -i \
|
sed -i \
|
||||||
-e "s|deb.debian.org|mirrors.tuna.tsinghua.edu.cn|g" \
|
-e "s|deb.debian.org|mirrors.huaweicloud.com|g" \
|
||||||
-e "s|security.debian.org/debian-security|mirrors.tuna.tsinghua.edu.cn/debian-security|g" \
|
-e "s|security.debian.org/debian-security|mirrors.huaweicloud.com/debian-security|g" \
|
||||||
-e "s|archive.ubuntu.com|mirrors.tuna.tsinghua.edu.cn|g" \
|
-e "s|archive.ubuntu.com|mirrors.huaweicloud.com|g" \
|
||||||
-e "s|security.ubuntu.com|mirrors.tuna.tsinghua.edu.cn|g" \
|
-e "s|security.ubuntu.com|mirrors.huaweicloud.com|g" \
|
||||||
"$source_file"
|
"$source_file"
|
||||||
done
|
done
|
||||||
apt-get update -qq
|
apt-get update -qq
|
||||||
@@ -87,15 +88,19 @@ ensure_arm64_emulation() {
|
|||||||
|
|
||||||
# --- 2. Pre-pull base images (resumable retries) -----------------------------
|
# --- 2. Pre-pull base images (resumable retries) -----------------------------
|
||||||
pull_with_retry() {
|
pull_with_retry() {
|
||||||
local img="$1" i
|
local platform="$1" img="$2" i
|
||||||
for i in $(seq 1 8); do
|
for i in $(seq 1 8); do
|
||||||
if docker image inspect "$img" >/dev/null 2>&1; then return 0; fi
|
if [ "$(docker image inspect --format '{{.Os}}/{{.Architecture}}' "$img" 2>/dev/null || true)" = "$platform" ]; then
|
||||||
log "Pulling $img (attempt $i/8) ..."
|
return 0
|
||||||
docker pull --platform linux/arm64 "$img" >/dev/null 2>&1 || true
|
fi
|
||||||
docker image inspect "$img" >/dev/null 2>&1 && return 0
|
log "Pulling $img for $platform (attempt $i/8) ..."
|
||||||
|
docker pull --platform "$platform" "$img" >/dev/null 2>&1 || true
|
||||||
|
if [ "$(docker image inspect --format '{{.Os}}/{{.Architecture}}' "$img" 2>/dev/null || true)" = "$platform" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
sleep 3
|
sleep 3
|
||||||
done
|
done
|
||||||
docker image inspect "$img" >/dev/null 2>&1 || die "Could not pull $img (network)."
|
die "Could not pull $img for $platform (network)."
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 3. Build API image ------------------------------------------------------
|
# --- 3. Build API image ------------------------------------------------------
|
||||||
@@ -142,9 +147,9 @@ export_images() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensure_arm64_emulation
|
ensure_arm64_emulation
|
||||||
pull_with_retry "$DOTNET_SDK_IMAGE"
|
pull_with_retry "$BUILD_PLATFORM" "$DOTNET_SDK_IMAGE"
|
||||||
pull_with_retry "$DOTNET_RUNTIME_IMAGE"
|
pull_with_retry linux/arm64 "$DOTNET_RUNTIME_IMAGE"
|
||||||
pull_with_retry "$NGINX_IMAGE"
|
pull_with_retry linux/arm64 "$NGINX_IMAGE"
|
||||||
build_api_image
|
build_api_image
|
||||||
build_frontend_image
|
build_frontend_image
|
||||||
export_images
|
export_images
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
ARG DOTNET_SDK_IMAGE=mcr.m.daocloud.io/dotnet/sdk:8.0-bookworm-slim
|
ARG DOTNET_SDK_IMAGE=mcr.m.daocloud.io/dotnet/sdk:8.0-bookworm-slim
|
||||||
ARG DOTNET_RUNTIME_IMAGE=mcr.m.daocloud.io/dotnet/aspnet:8.0-bookworm-slim
|
ARG DOTNET_RUNTIME_IMAGE=mcr.m.daocloud.io/dotnet/aspnet:8.0-bookworm-slim
|
||||||
|
|
||||||
FROM ${DOTNET_SDK_IMAGE} AS build
|
FROM --platform=$BUILDPLATFORM ${DOTNET_SDK_IMAGE} AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
# Keep proxy settings available for any package endpoint fallback. The primary
|
# Keep proxy settings available for any package endpoint fallback. The primary
|
||||||
@@ -12,6 +12,8 @@ ARG NO_PROXY
|
|||||||
ARG http_proxy
|
ARG http_proxy
|
||||||
ARG https_proxy
|
ARG https_proxy
|
||||||
ARG no_proxy
|
ARG no_proxy
|
||||||
|
ARG BUILDPLATFORM
|
||||||
|
ARG TARGETARCH
|
||||||
ENV HTTP_PROXY=${HTTP_PROXY} \
|
ENV HTTP_PROXY=${HTTP_PROXY} \
|
||||||
HTTPS_PROXY=${HTTPS_PROXY} \
|
HTTPS_PROXY=${HTTPS_PROXY} \
|
||||||
NO_PROXY=${NO_PROXY} \
|
NO_PROXY=${NO_PROXY} \
|
||||||
@@ -22,29 +24,38 @@ ENV HTTP_PROXY=${HTTP_PROXY} \
|
|||||||
# Map Docker TARGETARCH to .NET RID so native dependencies (SQLite, EF Core)
|
# Map Docker TARGETARCH to .NET RID so native dependencies (SQLite, EF Core)
|
||||||
# resolve to the correct platform. Framework-dependent output — apphost stays
|
# resolve to the correct platform. Framework-dependent output — apphost stays
|
||||||
# at /p:UseAppHost=false.
|
# at /p:UseAppHost=false.
|
||||||
ARG TARGETARCH
|
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Workaround for QEMU ARM64 emulation
|
# Run the SDK on the builder's native platform and cross-publish for the target
|
||||||
ENV DOTNET_EnableWriteXorExecute=0
|
# architecture. This keeps restore/publish out of QEMU for ARM64 builds.
|
||||||
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
|
RUN --mount=type=cache,id=liverecorder-nuget,target=/root/.nuget/packages,sharing=locked \
|
||||||
ENV DOTNET_GCConserveMemory=9
|
case "$TARGETARCH" in \
|
||||||
|
|
||||||
RUN case "$TARGETARCH" in \
|
|
||||||
amd64) RID=linux-x64 ;; \
|
amd64) RID=linux-x64 ;; \
|
||||||
arm64) RID=linux-arm64 ;; \
|
arm64) RID=linux-arm64 ;; \
|
||||||
*) echo "ERROR: unknown TARGETARCH=$TARGETARCH" >&2; exit 1 ;; \
|
*) echo "ERROR: unknown TARGETARCH=$TARGETARCH" >&2; exit 1 ;; \
|
||||||
esac ; \
|
esac ; \
|
||||||
echo "Building for TARGETARCH=$TARGETARCH -> RID=$RID" ; \
|
echo "Building on BUILDPLATFORM=$BUILDPLATFORM for TARGETARCH=$TARGETARCH -> RID=$RID" ; \
|
||||||
dotnet restore "src/LiveRecorder.WebApi/LiveRecorder.WebApi.csproj" -p:RestoreUseStaticGraphEvaluation=true --disable-parallel || \
|
restore_attempt=1 ; \
|
||||||
dotnet restore "src/LiveRecorder.WebApi/LiveRecorder.WebApi.csproj" -p:RestoreUseStaticGraphEvaluation=true --disable-parallel || \
|
until dotnet restore "src/LiveRecorder.WebApi/LiveRecorder.WebApi.csproj" \
|
||||||
dotnet restore "src/LiveRecorder.WebApi/LiveRecorder.WebApi.csproj" -p:RestoreUseStaticGraphEvaluation=true --disable-parallel ; \
|
-r "$RID" -p:RestoreUseStaticGraphEvaluation=true --disable-parallel; do \
|
||||||
dotnet publish "src/LiveRecorder.WebApi/LiveRecorder.WebApi.csproj" -c Release -o /app/publish -r "$RID" /p:UseAppHost=false /p:DebugType=None /p:DebugSymbols=false /maxcpucount:1
|
if [ "$restore_attempt" -ge 3 ]; then \
|
||||||
|
echo "ERROR: dotnet restore failed after $restore_attempt attempts for RID=$RID" >&2 ; \
|
||||||
|
exit 1 ; \
|
||||||
|
fi ; \
|
||||||
|
restore_attempt=$((restore_attempt + 1)) ; \
|
||||||
|
echo "dotnet restore failed; retrying attempt $restore_attempt/3 in 5 seconds" >&2 ; \
|
||||||
|
sleep 5 ; \
|
||||||
|
done ; \
|
||||||
|
dotnet publish "src/LiveRecorder.WebApi/LiveRecorder.WebApi.csproj" \
|
||||||
|
-c Release -o /app/publish -r "$RID" --no-restore \
|
||||||
|
/p:UseAppHost=false /p:DebugType=None /p:DebugSymbols=false /maxcpucount:1
|
||||||
|
|
||||||
FROM ${DOTNET_RUNTIME_IMAGE} AS runtime
|
FROM ${DOTNET_RUNTIME_IMAGE} AS runtime
|
||||||
|
|
||||||
RUN sed -i 's|deb.debian.org|mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/debian.sources \
|
RUN sed -i \
|
||||||
|
-e 's|http://deb.debian.org|https://mirrors.huaweicloud.com|g' \
|
||||||
|
-e 's|https://deb.debian.org|https://mirrors.huaweicloud.com|g' \
|
||||||
|
/etc/apt/sources.list.d/debian.sources \
|
||||||
&& apt-get update -o Acquire::ForceIPv4=true -o Acquire::Retries=5 \
|
&& apt-get update -o Acquire::ForceIPv4=true -o Acquire::Retries=5 \
|
||||||
&& apt-get install -o Acquire::ForceIPv4=true -o Acquire::Retries=5 -y --no-install-recommends ffmpeg nodejs ca-certificates curl jq \
|
&& apt-get install -o Acquire::ForceIPv4=true -o Acquire::Retries=5 -y --no-install-recommends ffmpeg nodejs ca-certificates curl jq \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using LiveRecorder.Application.Abstractions.Settings;
|
|||||||
using LiveRecorder.Application.Abstractions.Storage;
|
using LiveRecorder.Application.Abstractions.Storage;
|
||||||
using LiveRecorder.Application.Models.Reports;
|
using LiveRecorder.Application.Models.Reports;
|
||||||
using LiveRecorder.Application.Services;
|
using LiveRecorder.Application.Services;
|
||||||
|
using LiveRecorder.Domain.Enums;
|
||||||
using LiveRecorder.Infrastructure.Persistence;
|
using LiveRecorder.Infrastructure.Persistence;
|
||||||
using LiveRecorder.Infrastructure.Persistence.Repositories;
|
using LiveRecorder.Infrastructure.Persistence.Repositories;
|
||||||
using LiveRecorder.Infrastructure.Platforms.Bilibili;
|
using LiveRecorder.Infrastructure.Platforms.Bilibili;
|
||||||
|
|||||||
Reference in New Issue
Block a user