From fd5be2cc8e01df466f036c00d7b56b6873ee44a6 Mon Sep 17 00:00:00 2001 From: nanxun Date: Sun, 31 May 2026 16:42:37 +0800 Subject: [PATCH] ci: stabilize buildx heartbeat and cache --- Jenkinsfile | 159 ++++++++++++++--------------- src/LiveRecorder.WebApi/Dockerfile | 6 +- 2 files changed, 79 insertions(+), 86 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 22f0afd..39f7dd0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,5 +1,5 @@ pipeline { - agent { label '构建机1' } + agent { label '閺嬪嫬缂撻張?' } options { timestamps() @@ -8,15 +8,17 @@ pipeline { } environment { - REGISTRY_URL = 'reg.nxsir.cn' - API_IMAGE_NAME = 'liverecorder/app-api' - WEB_IMAGE_NAME = 'liverecorder/app-web' - IMAGE_TAG = "${env.BUILD_ID}" - DOCKER_CREDS = 'harbor_key' - TARGET_PLATFORMS = 'linux/amd64,linux/arm64' - BUILDER_NAME = 'liverecorder-buildx' - WEB_NODE_IMAGE = 'docker.m.daocloud.io/library/node:22-alpine' - WEB_NGINX_IMAGE = 'docker.m.daocloud.io/library/nginx:1.27-alpine' + REGISTRY_URL = 'reg.nxsir.cn' + API_IMAGE_NAME = 'liverecorder/app-api' + WEB_IMAGE_NAME = 'liverecorder/app-web' + IMAGE_TAG = "${env.BUILD_ID}" + DOCKER_CREDS = 'harbor_key' + TARGET_PLATFORMS = 'linux/amd64,linux/arm64' + BUILDER_NAME = 'liverecorder-buildx' + WEB_NODE_IMAGE = 'docker.m.daocloud.io/library/node:22-alpine' + WEB_NGINX_IMAGE = 'docker.m.daocloud.io/library/nginx:1.27-alpine' + HTTP_PROXY_URL = 'http://192.168.5.200:7890' + NO_PROXY_HOSTS = '127.0.0.1,localhost,reg.nxsir.cn,gitea.nxsir.cn' GIT_REPO_URL = 'https://gitea.nxsir.cn/nanxun/live_recorder.git' GIT_BRANCH = 'main' @@ -26,6 +28,8 @@ pipeline { API_IMAGE_LATEST = "${REGISTRY_URL}/${API_IMAGE_NAME}:latest" WEB_IMAGE_TAGGED = "${REGISTRY_URL}/${WEB_IMAGE_NAME}:${IMAGE_TAG}" WEB_IMAGE_LATEST = "${REGISTRY_URL}/${WEB_IMAGE_NAME}:latest" + API_CACHE_IMAGE = "${REGISTRY_URL}/${API_IMAGE_NAME}:buildcache" + WEB_CACHE_IMAGE = "${REGISTRY_URL}/${WEB_IMAGE_NAME}:buildcache" } stages { @@ -52,9 +56,20 @@ pipeline { set -e sudo docker buildx version sudo docker run --privileged --rm tonistiigi/binfmt --install arm64 - - # 强制清理旧的 builder 实例,防止僵尸状态 - sudo docker buildx rm ${BUILDER_NAME} || true + if ! sudo docker buildx inspect --builder ${BUILDER_NAME} >/dev/null 2>&1; then + sudo docker buildx create \ + --name ${BUILDER_NAME} \ + --driver docker-container \ + --driver-opt network=host \ + --driver-opt 'env.HTTP_PROXY=${HTTP_PROXY_URL}' \ + --driver-opt 'env.HTTPS_PROXY=${HTTP_PROXY_URL}' \ + --driver-opt 'env.NO_PROXY=reg.nxsir.cn' \ + --driver-opt 'env.http_proxy=${HTTP_PROXY_URL}' \ + --driver-opt 'env.https_proxy=${HTTP_PROXY_URL}' \ + --driver-opt 'env.no_proxy=reg.nxsir.cn' \ + --use + fi + sudo docker buildx inspect --builder ${BUILDER_NAME} --bootstrap >/dev/null """ } } @@ -82,67 +97,56 @@ pipeline { set -e run_with_heartbeat() { log_file="\$1" - shift + build_label="\$2" + shift 2 rm -f "\$log_file" : > "\$log_file" "\$@" >"\$log_file" 2>&1 & cmd_pid=\$! cmd_status=0 - last_line=0 + last_size=0 while kill -0 "\$cmd_pid" >/dev/null 2>&1; do + echo "[heartbeat] \${build_label} still running at \$(date -u +%Y-%m-%dT%H:%M:%SZ)" if [ -f "\$log_file" ]; then - total_lines=\$(wc -l < "\$log_file" 2>/dev/null || echo 0) - else - total_lines=0 - fi - if [ "\$total_lines" -gt "\$last_line" ]; then - sed -n "\$((last_line + 1)),\${total_lines}p" "\$log_file" - last_line=\$total_lines - else - echo "[heartbeat] API multi-arch build still running at \$(date -u +%Y-%m-%dT%H:%M:%SZ)" + current_size=\$(stat -c%s "\$log_file" 2>/dev/null || echo 0) + if [ "\$current_size" -gt "\$last_size" ]; then + start_byte=\$((last_size + 1)) + tail -c +"\$start_byte" "\$log_file" || true + last_size=\$current_size + fi fi sleep 20 done wait "\$cmd_pid" || cmd_status=\$? if [ -f "\$log_file" ]; then - total_lines=\$(wc -l < "\$log_file" 2>/dev/null || echo 0) - if [ "\$total_lines" -gt "\$last_line" ]; then - sed -n "\$((last_line + 1)),\${total_lines}p" "\$log_file" + current_size=\$(stat -c%s "\$log_file" 2>/dev/null || echo 0) + if [ "\$current_size" -gt "\$last_size" ]; then + start_byte=\$((last_size + 1)) + tail -c +"\$start_byte" "\$log_file" || true fi fi if [ "\$cmd_status" -ne 0 ]; then - echo "[heartbeat] API multi-arch build failed with exit code \$cmd_status" + echo "[heartbeat] \${build_label} failed with exit code \$cmd_status" fi return "\$cmd_status" } - if ! sudo docker buildx inspect --builder ${BUILDER_NAME} >/dev/null 2>&1; then - sudo docker buildx create \ - --name ${BUILDER_NAME} \ - --driver docker-container \ - --driver-opt network=host \ - --driver-opt 'env.HTTP_PROXY=http://192.168.5.200:7890' \ - --driver-opt 'env.HTTPS_PROXY=http://192.168.5.200:7890' \ - --driver-opt 'env.NO_PROXY=reg.nxsir.cn' \ - --driver-opt 'env.http_proxy=http://192.168.5.200:7890' \ - --driver-opt 'env.https_proxy=http://192.168.5.200:7890' \ - --driver-opt 'env.no_proxy=reg.nxsir.cn' \ - --use - fi sudo docker buildx inspect --builder ${BUILDER_NAME} --bootstrap >/dev/null echo 'Building and pushing multi-arch API image: ${API_IMAGE_TAGGED}' - run_with_heartbeat /tmp/live-recorder-api-buildx-${IMAGE_TAG}.log \ + run_with_heartbeat /tmp/live-recorder-api-buildx-${IMAGE_TAG}.log "API multi-arch build" \ sudo docker buildx build \ --builder ${BUILDER_NAME} \ --platform ${TARGET_PLATFORMS} \ --network host \ --progress=plain \ --provenance=false \ - --build-arg HTTP_PROXY=http://192.168.5.200:7890 \ - --build-arg HTTPS_PROXY=http://192.168.5.200:7890 \ - --build-arg NO_PROXY=127.0.0.1,localhost,reg.nxsir.cn,gitea.nxsir.cn \ - --build-arg http_proxy=http://192.168.5.200:7890 \ - --build-arg https_proxy=http://192.168.5.200:7890 \ - --build-arg no_proxy=127.0.0.1,localhost,reg.nxsir.cn,gitea.nxsir.cn \ + --cache-from type=registry,ref=${API_CACHE_IMAGE} \ + --cache-to type=registry,ref=${API_CACHE_IMAGE},mode=max \ + --build-arg HTTP_PROXY=${HTTP_PROXY_URL} \ + --build-arg HTTPS_PROXY=${HTTP_PROXY_URL} \ + --build-arg NO_PROXY=${NO_PROXY_HOSTS} \ + --build-arg http_proxy=${HTTP_PROXY_URL} \ + --build-arg https_proxy=${HTTP_PROXY_URL} \ + --build-arg no_proxy=${NO_PROXY_HOSTS} \ -f src/LiveRecorder.WebApi/Dockerfile \ -t ${API_IMAGE_TAGGED} \ -t ${API_IMAGE_LATEST} \ @@ -158,69 +162,58 @@ pipeline { set -e run_with_heartbeat() { log_file="\$1" - shift + build_label="\$2" + shift 2 rm -f "\$log_file" : > "\$log_file" "\$@" >"\$log_file" 2>&1 & cmd_pid=\$! cmd_status=0 - last_line=0 + last_size=0 while kill -0 "\$cmd_pid" >/dev/null 2>&1; do + echo "[heartbeat] \${build_label} still running at \$(date -u +%Y-%m-%dT%H:%M:%SZ)" if [ -f "\$log_file" ]; then - total_lines=\$(wc -l < "\$log_file" 2>/dev/null || echo 0) - else - total_lines=0 - fi - if [ "\$total_lines" -gt "\$last_line" ]; then - sed -n "\$((last_line + 1)),\${total_lines}p" "\$log_file" - last_line=\$total_lines - else - echo "[heartbeat] Web multi-arch build still running at \$(date -u +%Y-%m-%dT%H:%M:%SZ)" + current_size=\$(stat -c%s "\$log_file" 2>/dev/null || echo 0) + if [ "\$current_size" -gt "\$last_size" ]; then + start_byte=\$((last_size + 1)) + tail -c +"\$start_byte" "\$log_file" || true + last_size=\$current_size + fi fi sleep 20 done wait "\$cmd_pid" || cmd_status=\$? if [ -f "\$log_file" ]; then - total_lines=\$(wc -l < "\$log_file" 2>/dev/null || echo 0) - if [ "\$total_lines" -gt "\$last_line" ]; then - sed -n "\$((last_line + 1)),\${total_lines}p" "\$log_file" + current_size=\$(stat -c%s "\$log_file" 2>/dev/null || echo 0) + if [ "\$current_size" -gt "\$last_size" ]; then + start_byte=\$((last_size + 1)) + tail -c +"\$start_byte" "\$log_file" || true fi fi if [ "\$cmd_status" -ne 0 ]; then - echo "[heartbeat] Web multi-arch build failed with exit code \$cmd_status" + echo "[heartbeat] \${build_label} failed with exit code \$cmd_status" fi return "\$cmd_status" } - if ! sudo docker buildx inspect --builder ${BUILDER_NAME} >/dev/null 2>&1; then - sudo docker buildx create \ - --name ${BUILDER_NAME} \ - --driver docker-container \ - --driver-opt network=host \ - --driver-opt 'env.HTTP_PROXY=http://192.168.5.200:7890' \ - --driver-opt 'env.HTTPS_PROXY=http://192.168.5.200:7890' \ - --driver-opt 'env.NO_PROXY=reg.nxsir.cn' \ - --driver-opt 'env.http_proxy=http://192.168.5.200:7890' \ - --driver-opt 'env.https_proxy=http://192.168.5.200:7890' \ - --driver-opt 'env.no_proxy=reg.nxsir.cn' \ - --use - fi sudo docker buildx inspect --builder ${BUILDER_NAME} --bootstrap >/dev/null echo 'Building and pushing multi-arch Web image: ${WEB_IMAGE_TAGGED}' - run_with_heartbeat /tmp/live-recorder-web-buildx-${IMAGE_TAG}.log \ + run_with_heartbeat /tmp/live-recorder-web-buildx-${IMAGE_TAG}.log "Web multi-arch build" \ sudo docker buildx build \ --builder ${BUILDER_NAME} \ --platform ${TARGET_PLATFORMS} \ --network host \ --progress=plain \ --provenance=false \ + --cache-from type=registry,ref=${WEB_CACHE_IMAGE} \ + --cache-to type=registry,ref=${WEB_CACHE_IMAGE},mode=max \ --build-arg NODE_IMAGE=${WEB_NODE_IMAGE} \ --build-arg NGINX_IMAGE=${WEB_NGINX_IMAGE} \ - --build-arg HTTP_PROXY=http://192.168.5.200:7890 \ - --build-arg HTTPS_PROXY=http://192.168.5.200:7890 \ - --build-arg NO_PROXY=127.0.0.1,localhost,reg.nxsir.cn,gitea.nxsir.cn \ - --build-arg http_proxy=http://192.168.5.200:7890 \ - --build-arg https_proxy=http://192.168.5.200:7890 \ - --build-arg no_proxy=127.0.0.1,localhost,reg.nxsir.cn,gitea.nxsir.cn \ + --build-arg HTTP_PROXY=${HTTP_PROXY_URL} \ + --build-arg HTTPS_PROXY=${HTTP_PROXY_URL} \ + --build-arg NO_PROXY=${NO_PROXY_HOSTS} \ + --build-arg http_proxy=${HTTP_PROXY_URL} \ + --build-arg https_proxy=${HTTP_PROXY_URL} \ + --build-arg no_proxy=${NO_PROXY_HOSTS} \ -f frontend/Dockerfile \ --build-arg VITE_API_BASE_URL=/api \ -t ${WEB_IMAGE_TAGGED} \ diff --git a/src/LiveRecorder.WebApi/Dockerfile b/src/LiveRecorder.WebApi/Dockerfile index 451cff1..4608037 100644 --- a/src/LiveRecorder.WebApi/Dockerfile +++ b/src/LiveRecorder.WebApi/Dockerfile @@ -17,9 +17,9 @@ RUN dotnet publish "src/LiveRecorder.WebApi/LiveRecorder.WebApi.csproj" -c Relea 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 apt-get update -o Acquire::ForceIPv4=true \ - && apt-get install -o Acquire::ForceIPv4=true -y --no-install-recommends ffmpeg nodejs ca-certificates curl jq \ +RUN sed -i 's|deb.debian.org|mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list.d/debian.sources \ + && 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 \ && rm -rf /var/lib/apt/lists/* WORKDIR /app