本文档说明如何在本地/生产环境修改 web 前端代码,重新构建镜像,并在基于 compose.release.yml 的部署上完成滚动升级。

.env.release(由 .env.release.draft 复制修改得到)compose.release.yml 中 web 服务的镜像引用为:
image: ${SKILLHUB_WEB_IMAGE:-skillhub-web}:${SKILLHUB_VERSION:-latest}
pull_policy: never
pull_policy: never意味着 Docker 不会从镜像仓库拉取,只会使用本地同名同 tag 的镜像。所以打包出来的镜像名与 tag 必须和.env.release中的SKILLHUB_WEB_IMAGE+SKILLHUB_VERSION完全一致,否则就会"用不上新镜像"。
.env.release 建立 .env 软链接docker compose 默认会自动加载当前目录下的 .env 文件。给 .env.release 建一个软链接到 .env 后,后续所有命令就可以 省略 --env-file .env.release,直接写 docker compose -f compose.release.yml ...。
Linux / macOS:
# 仓库根目录执行,一次即可
ln -sf .env.release .env
Windows(PowerShell,管理员):
# 推荐使用软链接;如遇权限问题可改用 New-Item -ItemType HardLink
New-Item -ItemType SymbolicLink -Path .env -Target .env.release
Windows(cmd,管理员):
mklink .env .env.release
建立之后,所有 docker compose 命令都可以简化:
# 原命令
docker compose --env-file .env.release -f compose.release.yml up -d web
# 简化后
docker compose -f compose.release.yml up -d web
注意:
.env不要提交到 Git;且只应指向当前环境真正使用的那一份 env(如生产机指向.env.release,测试机指向.env.staging)。
cd web
pnpm install --frozen-lockfile # 首次或依赖变更后执行
pnpm dev # 启动 vite dev server
浏览器会自动打开开发服务器。修改 web/src/** 下的 .ts/.tsx 代码会热更新。
cd web
pnpm typecheck # TypeScript 类型检查
pnpm lint # 代码风格检查
pnpm test # 单元测试
pnpm build # 产物构建到 web/dist/
任何一步失败,都不要进入打包流程。
假设 .env.release 中:
SKILLHUB_WEB_IMAGE=ghcr.io/iflytek/skillhub-web
SKILLHUB_VERSION=v0.1.0-beta.5
则打包命令(在仓库根目录执行):
# PowerShell
docker build `
-t ghcr.io/iflytek/skillhub-web:v0.1.0-beta.5 `
-f web/Dockerfile `
web
# bash
docker build \
-t ghcr.io/iflytek/skillhub-web:v0.1.0-beta.5 \
-f web/Dockerfile \
./web
如果只是本机测试,不想写那么长的仓库前缀,可以修改 .env.release:
SKILLHUB_WEB_IMAGE=skillhub-web
SKILLHUB_VERSION=local
然后打包:
docker build -t skillhub-web:local -f web/Dockerfile ./web
关键:
docker build -t :里的 name 和 tag,必须等于SKILLHUB_WEB_IMAGE:SKILLHUB_VERSION。
docker images | grep skillhub-web
# 关注 IMAGE ID 是否变化、CREATED 是否是"几秒前"
如果 IMAGE ID 没变,说明你的代码没真的进到构建产物里(比如 build 失败、或者 build context 不对)。
仅仅 docker compose up -d 有时不会重建容器,导致你看到的还是老版本。正确的升级流程如下:
docker compose --env-file .env.release -f compose.release.yml ps
docker inspect --format "{{.Image}} {{.Config.Image}}"
把拿到的 image ID 跟 docker images 里新 build 出来的那个对比,确认不一致时才需要升级。
docker compose --env-file .env.release -f compose.release.yml up -d --force-recreate web
docker compose --env-file .env.release -f compose.release.yml stop web
docker compose --env-file .env.release -f compose.release.yml rm -f web
docker compose --env-file .env.release -f compose.release.yml up -d web
web 服务自带健康检查:http://127.0.0.1/nginx-health
docker compose --env-file .env.release -f compose.release.yml ps
# STATUS 列出现 (healthy) 即升级成功
curl -I http://127.0.0.1/ # 或替换为实际 WEB_PORT
保留上一版本的镜像 tag(例如 v0.1.0-beta.4),回滚只需:
# 方法一:临时覆盖 env
SKILLHUB_VERSION=v0.1.0-beta.4 \
docker compose --env-file .env.release -f compose.release.yml up -d --force-recreate web
# 方法二:改回 .env.release 的 SKILLHUB_VERSION,然后再 up -d --force-recreate web
建议不要给旧镜像打
latest、也不要复用老 tag,这样才能随时回滚。
| 现象 | 可能原因 | 解决 |
|---|---|---|
| 打包成功但页面没变化 | 浏览器或 CDN 缓存 | Ctrl+F5 强刷;检查 CDN 规则 |
| 打包成功但容器没更新 | 没有 --force-recreate |
按"四.2"执行 |
| 容器一直用老镜像 | 打包 tag 与 env 不一致 | 核对 SKILLHUB_WEB_IMAGE 与 SKILLHUB_VERSION |
| 拉不到镜像 | pull_policy: never,但本地没有该 tag |
本地 build,或临时删掉 pull_policy 并 docker compose pull web |
| 构建失败 | pnpm install --frozen-lockfile 与 lockfile 不一致 |
先 pnpm install 更新 lockfile,再提交并重新构建 |
| nginx 启动失败 | 运行时配置模板注入失败 | 查看 web/docker-entrypoint.d/30-runtime-config.sh 与 web/runtime-config.js.template |
# 1. 代码侧校验
cd web
pnpm install --frozen-lockfile
pnpm typecheck; pnpm lint; pnpm build
cd ..
# 2. 打包镜像(注意 tag 与 .env.release 对齐)
docker build -t ghcr.io/iflytek/skillhub-web:v0.1.0-beta.5 -f web/Dockerfile web
# 3. 重建 web 容器
docker compose --env-file .env.release -f compose.release.yml up -d --force-recreate web
# 4. 查看状态
docker compose --env-file .env.release -f compose.release.yml ps
docker compose --env-file .env.release -f compose.release.yml logs --tail=100 web
至此,web 服务的修改、打包、升级流程完成。