# 运行原理与 Docker 指南

> 返回 [← README](../README.md) · 深入设计见 [技术方案.md](技术方案.md)

本篇把「云微怎么跑起来」讲透：先一句话原理 + 架构图，再面向 Docker 新手的逐步拆解。

---

## 工作原理（一句话）

每个微信实例 = 一个容器，里面跑 Xvfb 虚拟显示 + 官方原版微信，KasmVNC 把画面串到浏览器。同一实例被多个浏览器连 = 共享同一个微信会话。**不修改微信客户端**。

前面一层自研 **面板（panel）** 是唯一对外入口：负责账号登录、子账号与**实例权限**管理，经 docker 引擎**按需创建/销毁**微信实例容器，并反向代理到对应实例——浏览器只和面板打交道，KasmVNC 的凭据由面板在服务端注入，不下发前端。

```
浏览器 ──▶ panel(:36080) ──┬─ /               面板 SPA（登录 / 实例网格 / 子账号 / 进入桌面）
            cookie 鉴权     ├─ /api/*           账号、实例、权限接口
                           └─ /desktop/:id/*   反代 → 对应实例 KasmVNC（注入 Basic 鉴权）

panel ──(docker.sock)──▶ docker 引擎 ──▶ 按需创建/销毁微信实例容器 woc-wx-<id>
                                          每个实例 = 独立容器 + 独立数据卷 + 独立微信会话
                                          实例只在 docker 网络内暴露，不直连宿主
```

---

## Docker 运行模式详解（新手向）

如果你对 Docker 不熟，这一节把本项目「怎么跑起来的」讲透。读完你就能看懂上面的图。

### 0. 先认识 5 个 Docker 概念

| 概念 | 一句话理解 | 在本项目里是什么 |
|------|-----------|------------------|
| **镜像 Image** | 只读的「软件安装包」，里面装好了程序和依赖 | `woc-panel`（面板）、`wechat-on-cloud`（微信实例） |
| **容器 Container** | 镜像「运行起来」的实例，相当于「正在跑的程序」。一个镜像能跑出多个容器 | `woc-panel` 容器、多个 `woc-wx-<id>` 容器 |
| **卷 Volume** | 容器之外的持久磁盘。容器删了，卷里的数据还在 | 每个微信实例一个卷 `woc-data-<id>`，存登录态和消息 |
| **网络 Network** | 容器之间互通的「虚拟局域网」，容器之间可用**容器名**当域名互访 | 面板和所有实例在同一网络里，面板用 `http://woc-wx-<id>:3000` 找实例 |
| **docker.sock** | Docker 引擎的「遥控器」（宿主上的一个特殊文件 `/var/run/docker.sock`）。谁拿到它，谁就能指挥 Docker 创建/删除容器 | 挂进面板容器，面板才能「动态造微信实例」 |

> **Compose** 则是「用一个 `docker-compose.yml` 文件描述要跑哪些容器，`docker compose up -d` 一条命令拉起」。本项目的 compose 里**只有面板一个服务**。

### 1. 本项目有两类容器（运行角色不同）

这是本项目最容易迷惑的地方：**不是所有容器都写在 `docker-compose.yml` 里。**

| | ① 面板容器 | ② 微信实例容器 |
|---|-----------|---------------|
| 容器名 | `woc-panel`（固定一个） | `woc-wx-<随机id>`（可有多个） |
| 用哪个镜像 | `woc-panel` | `wechat-on-cloud` |
| 谁来启动 | **你** 执行 `docker compose up -d` | **面板**：你在网页点「新建微信实例」时，面板通过 docker.sock 自动 `docker run` |
| 写在 compose 里吗 | 是 | **否**（运行期动态创建，compose 里看不到） |
| 对外暴露端口 | 是，宿主 `36080` → 容器 `8080` | 否，只在 docker 网络内，由面板反代 |
| 数据存哪 | 宿主目录 `./data-panel` | 各自的命名卷 `woc-data-<id>` |
| 生命周期 | 常驻 | 你在面板「删除实例」时销毁（默认保留卷） |

