Files
WechatOnCloud/docker/Dockerfile
Gloridust fda9522b78 fix(critical): 实例镜像 arm64 构建 OOM + 版本耦合无兜底致面板锁死(v1.4.1 连环 P0)
v1.4.1 只发布了面板、实例镜像 CI 失败,叠加版本耦合无兜底 → 用户升级指示器消失、
实例卡在坏的 1.4.0、浏览器仍黑屏。两处修复:

① Dockerfile arm64 OOM:CI 的 QEMU arm64 下第二个 apt 层 OOM(两次 apt-get update +
snapshot 源被后续层反复拉取)。合并为单层一次 update+install、装完即移除 snapshot 源、
Acquire::Languages=none + Retries=3,砍掉内存/网络峰值。本机原生 arm64 构建 + 全套探针
(Chromium 149 / DPI 98304 / CEF 连跑两次 / 30s 零崩溃 / 窗口可见)已验证通过。

② 版本耦合安全兜底:面板偏好「与自身同版本」的实例镜像 tag,但该 tag 在本地和 registry
都不存在时(CI 部分失败/发布时序),原先会指向不存在的 tag → 检测恒空、升级拉不到。
新增 resolveInstanceImage():不可达则回退 :latest,功能永不因版本错配而瘫痪(已运行时验证
9.9.9→latest)。启动时与 ensureImage 前各解析一次。

P0 复盘记录连环成因;待办:改用原生 arm64 runner 替代 QEMU、matrix 失败联动。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 12:11:16 +08:00

