Skip to content

Commit d6374d4

Browse files
committed
fix: prepare 0.4.6 playwright docker release
1 parent a089474 commit d6374d4

5 files changed

Lines changed: 94 additions & 29 deletions

File tree

Dockerfile

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,41 @@
1-
ARG APP_VERSION=0.4.5
1+
ARG APP_VERSION=0.4.6
22
ARG VCS_REF=
33
ARG PYTHON_IMAGE=3.11
44
ARG VARIANT=
55
ARG APT_MIRROR=
66
ARG PIP_INDEX_URL=
77
ARG PIP_EXTRA_INDEX_URL=
88
ARG PIP_TRUSTED_HOST=
9+
ARG SKIP_FRONTEND_BUILD=0
910

1011
FROM node:20 AS frontend-build
1112

13+
ARG SKIP_FRONTEND_BUILD=0
14+
1215
WORKDIR /app
1316

17+
COPY nb_cli_plugin_webui/dist/ nb_cli_plugin_webui/dist/
1418
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml ./
1519
COPY frontend/package.json frontend/
1620

17-
RUN corepack enable && pnpm install --frozen-lockfile
21+
RUN if [ "$SKIP_FRONTEND_BUILD" != "1" ]; then \
22+
corepack enable && pnpm install --frozen-lockfile; \
23+
fi
1824

1925
COPY frontend/ frontend/
2026

21-
RUN pnpm -C frontend run build-only
27+
RUN if [ "$SKIP_FRONTEND_BUILD" != "1" ]; then \
28+
pnpm -C frontend run build-only; \
29+
fi
2230

2331
FROM python:${PYTHON_IMAGE}${VARIANT:+-$VARIANT} AS build-stage
2432

25-
ARG APP_VERSION=0.4.5
33+
ARG APP_VERSION=0.4.6
2634
ARG VCS_REF=unknown
2735
ARG PIP_INDEX_URL
2836
ARG PIP_EXTRA_INDEX_URL
2937
ARG PIP_TRUSTED_HOST
38+
ARG SKIP_FRONTEND_BUILD=0
3039

3140
RUN if [ -n "$PIP_INDEX_URL$PIP_EXTRA_INDEX_URL$PIP_TRUSTED_HOST" ]; then \
3241
printf '[global]\n' > /etc/pip.conf; \
@@ -51,9 +60,10 @@ RUN pip install --no-deps .
5160

5261
FROM python:${PYTHON_IMAGE}${VARIANT:+-$VARIANT}
5362

54-
ARG APP_VERSION=0.4.5
63+
ARG APP_VERSION=0.4.6
5564
ARG VCS_REF=unknown
5665
ARG APT_MIRROR
66+
ARG SKIP_FRONTEND_BUILD=0
5767
EXPOSE 18080
5868

