fix(ci): 消除 preflight Set up job docker pull 卡点,改用宿主机 Node 22 + daemon.json mirrors + Dockerfile ARG 双保险

- preflight:删除 container.image: node:22-bookworm-slim,避免 Runner 在 Set up job 阶段独立 docker pull(国内连 Hub 被限速一直卡)
- preflight:改用 runs-on 直出 + actions/setup-node@v4 装 Node 22,npm registry 设 npmmirror
- build-image:python3 合法合成 /etc/docker/daemon.json 注入 3 组 docker.io registry mirrors(daocloud/1panel/1ms.run),systemctl→service→失败跳过 三级 non-intrusive 重启 docker
- Dockerfile:新增全局 ARG DOCKER_MIRROR / NODE_BUILDER_TAG / NODE_RUNTIME_TAG,FROM 统一前缀化;本地开发 DOCKER_MIRROR 为空时等价原写法,体验不变
- buildx BUILD_ARGS:新增 3 个 --build-arg 把 DOCKER_MIRROR_PREFIX / NODE_BUILDER_TAG / NODE_RUNTIME_TAG 传入,CI 拉 node:22-alpine 必走国内源
- 修复后:workflow 触发时 Preflight 日志不会再出现 Starting job container / docker pull image=node:***-bookworm-slim;前面 system-settings defaults 兜底修复可顺利部署上线
This commit is contained in:
2026-09-11 21:59:19 +08:00
parent 13b9b72170
commit 124280a92f
2 changed files with 85 additions and 36 deletions
+72 -34
View File
@@ -36,52 +36,45 @@ env:
APT_MIRROR_UBUNTU_SECURITY_HTTP: http://mirrors.tuna.tsinghua.edu.cn/ubuntu-security
HTTP_PROXY_EXAMPLE: ""
HTTPS_PROXY_EXAMPLE: ""
# ========== Docker 官方镜像国内加速(Runner 拉 node:alpine / buildkit 等最常见卡点) ==========
# 注意:如果你知道哪个镜像源在内网最快,可以在仓库 Variables 里覆盖 DOCKER_REGISTRY_MIRROR_1/2/3
DOCKER_REGISTRY_MIRROR_1: https://docker.m.daocloud.io
DOCKER_REGISTRY_MIRROR_2: https://docker.1panel.live
DOCKER_REGISTRY_MIRROR_3: https://docker.1ms.run
# Dockerfile 内 FROM 前缀替换(ARG DOCKER_MIRROR=…),避免 buildx build 内部 FROM node:22-alpine 再被 Hub 限速
DOCKER_MIRROR_PREFIX: docker.m.daocloud.io/library/
NODE_BUILDER_TAG: "22-alpine"
NODE_RUNTIME_TAG: "22-alpine"
jobs:
preflight:
name: Preflight 语法与构建检查
runs-on: ubuntu-latest
timeout-minutes: 15
container:
image: node:22-bookworm-slim
# 关键修复:去掉 container.image: node:22-bookworm-slim
# 原因:Runner 在 Set up job 阶段会先 docker pull 这个镜像,国内连 Docker Hub 被限速会一直卡转圈。
# 直接在 Runner 宿主机上执行(通常自带 node 20+);为保证 Node 22 一致性,用 actions/setup-node 主动安装。
steps:
- name: 安装基础运行依赖(git/ca-certificates,已换清华 TUNA 源)
- name: 安装基础运行依赖(git/curl/ca-certificates,Runner 自带)
run: |
set -euxo pipefail
# ========== Step 0:先用 HTTP 清华源装 ca-certificates(解鸡生蛋:HTTPS 需要证书,证书得先用 HTTP 装) ==========
SOURCES_FILE="/etc/apt/sources.list.d/debian.sources"
if [ -f "${SOURCES_FILE}" ]; then
sed -i "s|http://deb.debian.org/debian|${APT_MIRROR_DEBIAN_HTTP}|g" "${SOURCES_FILE}"
sed -i "s|http://deb.debian.org/debian-security|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|g" "${SOURCES_FILE}"
sed -i "s|https://deb.debian.org/debian|${APT_MIRROR_DEBIAN_HTTP}|g" "${SOURCES_FILE}"
sed -i "s|https://deb.debian.org/debian-security|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|g" "${SOURCES_FILE}"
else
if [ -f /etc/apt/sources.list ]; then
sed -i "s|http://deb.debian.org/debian|${APT_MIRROR_DEBIAN_HTTP}|g" /etc/apt/sources.list
sed -i "s|https://deb.debian.org/debian|${APT_MIRROR_DEBIAN_HTTP}|g" /etc/apt/sources.list
sed -i "s|http://security.debian.org/debian-security|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|g" /etc/apt/sources.list
sed -i "s|https://security.debian.org/debian-security|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|g" /etc/apt/sources.list
fi
fi
apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends ca-certificates
update-ca-certificates 2>/dev/null || true
command -v git || (apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends git ca-certificates)
command -v curl || (apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends curl)
command -v node && node -v || true
command -v npm && npm -v || true
# ========== Step 1:现在有了证书,换成 HTTPS 清华源(更安全)+ 装 git/curl ==========
if [ -f "${SOURCES_FILE}" ]; then
sed -i "s|${APT_MIRROR_DEBIAN_HTTP}|${APT_MIRROR_DEBIAN}|g" "${SOURCES_FILE}"
sed -i "s|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|${APT_MIRROR_DEBIAN_SECURITY}|g" "${SOURCES_FILE}"
else
if [ -f /etc/apt/sources.list ]; then
sed -i "s|${APT_MIRROR_DEBIAN_HTTP}|${APT_MIRROR_DEBIAN}|g" /etc/apt/sources.list
sed -i "s|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|${APT_MIRROR_DEBIAN_SECURITY}|g" /etc/apt/sources.list
fi
fi
apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends git curl
rm -rf /var/lib/apt/lists/*
- name: 使用 Node.js 22(若 Runner 自带版本不足 22 则自动下载)
uses: actions/setup-node@v4
with:
node-version: "22"
- name: 校验 Node + npm + git 可用
run: |
set -euxo pipefail
# 全局 git 代理:任何 git clone/fetch/pull https://github.com/... 自动走 gh-proxy 前缀
git config --system url."${GH_PROXY_PREFIX}https://github.com/".insteadOf "https://github.com/" || true
# npm registry 走 npmmirror,避免后续 npm ci 也卡
npm config set registry https://registry.npmmirror.com >/dev/null 2>&1 || true
git --version
node -v
npm -v
@@ -166,6 +159,48 @@ jobs:
sudo git config --system url."${GH_PROXY_PREFIX}https://github.com/".insteadOf "https://github.com/" || true
# npm:强制用 npmmirror(与 preflight 对齐)
npm config set registry https://registry.npmmirror.com >/dev/null 2>&1 || true
# ========== 关键修复:宿主机 Docker daemon 先注入国内 registry mirrors ==========
# 原因:Runner 任何 docker pull / buildx create(moby/buildkit 拉基础镜像)都要先经过 daemon
# 如果直接连 docker.io,国内会被限速到 <200KB/s,导致 Setup / BuildKit 拉镜像一直卡。
DOCKER_DAEMON_CONF="/etc/docker/daemon.json"
if command -v docker >/dev/null 2>&1 && command -v sudo >/dev/null 2>&1; then
sudo mkdir -p /etc/docker 2>/dev/null || true
OLD_MIRRORS_JSON="{}"
if [ -f "${DOCKER_DAEMON_CONF}" ]; then
OLD_MIRRORS_JSON="$(sudo cat "${DOCKER_DAEMON_CONF}" 2>/dev/null || echo "{}")"
fi
# 用 python3 合成合法 JSON(避免 bash 手搓 JSON 转义坑)
NEW_DAEMON_JSON="$(
python3 - "$OLD_MIRRORS_JSON" \
"${DOCKER_REGISTRY_MIRROR_1}" "${DOCKER_REGISTRY_MIRROR_2}" "${DOCKER_REGISTRY_MIRROR_3}" <<'PY'
import json, sys
try:
data = json.loads(sys.argv[1] or "{}")
except Exception:
data = {}
mirrors_envs = [m for m in sys.argv[2:5] if m]
existing = data.get("registry-mirrors") or []
if isinstance(existing, list):
combined = list(dict.fromkeys([*mirrors_envs, *existing]))
else:
combined = mirrors_envs
if combined:
data["registry-mirrors"] = combined
data.setdefault("log-driver", "json-file")
print(json.dumps(data, ensure_ascii=False, indent=2))
PY
)"
echo "${NEW_DAEMON_JSON}" | sudo tee "${DOCKER_DAEMON_CONF}" >/dev/null
echo "[Docker] daemon.json 已注入 registry-mirrors:"
sudo cat "${DOCKER_DAEMON_CONF}" 2>/dev/null || true
# 非侵入式重启 docker;runner 没 systemd 时用 service 兜底;失败也跳过(buildkitd.toml 内部仍有 mirrors)
sudo systemctl restart docker 2>/dev/null \
|| sudo service docker restart 2>/dev/null \
|| echo "[Docker] systemctl/service 重启失败,跳过(后续 buildx builder 内部仍有 registry mirrors)"
sleep 3 2>/dev/null || true
fi
echo "环境准备完成"
cat /etc/os-release 2>/dev/null | head -4 || true
docker --version
@@ -307,6 +342,9 @@ jobs:
BUILD_ARGS=(
--build-arg BUILDKIT_INLINE_CACHE=1
--build-arg NODE_ENV=production
--build-arg DOCKER_MIRROR="${DOCKER_MIRROR_PREFIX}"
--build-arg NODE_BUILDER_TAG="${NODE_BUILDER_TAG}"
--build-arg NODE_RUNTIME_TAG="${NODE_RUNTIME_TAG}"
)
# 说明:暂时关闭 registry 分层缓存(buildkitd 推 buildcache 也要认证,同样会触发 Gitea 1.27 OAuth2 空 token)
# 改为本地 Docker daemon 缓存,已构建的层会自动复用,下次 build 速度几乎相同