96 lines
6.2 KiB
Docker
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# WechatOnCloud —— 在浏览器里访问服务端微信
# 基于 linuxserver 的 KasmVNC 基础镜像(多架构 amd64/arm64
# 自带 Xvfb + openbox + KasmVNC + web 客户端(3000/3001)
FROM lscr.io/linuxserver/baseimage-kasmvnc:debianbookworm
# 微信本体不再在构建时下载/安装,改为运行时由面板点击下载、解压到数据卷 /config
#(见 wechat-ctl.sh。构建时只装中文字体、语言环境、下载工具以及微信运行所
# 需的全部系统库(这些需 root/apt必须 bake 进镜像)。
ENV DEBIAN_FRONTEND=noninteractive
# ⚠️ Chromium 版本锚定(架构守则 R1——绝不跟随 Debian 滚动:
# Debian 源只保留最新版 chromium而新版本在本容器栈KasmVNC/Xvnc + 软件渲染)上反复引入致命崩溃:
# · 149 收紧变换矩阵断言(叠加 DPI bug 全面崩溃v1.4.0 已修 DPI
# · 150 「非首次启动」路径与 --start-maximized 直接 SIGTRAP → 浏览器实例必黑屏(无任何 flag 可绕)。
# 故从 snapshot.debian.org 的固定快照安装验证过的版本。升级 chromium = 显式改下面两行(快照时间戳 +
# 版本号),并跑通 doc/dev/发布门禁.md 的全部探针后才允许合并。
ARG CHROMIUM_SNAPSHOT=20260704T180435Z
ARG CHROMIUM_VERSION=149.0.7827.196-1~deb12u1
# 单层完成所有 apt 安装(此前拆成两层 → 两次 apt-get update在 CI 的 QEMU arm64 模拟下第二次
# update 处理全部源时 OOM "Cannot allocate memory",实例镜像发不出去)。合并为一次 update + 一次
# install并在装完立刻移除 snapshot 源,避免后续 apt 再去慢速快照站Languages=none 跳过翻译文件、
# Retries 抗网络抖动——共同把 QEMU 下的内存/网络压力降到最低。
RUN set -eux; \
echo "deb [check-valid-until=no] https://snapshot.debian.org/archive/debian-security/${CHROMIUM_SNAPSHOT}/ bookworm-security main" \
> /etc/apt/sources.list.d/woc-chromium-pin.list; \
printf 'Package: chromium*\nPin: version %s\nPin-Priority: 1001\n' "${CHROMIUM_VERSION}" \
> /etc/apt/preferences.d/woc-chromium-pin; \
apt-get -o Acquire::Languages=none -o Acquire::Retries=3 update; \
apt-get install -y --no-install-recommends \
curl ca-certificates locales dpkg \
fonts-wqy-zenhei fonts-wqy-microhei fonts-noto-cjk fonts-noto-color-emoji \
libnss3 libgbm1 libasound2 libxss1 \
xz-utils \
chromium="${CHROMIUM_VERSION}" \
xdotool xclip \
xwallpaper xsettingsd \
# 微信原生版是 Qt 程序,依赖一组 xcb 平台库libxcb-cursor0 由 Qt 动态 dlopenldd 查不到,需主动装。
libatomic1 libxdamage1 libxkbcommon-x11-0 \
libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xkb1 libxcb-cursor0 \
# WeChatAppEx 是 Chromium 内核,需 GTK3 全家桶 + 一组 X 扩展 + cups
libgtk-3-0 libatk1.0-0 libatk-bridge2.0-0 libatspi2.0-0 libcups2 \
libxcomposite1 libxrandr2 libxfixes3 libxtst6 libxshmfence1 libdrm2; \
chromium --version; \
rm -f /etc/apt/sources.list.d/woc-chromium-pin.list /etc/apt/preferences.d/woc-chromium-pin; \
sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen; \
locale-gen; \
apt-get clean; \
rm -rf /var/lib/apt/lists/*
# 字体/字体配置目录都在会话 HOME=/config 下(数据卷,运行时才挂载),故不在此预建;
# 由 autostart 在启动时按需 mkdir + 建 ~/.local/share/fonts → /config/.fonts 软链(见 docker/autostart
ENV LANG=zh_CN.UTF-8 \
LC_ALL=zh_CN.UTF-8 \
LIBGL_ALWAYS_SOFTWARE=1
# 改 KasmVNC web 客户端的 webpack 产物 dist/*.bundle.js
# (1) 默认开启 IME 输入模式:本地(客户端)输入法打中文,拼音联想在本地完成、只把成品汉字
# 发进容器,无需容器内装 IME。默认值仅在浏览器未存过该设置时生效不覆盖用户手动改过的偏好。
# (2) 修复 noVNC 中文 IME 输入:原实现靠隐藏 textarea 差分逐字符重发 keysym会泄漏中间拼音、
# 累积不 reset、退格风暴导致大量丢字 / ~21 字卡住 / 跨浏览器不稳。改为只在 compositionend
# 用 e.data 直发成品字符串(详见 woc-www-patch.sh / woc-ime.pl
# 注意:实际加载的是 webpack 产物 dist/main.bundle.jsapp/ui.js 是未打包源码、运行时不加载),故必须改 bundle。
COPY woc-www-patch.sh woc-ime.pl /woc/
RUN chmod 755 /woc/woc-www-patch.sh && chmod 644 /woc/woc-ime.pl && /woc/woc-www-patch.sh
# 微信下载/解压控制脚本(运行时由面板经 docker exec 触发,状态写入数据卷 /config/.woc-state
COPY wechat-ctl.sh /woc/wechat-ctl.sh
RUN chmod 755 /woc/wechat-ctl.sh
# v1.2.0 多应用应用定义app-defs.sh被 autostart/app-ctl 引用)+ 通用安装/状态控制app-ctl.sh
# 微信委托回 wechat-ctl.sh、其它应用各自实现。app-defs.sh 是被 source 的、不需可执行位。
COPY app-defs.sh app-ctl.sh /woc/
RUN chmod 644 /woc/app-defs.sh && chmod 755 /woc/app-ctl.sh
# openbox 会话启动时执行此脚本:等待微信就绪 + 常驻拉起微信 + 最小化自动复原看守
COPY autostart /defaults/autostart
RUN chmod 755 /defaults/autostart
# 启动钩子00给每个实例唯一且持久的 machine-id避免所有实例共用镜像里烤死的同一个
# 触发腾讯"设备农场"风控导致登录即被强制退出。须在 autostart拉起微信之前执行故用 00 前缀。
COPY woc-identity.sh /custom-cont-init.d/00-woc-identity
RUN chmod 755 /custom-cont-init.d/00-woc-identity
# 启动钩子01每次启动用镜像内最新 autostart 覆盖数据卷旧副本(否则旧实例升级后用不上新逻辑)
COPY woc-update-autostart /custom-cont-init.d/01-woc-autostart
RUN chmod 755 /custom-cont-init.d/01-woc-autostart
# 启动钩子02把容器环境 WOC_APP_TYPE 写入 /config/.woc-app供 autostart 选择启动哪个应用。
# 须在 autostart 之前执行;缺 WOC_APP_TYPE 则不写 → autostart 回退微信(向后兼容)。
COPY woc-app-init.sh /custom-cont-init.d/02-woc-app
RUN chmod 755 /custom-cont-init.d/02-woc-app
# 3000 = HTTP web 客户端, 3001 = HTTPS
EXPOSE 3000 3001