From 4de44923547a2bdfb94b03050bd7c90818a62889 Mon Sep 17 00:00:00 2001 From: cqh963852 Date: Thu, 8 Oct 2026 20:55:15 +0800 Subject: [PATCH] =?UTF-8?q?ci:=20=E5=9F=BA=E5=BA=A7=E5=88=87=20idealjs/nod?= =?UTF-8?q?e:24.21.0-bookworm-slim=EF=BC=88crane=20=E7=9B=B4=E4=BC=A0?= =?UTF-8?q?=E8=BD=AC=E6=8E=A8=EF=BC=8Cdigest=20=E4=B8=80=E8=87=B4=EF=BC=89?= =?UTF-8?q?=EF=BC=9BDockerfile=20=E7=A7=BB=E4=BB=93=E5=BA=93=E6=A0=B9?= =?UTF-8?q?=EF=BC=8C=E6=8C=89=20=E4=BE=9D=E8=B5=96=E6=B8=85=E5=8D=95?= =?UTF-8?q?=E2=86=92=E5=AE=89=E8=A3=85=E2=86=92=E6=89=93=E5=8C=85=20?= =?UTF-8?q?=E5=88=86=E5=B1=82=EF=BC=8Cyarn4=20=E7=9B=B4=E8=B0=83=20yarnPat?= =?UTF-8?q?h=20=E8=84=9A=E6=9C=AC=E5=85=8D=20corepack=EF=BC=9BCI=20?= =?UTF-8?q?=E5=9F=BA=E5=BA=A7=E8=B5=B0=20VPC=20=E5=86=85=E7=BD=91=E7=AB=AF?= =?UTF-8?q?=E7=82=B9=E3=80=81=E5=87=AD=E6=8D=AE=E6=8B=86=E5=8F=8C=20secret?= =?UTF-8?q?=20printf=20=E7=99=BB=E5=BD=95=E3=80=81=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E5=90=8E=E7=99=BB=E5=87=BA=E6=B8=85=E5=87=AD=E6=8D=AE=E3=80=81?= =?UTF-8?q?=E5=88=A0=E4=BA=A7=E7=89=A9=E4=B8=8A=E4=BC=A0=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 8 +++++ .gitea/workflows/build-tutorial.yml | 50 ++++++++--------------------- Dockerfile | 23 +++++++++++++ apps/tutorial/Dockerfile | 13 -------- 4 files changed, 45 insertions(+), 49 deletions(-) create mode 100644 Dockerfile delete mode 100644 apps/tutorial/Dockerfile diff --git a/.dockerignore b/.dockerignore index eb4927c..c0e1594 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,3 +6,11 @@ **/playwright-report apps/design-lab/e2e .zcode* +.env +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions diff --git a/.gitea/workflows/build-tutorial.yml b/.gitea/workflows/build-tutorial.yml index cb786ee..14e6008 100644 --- a/.gitea/workflows/build-tutorial.yml +++ b/.gitea/workflows/build-tutorial.yml @@ -1,10 +1,9 @@ name: Build Tutorial # 主仓库 gitea.idealjs.com/idealjs/stack 的 CI:打包新教程站。 -# 构建环境全部封装在 apps/tutorial/Dockerfile(node24-alpine + yarn4 + npmmirror), +# 构建环境全部封装在仓库根 Dockerfile(node24-bookworm-slim + yarn4 + npmmirror), # runner 用 buildah 无 daemon 执行——不依赖 runner 宿主的 node/docker,也不碰 github.com。 -# 源码:gitea API tarball(同机房) -# 产物:滚动 release「ci-dist」资产(node 取自镜像挂载层,原生 fetch 上传) +# 源码:gitea API tarball(同机房);产物留在镜像 stack-tutorial:ci 内(/repo/apps/tutorial/dist) on: push: branches: [main] @@ -24,7 +23,7 @@ jobs: run: | wget -q "$API/archive/$GITHUB_SHA.tar.gz" -O /tmp/src.tgz tar -xzf /tmp/src.tgz --strip-components=1 - ls apps/tutorial/Dockerfile + ls Dockerfile - name: 装 buildah(runner 无 docker;buildah 无 daemon 即可构建) run: | @@ -35,41 +34,20 @@ jobs: - name: buildah 登录阿里云镜像仓(基座为私有 idealjs/node) env: - ALIYUN_AUTH: ${{ secrets.ALIYUN_AUTH }} + ALIYUN_DOCKER_USERNAME: ${{ secrets.ALIYUN_DOCKER_USERNAME }} + ALIYUN_DOCKER_PASSWORD: ${{ secrets.ALIYUN_DOCKER_PASSWORD }} run: | - echo "$ALIYUN_AUTH" | buildah login --username "${ALIYUN_AUTH%%:*}" --password-stdin registry.cn-hangzhou.aliyuncs.com + printf '%s' "$ALIYUN_DOCKER_PASSWORD" | buildah login --username "$ALIYUN_DOCKER_USERNAME" --password-stdin registry.cn-hangzhou.aliyuncs.com + # authfile 按域名区分——构建走 VPC 端点,需单独 login(凭据相同) + printf '%s' "$ALIYUN_DOCKER_PASSWORD" | buildah login --username "$ALIYUN_DOCKER_USERNAME" --password-stdin registry-vpc.cn-hangzhou.aliyuncs.com - name: buildah 构建镜像(环境封装在 Dockerfile) run: | - buildah build --storage-driver=vfs -f apps/tutorial/Dockerfile -t stack-tutorial:ci . + # runner 与镜像仓同 region(杭州)——基座走 VPC 内网端点,快且不占公网带宽 + buildah build --storage-driver=vfs --build-arg BASE_REGISTRY=registry-vpc.cn-hangzhou.aliyuncs.com -f Dockerfile -t stack-tutorial:ci . - - name: 取产物并上传 release(node 取自镜像挂载层) - env: - TOK: ${{ secrets.CI_TOKEN || github.token }} + - name: buildah 登出(清掉 runner 上 auth.json 里的凭据;长驻 runner 不留凭据) + if: always() run: | - CID=$(buildah from localhost/stack-tutorial:ci) - MNT=$(buildah mount "$CID") - ls "$MNT/repo/apps/tutorial/dist/index.html" - tar -czf /tmp/tutorial-dist.tar.gz -C "$MNT/repo/apps/tutorial/dist" . - export LD_LIBRARY_PATH="$MNT/usr/lib" - cat > /tmp/upload.mjs <<'JS' - const API = process.env.API - const H = { Authorization: `token ${process.env.TOK}` } - const j = async (u, opt) => { const r = await fetch(API + u, { ...opt, headers: { ...H, ...(opt?.headers || {}) } }); return { ok: r.ok, status: r.status, data: r.status === 204 ? null : await r.json().catch(() => null) } } - let rid - let r = await j('/releases/tags/ci-dist') - if (r.ok) rid = r.data.id - else { - r = await j('/releases', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tag_name: 'ci-dist', name: 'CI 产物(滚动更新)', body: '每次构建的最新 dist。', draft: false, prerelease: true }) }) - if (r.ok) rid = r.data.id - } - if (!rid) { console.log(`::warning::release 不可用(${r.status})——构建已成功,产物留在 runner`); process.exit(0) } - for (const a of (await j(`/releases/${rid}/assets`)).data || []) await j(`/releases/${rid}/assets/${a.id}`, { method: 'DELETE' }) - const fd = new FormData() - fd.append('attachment', new Blob([await (await import('node:fs/promises')).readFile('/tmp/tutorial-dist.tar.gz')]), 'tutorial-dist.tar.gz') - const up = await fetch(`${API}/releases/${rid}/assets?name=tutorial-dist.tar.gz`, { method: 'POST', headers: H, body: fd }) - console.log(up.ok ? `产物下载:${(await up.json()).browser_download_url}` : `上传失败 ${up.status}`) - JS - "$MNT/usr/local/bin/node" /tmp/upload.mjs - buildah unmount "$CID" >/dev/null 2>&1 || true - buildah rm "$CID" >/dev/null 2>&1 || true + buildah logout registry.cn-hangzhou.aliyuncs.com || true + buildah logout registry-vpc.cn-hangzhou.aliyuncs.com || true diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f4aa7b4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +# 教程站构建镜像——CI 用 buildah(无 daemon)执行,本地 docker/podman build 同样可用。 +# 基座=自家阿里云镜像仓(idealjs/node,由官方 node:24.21.0-bookworm-slim 转推;私有仓,需 login)。 +# 默认公网端点(本地可用);阿里云同 region 的 CI 传 --build-arg BASE_REGISTRY=registry-vpc.cn-hangzhou.aliyuncs.com 走内网。 +ARG BASE_REGISTRY=registry.cn-hangzhou.aliyuncs.com +FROM ${BASE_REGISTRY}/idealjs/node:24.21.0-bookworm-slim + +ENV YARN_NPM_REGISTRY_SERVER=https://registry.npmmirror.com +WORKDIR /workspace + +# ① 依赖配置——只拷贝清单/锁文件/yarn 运行时,源码变更不失效依赖层 +COPY .yarnrc.yml package.json yarn.lock ./ +COPY .yarn/releases/yarn-4.9.2.cjs .yarn/releases/ +COPY apps/tutorial/package.json apps/tutorial/ +COPY apps/design-lab/package.json apps/design-lab/ +COPY packages/design-system/package.json packages/design-system/ +COPY packages/stack-idealjs/package.json packages/stack-idealjs/ + +# ② 安装依赖——yarn 4.9.2 由 yarnPath(.yarn/releases)提供,node 直调脚本,不依赖 corepack/全局 yarn +RUN node .yarn/releases/yarn-4.9.2.cjs install --immutable + +# ③ 打包——monorepo 全量源码(.dockerignore 瘦身,无 node_modules/dist);产物在 /workspace/apps/tutorial/dist +COPY . . +RUN node .yarn/releases/yarn-4.9.2.cjs workspace @stack/tutorial build diff --git a/apps/tutorial/Dockerfile b/apps/tutorial/Dockerfile deleted file mode 100644 index 3e0f639..0000000 --- a/apps/tutorial/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -# 教程站构建镜像——CI 用 buildah(无 daemon)执行,本地 docker/podman build 同样可用。 -# 基座=自家阿里云镜像仓(idealjs/node,由官方 node:24.14.0-alpine 转推;私有仓,CI 需 buildah login)。 -FROM registry.cn-hangzhou.aliyuncs.com/idealjs/node:24.14.0-alpine - -ENV YARN_NPM_REGISTRY_SERVER=https://registry.npmmirror.com -WORKDIR /repo - -# monorepo 全量上下文(.dockerignore 瘦身);依赖与构建同层——lockfile 由 --immutable 锁定 -COPY . . -RUN rm -f /usr/local/bin/yarn /usr/local/bin/yarnpkg \ - && corepack enable \ - && yarn install --immutable \ - && yarn workspace @stack/tutorial build