5969
# 创建挂载目录
@@ -92,12 +102,16 @@ RUN if [ -n "$APT_MIRROR" ]; then \
92102
fi \
93103
&& apt-get -o Acquire::http::Proxy=false -o Acquire::https::Proxy=false update \
94104
&& apt-get -o Acquire::http::Proxy=false -o Acquire::https::Proxy=false install -y --no-install-recommends \
105+
libasound2t64 \
95106
libnspr4 \
96107
libnss3 \
97108
libdbus-1-3 \
98109
libatk1.0-0t64 \
99110
libatk-bridge2.0-0t64 \
100111
libcups2t64 \
112+
libevent-2.1-7t64 \
113+
libharfbuzz-icu0 \
114+
libicu76 \
101115
libxkbcommon0 \
102116
libatspi2.0-0t64 \
103117
libxcomposite1 \
@@ -117,7 +131,10 @@ RUN if [ -n "$APT_MIRROR" ]; then \
117131
libwoff1 \
118132
libvpx9 \
119133
libopus0 \
134+
libwebpdemux2 \
135+
libwebpmux3 \
120136
libflite1 \
137+
libxslt1.1 \
121138
libjxl0.11 \
122139
libavif16 \
123140
libenchant-2-2 \
@@ -126,11 +143,10 @@ RUN if [ -n "$APT_MIRROR" ]; then \
126143
libmanette-0.2-0 \
127144
libgles2 \
128145
libx264-164 \
129-
libasound2t64 \
130146
&& ln -sf /usr/lib/x86_64-linux-gnu/libx264.so.164 /usr/lib/x86_64-linux-gnu/libx264.so \
131147
&& rm -rf /var/lib/apt/lists/*
132148

133-
CMD nb ui run
149+
CMD ["nb", "ui", "run"]
134150

135151
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
136152
CMD python -c "import json,sys,urllib.request; from pathlib import Path; path=Path('/app/config.json'); port=str((json.loads(path.read_text(encoding='utf-8')).get('port') if path.exists() else None) or '18080'); urllib.request.urlopen(f'http://127.0.0.1:{port}', timeout=5); sys.exit(0)"

README.md

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ _✨ 面向 NoneBot 多实例运维的 WebUI ✨_
7777
- `docker.io/xisoul/nonebot-webui:master`
7878
- `docker.io/xisoul/nonebot-webui:${version}`
7979

80-
推荐优先使用显式版本号,例如 `0.4.5``0.4`,后面做升级、回滚、版本检测会更方便。
80+
推荐优先使用显式版本号,例如 `0.4.6``0.4`,后面做升级、回滚、版本检测会更方便。
8181

8282
### 非 Docker 安装
8383

@@ -166,7 +166,16 @@ WebUI 会自动把它解析并保存为容器内的真实绝对路径。
166166

167167
另外,添加的目录本身需要是一个 NoneBot 项目根目录,至少应当能看到 `pyproject.toml`。如果 `pyproject.toml` 在子目录里,就填写那个子目录,不要填到父目录。
168168

169-
本镜像当前不内置 Playwright Linux 系统依赖;若你管理的外部项目自身依赖 Playwright,请在对应项目运行环境中单独安装。
169+
本镜像已内置 WebUI 预装 `nonebot_plugin_htmlrender` / Playwright Chromium 常见所需的 Linux 运行库。
170+
171+
如果你的外部项目依赖 Playwright,WebUI 在启动实例前会优先尝试用该项目自己的 Python 环境执行:
172+
173+
```shell
174+
python -m playwright install chromium
175+
```
176+
177+
浏览器二进制仍然安装在实例运行时可见的目录里,不会直接打进项目仓库。
178+
如果你的网络环境使用 SOCKS 代理,WebUI 会继续保留实例代理环境用于下载 Chromium,但系统库仍然依赖当前 WebUI 容器镜像提供。
170179

171180
### 登录说明
172181

@@ -213,6 +222,15 @@ docker logs nonebot-webui
213222
- `WEBUI_PIP_EXTRA_INDEX_URL`
214223
- `WEBUI_PIP_TRUSTED_HOST`
215224

225+
### 本地镜像排查
226+
227+
如果你是在本机或 WSL 里排查 Docker 镜像问题,仓库额外提供了一个只用于调试的构建参数:
228+
229+
- `SKIP_FRONTEND_BUILD=1`
230+
231+
它会直接复用仓库内现成的 `nb_cli_plugin_webui/dist`,跳过 Node / pnpm 的前端重新构建步骤,方便先验证 Python、Playwright、Linux 运行库和实例启动链路。
232+
正式发布时默认不要开启这个参数,仍应走完整前端构建流程。
233+
216234
## 常见提醒
217235

218236
- WebUI 新建实例默认放在 `/projects`
@@ -221,7 +239,7 @@ docker logs nonebot-webui
221239
- 如果实例根目录里没有 `pyproject.toml`,说明你填错目录层级了
222240
- 首次登录凭证请去容器日志里看
223241
- 想回头找 token,直接看容器日志,不是在页面里反查
224-
- 如果某些插件依赖 Playwright 或系统库,请在对应机器人项目自己的运行环境里安装,不是装在 WebUI 容器里
242+
- 如果某些插件依赖 Playwright,优先让 WebUI 在实例启动前自动预装;若项目还有额外浏览器或系统库要求,再按该项目自身文档补充
225243

226244
## 发布流程
227245

@@ -245,20 +263,20 @@ docker logs nonebot-webui
245263
- `${major}.${minor}`
246264
- `${version}`
247265

248-
例如版本 `0.4.5` 会自动生成:
266+
例如版本 `0.4.6` 会自动生成:
249267

250268
- `xisoul/nonebot-webui:latest`
251269
- `xisoul/nonebot-webui:master`
252270
- `xisoul/nonebot-webui:0.4`
253-
- `xisoul/nonebot-webui:0.4.5`
271+
- `xisoul/nonebot-webui:0.4.6`
254272

255273
### 推荐发版步骤
256274

257275
1. 修改代码并在本地测试通过
258276
2. 更新 `pyproject.toml` 中的版本号
259277
3. 同步更新 `Dockerfile` 中的 `APP_VERSION`
260278
4. 提交代码
261-
5. 打版本 tag,例如 `v0.4.5`
279+
5. 打版本 tag,例如 `v0.4.6`
262280
6. 推送 `master` 和对应 tag
263281

264282
示例:
@@ -268,8 +286,8 @@ git add .
268286
git commit -m "feat: your change"
269287
git push origin master
270288

271-
git tag v0.4.5
272-
git push origin v0.4.5
289+
git tag v0.4.6
290+
git push origin v0.4.6
273291
```
274292

275293
### 重要说明

RELEASE_TODO_2026-05-01.md

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Release Notes Draft 2026-05-01
22

3-
这份清单用于记录 `0.4.5` 计划带上的修复项。
3+
这份清单用于记录 `0.4.6` 计划带上的修复项。
44

5-
## 0.4.5 已纳入修复
5+
## 0.4.6 已纳入修复
66

77
### 1. Docker / NAS 创建容器体验修复
88

@@ -64,21 +64,27 @@
6464
- 改为统一走 `get_version()`
6565
- 修复改包名后镜像启动 `PackageNotFoundError`
6666

67-
## 本次明确不纳入发版
68-
69-
### htmlrender / Playwright 下载链路
67+
### 7. htmlrender / Playwright 启动前预装与 Linux 依赖补齐
7068

7169
- 文件:
70+
- `Dockerfile`
71+
- `README.md`
7272
- `nb_cli_plugin_webui/app/process/service.py`
73-
- 原因:
74-
- 当前不同平台行为差异大
75-
- 你已经明确说明这条先不动,后面有时间再单独测试
76-
- 不建议在这次发版里继续混入 htmlrender 下载策略调整
73+
- 内容:
74+
- WebUI 启动实例前会先尝试用项目自己的 Python 环境执行 `python -m playwright install chromium`
75+
- `nonebot_plugin_htmlrender` 场景下统一补齐 `PLAYWRIGHT_BROWSERS_PATH` 和下载超时等运行时环境
76+
- Docker 镜像内补齐 Playwright Chromium 常见 Linux 运行库,覆盖 `libicu76``libxslt1.1``libevent-2.1-7t64``libwebpdemux2``libwebpmux3``libharfbuzz-icu0` 等缺失项
77+
- 遇到 SOCKS 代理时,日志会明确说明系统库依赖镜像内提供,避免把插件内部 `--with-deps` 失败误判成浏览器未下载
78+
79+
## 本次测试备注
80+
81+
- WSL 侧 Docker `buildx` 插件曾出现段错误,已在本机补装系统包版 `docker-buildx`
82+
- 当前仓库额外加入了 `SKIP_FRONTEND_BUILD=1` 构建开关,仅用于本地/WSL 排查镜像问题时复用现成前端产物;默认发布流程仍走完整前端构建
7783

7884
## 发版前建议确认
7985

80-
1. 确认 `pyproject.toml` 版本号与待打 tag `v0.4.5` 一致
81-
2. 确认 `Dockerfile``APP_VERSION` 已同步更新到 `0.4.5`
82-
3. 确认这次不包含 `htmlrender` 下载源策略调整
83-
4. 构建镜像后优先验证 NAS 容器创建页是否还会自动带出错误挂载
86+
1. 确认 `pyproject.toml` 版本号与待打 tag `v0.4.6` 一致
87+
2. 确认 `Dockerfile``APP_VERSION` 已同步更新到 `0.4.6`
88+
3. 构建镜像后优先验证 `nonebot_plugin_htmlrender` 项目的 Playwright Chromium 预装与启动
89+
4. 复测 NAS / Docker 场景下的路径映射与默认挂载说明
8490
5. 复测“添加实例失败”场景,确认不再留脏记录

nb_cli_plugin_webui/app/process/service.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,13 @@ def _default_nonebot2_data_dir(env: dict) -> Path:
217217
return home_dir / ".local" / "share" / "nonebot2"
218218

219219

220+
def _is_socks_proxy_url(value: str) -> bool:
221+
normalized = str(value or "").strip().lower()
222+
return normalized.startswith(
223+
("socks4://", "socks4a://", "socks5://", "socks5h://")
224+
)
225+
226+
220227
def _clear_stale_htmlrender_dirlock(env: dict, log_storage: Optional[LogStorage] = None) -> None:
221228
lock_path = (
222229
_default_nonebot2_data_dir(env)
@@ -629,6 +636,7 @@ async def _background_install() -> None:
629636
or str(env.get("HTTPS_PROXY") or env.get("https_proxy") or "").strip()
630637
or str(env.get("HTTP_PROXY") or env.get("http_proxy") or "").strip()
631638
)
639+
socks_proxy_active = _is_socks_proxy_url(active_proxy)
632640

633641
if log_storage is not None:
634642
await log_storage.add_log(
@@ -666,6 +674,16 @@ async def _background_install() -> None:
666674
),
667675
)
668676
)
677+
if socks_proxy_active:
678+
await log_storage.add_log(
679+
CustomLog(
680+
level="INFO",
681+
message=(
682+
"当前代理为 SOCKS 协议,启动前预装只下载 Playwright Chromium,"
683+
"不依赖 apt 安装系统库;Linux 运行库需由 WebUI 容器镜像预先提供。"
684+
),
685+
)
686+
)
669687
else:
670688
await log_storage.add_log(
671689
CustomLog(
@@ -976,6 +994,13 @@ async def run_nonebot_project(project: project_service.NoneBotProjectManager):
976994
if str(env_data.get("HOST", "")).strip() != host:
977995
project.write_to_env(project_meta.use_env, "HOST", host)
978996

997+
await _ensure_htmlrender_browser_ready(
998+
project_meta,
999+
env,
1000+
log_storage=log_storage,
1001+
block=True,
1002+
)
1003+
9791004
process = ProcessManager.get_process(project_meta.project_id)
9801005
if process:
9811006
if process.refresh_runtime_state():

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "nb-cli-plugin-webui-xisoul"
3-
version = "0.4.5"
3+
version = "0.4.6"
44
description = "web ui support for nb-cli"
55
authors = ["Kyomotoi <kyomotoiowo@gmail.com>"]
66
license = "MIT"

0 commit comments

Comments
 (0)