一句话：**你只手动管面板这一个容器；微信实例是面板帮你按需开关的。** 这就是为什么面板要挂 `docker.sock`——它需要「遥控」Docker 去开关微信实例容器。

### 2. 镜像从哪来：两种「构建/获取」模式

容器要跑，先得有镜像。本项目的两个镜像有两条获取途径，**任选其一**（[README 快速开始](../README.md#快速开始)对应方式 A / B）：

| | 方式 A · 本地自构建 | 方式 B · 拉取官方镜像 |
|---|--------------------|----------------------|
| 怎么做 | `./scripts/build-local.sh`（用本仓库 Dockerfile 在你机器上造镜像） | `docker compose up -d`（自动从 GHCR 下载现成镜像） |
| 适合谁 | 官方还没发布镜像时 / 想自己改代码 / 内网无法访问 GHCR | 普通用户，开箱即用 |
| 前提 | 本机能拉到基础镜像（node、KasmVNC base） | GHCR 上已发布且包为公开（见[发布到 GHCR](发布到GHCR.md)） |
| 产物 | 本地镜像，标签和 compose 里写的一模一样 | 同名镜像，来自云端 |

> compose 的拉取策略是默认值（`missing`）：**本地已有同名镜像就直接用，没有才去 GHCR 拉**。所以方式 A 构建完，`docker compose up -d` 会直接用你的本地镜像，不会再联网。想升级到 GHCR 最新版：`docker compose pull && docker compose up -d`。

> 第三个「镜像」其实是**微信本体**：它**不打进任何镜像**，而是你在面板点「下载并安装」时，由实例容器实时从腾讯官方 CDN 下到自己的卷里（见[部署与运维 · 数据持久化](部署与运维.md#数据持久化)）。

### 3. 从零到能用，整体发生了什么

```
你: docker compose up -d
      └─▶ Docker 读取 docker-compose.yml
            └─▶ 拉起【面板容器 woc-panel】，挂上 ./data-panel 和 docker.sock，暴露 36080 端口

你: 浏览器开 http://NAS:36080 → 登录 → 点「新建微信实例」
      └─▶ 面板通过 docker.sock 指挥 Docker:
            ├─ docker run 一个【微信实例容器 woc-wx-xxx】
            ├─ 给它挂一个新卷 woc-data-xxx（存登录态/消息）
            └─ 接到同一个 docker 网络（面板才能反代到它）

你: 进入该实例 → 点「下载并安装」
      └─▶ 面板 docker exec 进实例容器，触发脚本从腾讯 CDN 下载微信、解压到卷

你: 点「进入电脑版微信」→ 手机扫码
      └─▶ 浏览器 ⇄ 面板(反代+注入鉴权) ⇄ 实例容器的 KasmVNC ⇄ 微信窗口
```

### 4. 常用命令速查

```bash
docker compose up -d            # 启动面板（首次会拉/用镜像）
docker compose down             # 停止并删除面板容器（不动数据卷和微信实例）
docker compose pull             # 把面板/微信镜像更新到 GHCR 最新
docker ps                       # 看正在运行的容器（能看到 woc-panel 和各 woc-wx-*）
docker logs -f woc-panel        # 看面板日志
docker logs -f woc-wx-<id>      # 看某个微信实例日志
docker volume ls | grep woc     # 看所有微信实例的数据卷
```

> ⚠️ 微信实例容器请**始终在面板网页里增删**，不要手动 `docker rm` 它们——否则面板的实例登记和真实容器会对不上。

---

## 架构自动适配

镜像本身多架构（amd64/arm64）；下载微信时容器内**运行时再自动检测 CPU 架构**（`dpkg --print-architecture`）取对应官方包：

| 运行机器 | 架构 | 自动下载 |
|----------|------|----------|
| Intel/AMD NAS、x86 服务器 | amd64 | `WeChatLinux_x86_64.deb` |
| ARM NAS、Apple Silicon Mac | arm64 | `WeChatLinux_arm64.deb` |

到飞牛上（无论 x64 还是 arm）`docker compose up -d` 同一条命令，无需改任何架构相关配置。
