v1.1.0: Alpine 轻量级 Docker 开发环境 + 敏感凭证清理

This commit is contained in:
lxy
2026-07-27 13:59:18 +08:00
parent feb76081a0
commit ccca0fa62b
51 changed files with 6125 additions and 993 deletions
+508 -248
View File
@@ -1,317 +1,577 @@
# WorkPod 技术规格说明书
# WorkPod Alpine 技术规格
> 文档版本:1.0
> 最后更新:2026-03-18
> 项目路径:`E:/workpod`
> 版本:1.1.0 | 更新日期:2026-04-07 | 镜像版本:workpod-alpine:latest (1.1.0)
---
## 1. 概述
## 1. 项目概述
### 1.1 项目定位
WorkPod Alpine 是一个**轻量级 Docker 开发环境容器**,基于 Alpine Linux 3.23 构建,提供 Web 终端(ttyd)和 SSH 双入口,支持多实例部署、开发工具自动检测、tmux 多会话管理。
WorkPod 是一个基于 Docker 的**全栈开发环境容器**,旨在提供统一、可移植、可离线部署的开发环境。
### 核心特性
### 1.2 设计目标
| 目标 | 说明 |
| 特性 | 说明 |
|------|------|
| **环境统一** | 消除"在我机器上能跑"的问题 |
| **离线可用** | 所有依赖包本地化,无需网络 |
| **快速启动** | 一键启动完整开发环境 |
| **可迁移性** | 支持导出/导入到服务器 |
| **数据持久化** | 容器可重建,数据不丢失 |
| **镜像大小** | ~436MB(多阶段构建,Ubuntu 版的 1/6) |
| **基础镜像** | alpine:3.23 (~7MB) |
| **运行时内存** | 80-120MB 基线 + 应用 |
| **启动时间** | ~2.5 秒 |
| **Web 终端** | ttyd + tmux 会话管理 |
| **AI 工具集成** | Claude Code + coding-helper + 智谱 GLM |
### 1.3 适用场景
### 适用场景
- 多工作空间统一开发环境(wk-flux, wk-lab, wk-suke, wk-oth 等
- 新成员快速上手
- 服务器环境部署
- 离线/内网开发环境
- 远程开发环境(浏览器直接访问,无需本地配置
- 团队成员统一开发环境
- 多项目隔离部署(每个项目独立容器实例)
---
## 2. 技术架构
## 2. 架构设计
### 2.1 基础架构
```mermaid
graph TB
subgraph "Docker Host"
DC["docker-compose.yml<br/>基础实例"]
DCF["docker-compose.flux.yml<br/>Flux 项目"]
DCA["docker-compose-alpine.yml<br/>备用/测试"]
end
```
┌─────────────────────────────────────────────────────────┐
│ Docker Desktop │
│ ┌───────────────────────────────────────────────────┐ │
│ │ workpod 容器 (Ubuntu 22.04) │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │Python│ │ Node │ │ Go │ │ Rust │ │MySQL │ │ │
│ │ │ 3.10 │ │ 24.x │ │1.26 │ │1.94 │ │ 8.0 │ │ │
│ │ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │ │
│ │ ┌──────┐ ┌──────┐ ┌──────────────────────────┐ │ │
│ │ │Redis │ │ SSH │ │ Claude Code + OpenClaw │ │ │
│ │ │ 6.0 │ │ 2222 │ │ (AI 编程工具) │ │ │
│ │ └──────┘ └──────┘ └──────────────────────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
│ ↕ 数据卷挂载 (/d/docker-data) │
│ ┌───────────────────────────────────────────────────┐ │
│ │ MySQL │ Redis │ Workspace │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
subgraph "Images"
BASE["workpod-alpine:latest<br/>Alpine 3.23 + Node 24<br/>~436MB"]
FLUX["ws-flux-dev:latest<br/>BASE + JDK17/Maven 挂载"]
end
subgraph "Containers"
W1["workpod-alpine<br/>SSH :2222 / Web :7681<br/>network: workpod-alpine-network"]
W2["ws-flux-dev<br/>SSH :2201 / Web :7701<br/>network: workpod-flux-network"]
end
subgraph "Host Mounts"
WS["E:/wk-flux → /workspace"]
JDK["D:/Java/jdk-musl-17 → /opt/jdk-musl-17 :ro"]
MVN["D:/Java/maven-mvnd → /opt/maven-mvnd :ro"]
end
subgraph "Optional"
AP["auth-proxy.js<br/>认证代理 :8080<br/>Basic Auth + Token"]
NX["nginx (wk.1216.top)<br/>SSL 终止 + 反向代理"]
end
DC -->|"build"| BASE
DCF -->|"build"| FLUX
DCA -->|"image"| W1
BASE --> W1
FLUX --> W2
W2 --> WS
W2 --> JDK
W2 --> MVN
AP -.->|"proxy"| W1
AP -.->|"proxy"| W2
NX -.->|"ssl termination"| AP
```
### 2.2 技术栈明细
### 组件职责
| 组件 | 版本 | 安装方式 | 启动方式 |
|------|------|---------|---------|
| Ubuntu | 22.04 | 基础镜像 | - |
| Python | 3.10 | apt | 常驻 |
| Node.js | 24.14.0 | 离线包 | 常驻 |
| Go | 1.26.1 | 离线包 | 常驻 |
| Rust | 1.94.0 | 离线包 | 常驻 |
| MySQL | 8.0 | apt | 手动 |
| Redis | 6.0 | apt | 手动 |
| Claude Code | 2.1.78 | 离线包 | 按需 |
| OpenClaw | 2026.3.13 | 离线包 | 按需 |
### 2.3 离线包清单
```
packages/
├── node-v24.14.0-linux-x64.tar.xz # Node.js 预编译包
├── go1.26.1.linux-amd64.tar.gz # Go SDK
├── rust-1.94.0-x86_64-unknown-linux-gnu.tar.xz # Rust 工具链
├── claude-code-2.1.78.tgz # Claude Code npm 包
├── openclaw-2026.3.13.tgz # OpenClaw npm 包
└── rustup-init.sh # Rust 安装脚本 (备用)
```
| 组件 | 职责 | 状态 |
|------|------|------|
| `Dockerfile` | 基础镜像构建(Node + Claude Code + coding-helper | 活跃 |
| `Dockerfile.flux` | Flux 项目扩展(基于基础镜像,JDK 外挂) | 活跃 |
| `entrypoint.sh` | 容器入口:信号处理、PATH 检测、服务启停 | 活跃 |
| `ttyd-session.sh` | tmux 会话管理(URL 参数 / 交互菜单) | 活跃 |
| `docker-compose.yml` | 基础实例编排 | 活跃 |
| `docker-compose.flux.yml` | Flux 项目实例编排 | 活跃 |
| `docker-compose-alpine.yml` | 备用编排(多端口 /root 挂载) | 归档备用 |
| `auth-proxy.js` | 认证代理(Basic Auth + Token + WS 代理) | 可选组件 |
| `download-packages.sh` | 离线包下载脚本 | 归档备用 |
| `entrypoint-test.sh` | Test 入口(developer 用户 + 全权限 Claude | 已归档 |
---
## 3. 网络配置
## 3. 镜像构建
### 3.1 端口映射
### 3.1 基础镜像 (Dockerfile)
| 服务 | 宿主机 | 容器 | 协议 | 说明 |
|------|--------|------|------|------|
| SSH | 2222 | 22 | TCP | 远程登录 |
| HTTP | 8080 | 80 | TCP | Web 服务 |
| HTTPS | 8443 | 443 | TCP | 加密 Web 服务 |
| MySQL | 13306 | 3306 | TCP | 数据库 |
| Redis | 16379 | 6379 | TCP | 缓存 |
```dockerfile
# 多阶段构建
FROM alpine:3.23 AS builder # 阶段1: 构建
# → 安装 xz, libstdc++
# → 解压 Node.js v24.14.1 (musl)
# → npm install -g claude-code@latest, coding-helper@latest
# → npm cache clean
### 3.2 连接方式
FROM alpine:3.23 # 阶段2: 运行时
# → apk add: curl git openssh-server bash ttyd tmux libstdc++
# → ssh-keygen + chpasswd + PermitRootLogin yes
# COPY --from=builder /opt/node /usr/local
# → npm config set registry npmmirror.com
# COPY --chmod=755 entrypoint.sh /entrypoint.sh
# COPY --chmod=755 ttyd-session.sh /opt/ttyd-session.sh
```
**构建产物**
| 层 | 内容 | 大小 |
|----|------|------|
| alpine:3.23 | 基础系统 | ~7MB |
| runtime tools | curl/git/ssh/ttyd/tmux/bash | ~80MB |
| /usr/local | Node.js + npm 全局包 | ~200MB |
| scripts | entrypoint + ttyd-session | <10KB |
| **总计** | | **~436MB (压缩后)** |
### 3.2 Flux 扩展镜像 (Dockerfile.flux)
```dockerfile
FROM workpod-alpine:latest
# 无额外 RUN 指令
# JDK 通过 docker-compose volume 从宿主机挂载
# JAVA_HOME 由 environment 设置
EXPOSE 22 7681
ENTRYPOINT ["/entrypoint.sh"]
```
Flux 镜像与基础镜像几乎等大(仅增加 LABEL 元数据),JDK/Maven 不占用镜像空间。
### 3.3 构建命令
```bash
# SSH 连接
ssh root@localhost -p 2222
# 密码:workpod123
# 基础镜像
docker build -t workpod-alpine:latest .
# Docker exec 进入
docker exec -it workpod bash
# 数据库连接
mysql -h 127.0.0.1 -P 13306 -u root
redis-cli -h 127.0.0.1 -p 16379
# Flux 镜像(依赖基础镜像先构建好)
docker build -t ws-flux-dev:latest -f Dockerfile.flux .
```
---
## 4. 存储配置
## 4. 容器编排
### 4.1 数据卷映射
### 4.1 三份 Compose 文件对比
| 宿主机路径 | 容器路径 | 用途 |
|-----------|---------|------|
| `/d/docker-data/mysql` | `/var/lib/mysql` | MySQL 数据 |
| `/d/docker-data/redis` | `/var/lib/redis` | Redis 数据 |
| `/d/docker-data/workspace` | `/workspace` | 工作目录 |
| `./config/supervisor` | `/etc/supervisor/conf.d` | 进程配置 |
| 配置项 | docker-compose.yml (基础) | docker-compose.flux.yml (Flux) | docker-compose-alpine.yml (备用) |
|--------|--------------------------|-------------------------------|--------------------------------|
| **Service 名** | workpod-alpine | ws-flux-dev | workpod-alpine |
| **Container 名** | workpod-alpine | ws-flux-dev | workpod-alpine |
| **SSH 端口** | 2222 → 22 | 2201 → 22 | 2223 → 22 |
| **Web 端口** | 7681 → 7681 | 7701 → 7681 | 7683→7681, 7684→7682 |
| **工作空间挂载** | ./data/workspace → /workspace | E:/wk-flux → /workspace | data/workpod-alpine/workspace → /workspace |
| **JDK 挂载** | 无 | D:/Java/jdk-musl-17:ro → /opt/jdk-musl-17 | 无 |
| **Maven 挂载** | 无 | D:/Java/maven-mvnd:ro → /opt/maven-mvnd | 无 |
| **智谱 GLM env** | 无 | ANTHROPIC_* 5 项传递 | 无 |
| **privileged** | true | false | true |
| **内存限制** | 4G limit / 1G reserve | 4G limit / 1G reserve | 无 |
| **健康检查** | 有 | 有 | 无 |
| **日志轮转** | 10m × 3 | 10m × 3 | 无 |
| **网络** | workpod-alpine-network | workpod-flux-network | workpod-network |
### 4.2 存储要求
### 4.2 启动命令
| 项目 | 最小空间 | 建议空间 |
```bash
# 基础实例
docker compose up -d
# Flux 项目实例
docker compose -f docker-compose.flux.yml up -d
# 备用实例
docker compose -f docker-compose-alpine.yml up -d
```
---
## 5. 运行时
### 5.1 启动流程 (entrypoint.sh)
```
trap SIGTERM/SIGINT/SIGQUIT → cleanup()
┌─ PATH 自动检测 ─────────────────────────┐
│ JAVA_HOME → ${JAVA_HOME}/bin │
│ MAVEN_HOME → ${MAVEN_HOME}/bin │
│ .cargo/bin → Rust (cargo/rustup) │
│ gvm/gos → Go (gvm 版本管理) │
│ .pyenv → Python (pyenv) │
│ go/bin → Go (自定义安装) │
│ .local/bin → 本地工具 │
│ rust-* → Rust 独立安装 │
└──────────────────────────────────────────┘
┌─ 写入 /etc/profile.d/dev-tools.sh ─────┐│ (新 shell 会话也生效)
│ (同样逻辑,确保持久化) │
└──────────────────────────────────────────┘
┌─ 启动服务 ────────────────────────────────┐
│ /usr/sbin/sshd │
│ ttyd -W -c "${TTYD_CREDENTIALS}" \ │
│ -t fontSize=16 \ │
│ -t theme='{"background":"#1a1a2e"}' │
│ /opt/ttyd-session.sh & │
└──────────────────────────────────────────┘
┌─ 健康检查 ────────────────────────────────┐
│ kill -0 $TTYD_PID → ttyd 存活? │
│ pidof sshd → sshd 存活? │
│ 任一失败 → exit 1 │
└──────────────────────────────────────────┘
┌─ 显示环境信息 ──────────────────────────┐
│ Node/npm/Claude/Rust/Go/Python 版本 │
│ 连接方式 (Web URL + SSH 命令) │
└──────────────────────────────────────────┘
exec sleep infinity (PID 1)
```
### 5.2 信号处理
```bash
cleanup() {
kill $TTYD_PID # ttyd 后台进程
kill $SSHD_PID # sshd (注意: 当前 PID 未追踪,实际用 pkill)
wait # 等待子进程退出
exit 0
}
trap cleanup SIGTERM SIGINT SIGQUIT
```
### 5.3 ttyd 会话管理 (ttyd-session.sh)
```
用户访问 http://host:7681
┌─ URL 带 ?session=xxx ? ──────┐
│ 是 → 解析 session 名称 │
│ ↓ │
│ 过滤非法字符 (仅 a-zA-Z0-9_-) │
│ ↓ │
│ tmux attach (存在) 或 new (不存在)│
│ │
│ 否 → 显示交互式菜单 │
│ ┌─────────────────────────┐ │
│ │ [1] session_a │ │
│ │ [2] session_b │ │
│ │ 输入编号或新名称 │ │
│ └─────────────────────────┘ │
│ ↓ │
│ 数字 → 映射到已有 session │
│ 字符串 → 新建 session │
│ ↓ │
│ exec tmux attach/new │
└─────────────────────────────────────┘
```
**安全设计**
- Session 名过滤:`tr -cd 'a-zA-Z0-9_-'` 防止注入
- 共享模式:不带 `-d` 参数,多人可同时查看同一 session
- 默认值:空输入默认为 `default`
---
## 6. 服务端口与连接方式
### 6.1 端口分配表
| 实例 | SSH | Web 终端 (ttyd) | 网络 |
|------|-----|---------------|------|
| **workpod-alpine** (基础) | 2222 | 7681 | workpod-alpine-network |
| **ws-flux-dev** (Flux) | 2201 | 7701 | workpod-flux-network |
| **workpod-test** (旧测试) | 2223 | 7682 | — |
### 6.2 连接速查
```bash
# 基础实例
Web: http://localhost:7681 # 用户 jc / 密码 1234567
SSH: ssh root@localhost -p 2222 # 密码 workpod123 (或 ROOT_PASSWORD)
# Flux 项目实例
Web: http://localhost:7701 # 用户 jc / 密码 1234567
SSH: ssh root@localhost -p 2201 # 密码 workpod123 (或 ROOT_PASSWORD)
# 进入容器 (调试用)
MSYS_NO_PATHCONV=1 docker exec -it workpod-alpine bash
MSYS_NO_PATHCONV=1 docker exec -it ws-flux-dev bash
```
### 6.3 环境变量速查
| 变量 | 默认值 | 用途 |
|------|--------|------|
| `ROOT_PASSWORD` | workpod123 | SSH root 密码 |
| `TTYD_CREDENTIALS` | jc:1234567 | ttyd Web 终端认证 (格式 `用户:密码`) |
| `TZ` | Asia/Shanghai | 时区 |
| `JAVA_HOME` | (无) | JDK 路径 (Flux 实例设置) |
| `MAVEN_HOME` | (无) | Maven 路径 (Flux 实例设置) |
| `ANTHROPIC_AUTH_TOKEN` | (从宿主机继承) | 智谱 API 密钥 |
| `ANTHROPIC_BASE_URL` | https://open.bigmodel.cn/api/anthropic | 智谱 API 地址 |
| `ANTHROPIC_DEFAULT_SONNET_MODEL` | glm-5v-turbo | Sonnet 模型 |
| `ANTHROPIC_DEFAULT_OPUS_MODEL` | glm-5.1 | Opus 模型 |
| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | glm-4.5-air | Haiku 模型 |
---
## 7. 开发工具外挂机制
### 7.1 支持的工具链
entrypoint.sh 启动时自动检测以下路径并加入 PATH:
| 工具 | 检测路径 | 环境变量 |
|------|---------|---------|
| 镜像构建 | 10 GB | 20 GB |
| 容器运行 | 5 GB | 10 GB |
| MySQL 数据 | 1 GB | 按需 |
| 工作空间 | 1 GB | 按需 |
| Java (JDK) | `$JAVA_HOME/bin` | JAVA_HOME |
| Maven | `$MAVEN_HOME/bin` | MAVEN_HOME |
| Rust (rustup) | `/root/.cargo/bin` | RUSTUP_HOME, CARGO_HOME |
| Rust (独立) | `/root/rust-*/bin` | |
| Go (gvm) | `/root/gvm/gos/current/bin` | — |
| Python (pyenv) | `/root/.pyenv/shims`, `.pyenv/bin` | — |
| Go (自定义) | `/root/go/bin` | GOROOT |
| 本地工具 | `/root/.local/bin` | — |
### 7.2 PATH 生效范围
- **当前 entrypoint 进程**:立即 export
- **后续 shell 登录**:通过 `/etc/profile.d/dev-tools.sh` 自动加载
- **docker exec**:需要 `bash -lc 'command'` 或手动 source profile
### 7.3 使用方式
开发者只需将工具安装到对应路径(通过挂载 /root 或在容器内安装),重启或重新登录即可生效。无需修改 Dockerfile 或 entrypoint。
---
## 5. 构建规范
## 8. 多实例部署策略
### 5.1 构建前检查
### 8.1 推荐方案
```bash
# 检查 Docker 状态
docker info
docker ps
# 检查离线包完整性
cd E:/workpod/packages
ls -lh *.tar.* *.tgz
```
项目 A → docker-compose.A.yml (端口 220x / 770x)
项目 B → docker-compose.B.yml (端口 221x / 771x)
通用 → docker-compose.yml (端口 2222 / 7681)
```
### 5.2 构建命令
每个项目一份 compose 文件,基于同一个基础镜像 `workpod-alpine:latest`,通过 Dockerfile 扩展或 volume 挂载添加项目特定依赖。
```bash
# 构建镜像
cd E:/workpod
docker build -t workpod:latest .
### 8.2 扩展新实例步骤
# 验证镜像
docker images workpod
1. 创建 `Dockerfile.xxx`(如需额外包)或直接用基础镜像
2. 创建 `docker-compose.xxx.yml`(配置端口、挂载、环境变量)
3. `docker compose -f docker-compose.xxx.yml up -d`
4. 确认端口不冲突
# 启动容器
docker-compose up -d
### 8.3 网络隔离
# 验证容器
docker ps --filter name=workpod
每个 compose 文件创建独立的 bridge network,容器间默认不可互通。如需互通可在同一 compose 中定义多 service。
---
## 9. 安全模型
### 9.1 当前状态
| 安全项 | 配置 | 风险等级 | 备注 |
|--------|------|---------|------|
| **特权模式** | 基础版 `privileged: true` | **高** | Flux 版已移除 |
| **运行用户** | 全部 root | 中 | 开发环境可接受 |
| **SSH 登录** | PermitRootLogin yes + 密码 | 中 | 建议生产环境禁用 |
| **ttyd 认证** | Basic Auth (jc:1234567) | 低-中 | 可配置强密码 |
| **密码管理** | 环境变量注入 | 低 | 已修复硬编码 |
| **API Key** | docker-compose env 传递 | 低 | 不写入文件系统 |
| **镜像源** | alpine:3.23 + npmmirror | 低 | 第三方信任链 |
| **npm 包** | @latest (不确定版本) | 低 | 用户决策,接受风险 |
### 9.2 已修复的问题
- ~~密码硬编码在源码中~~ → ROOT_PASSWORD / TTYD_CREDENTIALS 环境变量
- ~~API Key 写入 .bashrc~~ → docker-compose environment 直接传递
- ~~healthcheck CMD 数组管道错误~~ → CMD-SHELL + netstat
- ~~entrypoint 外挂 bind mount~~ → COPY --chmod 内置镜像
- ~~构建上下文 ~520MB~~ → .dockerignore 优化到 275 bytes
### 9.3 待改进项
| 优先级 | 改进项 | 建议 |
|--------|--------|------|
| P0 | 移除 privileged: true | 基础版改用具体 capability 或确认是否真需要 |
| P1 | SSH 禁用密码登录 | 改为密钥认证,或限制来源 IP |
| P2 | ttyd 加密传输 | 前置 nginx/caddy 做 HTTPS 终止 |
| P3 | npm 包固定版本 | 将 @latest 改为具体版本号,构建可重现 |
---
## 10. 认证代理 (auth-proxy.js)
> 状态:可选组件,已补充到主目录但未默认启用
### 10.1 架构
```
浏览器 → :8080 auth-proxy.js
├── GET /login → 登录页面 (static/login.html)
├── POST /auth/check → Basic Auth → Token (1h 过期)
├── GET /api/workspaces → 工作空间列表
├── GET/WS /* → Token 验证 → 代理到 ttyd :7681
└── WebSocket upgrade → 双向管道 (终端 I/O)
```
### 5.3 镜像导出/导入
### 10.2 配置
| 配置项 | 值 |
|--------|-----|
| 监听端口 | 8080 |
| 认证方式 | Basic Auth (`wk:1234567`, `admin:admin123`) |
| Token 格式 | `wk_{用户名}_{时间戳}` |
| Token 过期 | 1 小时 (内存存储) |
| 工作区路由 | 默认(/) → :7681, hszd → :7682 |
### 10.3 生产部署
```bash
# 导出(压缩
docker save workpod:latest | gzip > workpod.tar.gz
# 导入
docker load < workpod.tar.gz
# 1. 修改密码(环境变量或配置文件
# 2. 前置 Nginx 反向代理 (wk.1216.conf)
# 3. SSL 证书 (wk.1216.top)
# 4. 启动
node auth-proxy.js
```
---
## 6. 运维规范
## 11. 离线包管理
### 6.1 日常操作
> 状态:归档备用,Dockerfile 直接从 registry 安装
### 11.1 包清单
| 包名 | 版本 | 用途 | 来源 |
|------|------|------|------|
| node-v24.14.1-linux-x64-musl.tar.gz | v24.14.1 | Node.js 运行时 | unofficial-builds.nodejs.org |
| claude-code-*.tgz | @latest | AI 编程助手 | registry.npmmirror.com |
| z_ai-coding-helper-*.tgz | @latest | AI 编程助手 | registry.npmmirror.com |
| openclaw-*.tgz | 2026.3.28 | (未使用) | registry.npmmirror.com |
| go1.26.1.linux-amd64.tar.gz | 1.26.1 | (外挂预留) | Go 官方 |
| rust-1.94.1-x86_64-unknown-linux-musl.tar.xz | 1.94.1 | (外挂预留) | Rust 官方 |
### 11.2 下载脚本
```bash
# 启动容器
docker-compose up -d
./download-packages.sh
# 自动下载到 packages/ 目录
# 支持断点续传(文件存在则跳过)
# 使用国内镜像加速
```
# 停止容器
docker-compose down
---
# 重启容器
docker-compose restart
## 12. 决策记录
以下是在项目演进过程中做出的关键架构决策及其原因:
### DEC-01: Alpine vs Ubuntu 作为基础镜像
- **决策**: 选择 Alpine 3.23
- **原因**: 镜像小 6 倍(436MB vs 2.6GB)、内存基线低 5 倍、启动快 6 倍
- **代价**: musl libc 兼容性需注意(JDK 必须用 musl 版本)
### DEC-02: JDK/Maven 宿主机挂载 vs 镜像内安装
- **决策**: 选择宿主机目录 ro 挂载(`D:/Java/jdk-musl-17`, `D:/Java/maven-mvnd`
- **原因**: 升级 JDK/Maven 无需 rebuild 镜像;本地多项目可共享同一套工具链
- **代价**: 依赖宿主机路径存在;容器不可脱离该主机单独分发
### DEC-03: BellSoft Liberica JDK vs 其他 musl JDK
- **决策**: BellSoft Liberica JDK 17.0.16+12 (musl)
- **原因**: Adoptium "musl" 标签实际仍链接 glibcAlpine openjdk 无法外部挂载;gcompat 缺少符号
- **参考**: 经 ldd 验证解释器为 `/lib/ld-musl-x86_64.so.1`
### DEC-04: npm 包 @latest vs 固定版本
- **决策**: 保持 @latestclaude-code 和 coding-helper
- **原因**: 用户选择每次构建自动获取最新版本,接受不确定性
- **风险**: 构建结果可能不一致;回归问题排查困难
### DEC-05: auto-upgrade 功能废弃
- **决策**: 不实现容器启动时自动检测升级
- **原因**: 维护负担 > 收益;增加启动复杂度和网络依赖;set -e 下失败处理困难
- **替代**: 手动 `docker build` 时自然获取最新
### DEC-06: workpod-alpine 目录合并到 workpod
- **决策**: 删除 `E:/wk-lab/workpod-alpine/`,全部内容归入 `E:/wk-lab/workpod/`
- **原因**: 单一目录管理;避免两份代码漂移;旧版完整归档于 `_archive/`
### DEC-07: entrypoint/ttyd-session 内置镜像 vs bind mount
- **决策**: COPY --chmod=755 内置到镜像
- **原因**: 避免 execvp failedbind mount 源目录删除后容器失效);符合 immutable 镜像最佳实践
- **触发事件**: 2026-04-04 因删除 workpod-alpine 目录导致 workpod 容器 ttyd 子进程全部 crash (exit code 254)
---
## 附录 A: 常用运维命令
```bash
# 构建
docker build -t workpod-alpine:latest .
docker build -t ws-flux-dev:latest -f Dockerfile.flux .
# 启动/停止
docker compose up -d
docker compose down
docker compose -f docker-compose.flux.yml up -d
# 查看日志
docker logs -f workpod
# 查看资源使用
docker stats workpod
docker logs -f workpod-alpine
docker logs --tail 50 ws-flux-dev
# 进入容器
docker exec -it workpod bash
MSYS_NO_PATHCONV=1 docker exec -it workpod-alpine bash
# 验证工具链 (需 login shell)
MSYS_NO_PATHCONV=1 docker exec -it workpod-alpine bash -lc '
echo "Java: $(java -version 2>&1 | head -1)"
echo "Maven: $(mvn -version 2>&1 | head -1)"
echo "Node: $(node -v)"
echo "Claude: $(claude --version)"
'
# 清理
docker system prune -f # 清理悬停资源
docker image prune -f # 清理未使用镜像
```
### 6.2 数据库管理
```bash
# 启动 MySQL
docker exec workpod bash -c "mysqld --user=mysql --datadir=/var/lib/mysql &"
# 启动 Redis
docker exec workpod redis-server --daemonize yes
# 停止 MySQL
docker exec workpod bash -c "mysqladmin -u root shutdown"
# 停止 Redis
docker exec workpod redis-cli shutdown
```
### 6.3 健康检查
```bash
# 检查容器状态
docker inspect workpod --format='{{.State.Health.Status}}'
# 检查 SSH 服务
curl -k https://localhost:2222
# 检查 MySQL
docker exec workpod mysql -e "SELECT VERSION()"
# 检查 Redis
docker exec workpod redis-cli ping
```
---
## 7. 安全规范
### 7.1 访问控制
| 项目 | 当前配置 | 建议 |
|------|---------|------|
| SSH 密码 | workpod123 | 生产环境修改 |
| MySQL root | 无密码 | 生产环境设置密码 |
| Redis | 无密码 | 生产环境设置密码 |
### 7.2 安全加固建议
1. **生产环境**必须修改默认密码
2. 限制端口暴露范围
3. 使用 Docker 网络隔离
4. 定期更新基础镜像
---
## 8. 故障排查
### 8.1 常见问题
| 问题 | 可能原因 | 解决方案 |
|------|---------|---------|
| 容器启动失败 | 端口被占用 | `netstat -ano \| findstr :2222` |
| MySQL 无法启动 | 数据目录权限 | `chown mysql:mysql /var/lib/mysql` |
| SSH 连接失败 | SSH 服务未启动 | `docker exec workpod service ssh start` |
| 构建失败 | 离线包缺失 | 检查 packages/ 目录 |
### 8.2 日志位置
| 日志 | 命令 |
|------|------|
| 容器日志 | `docker logs workpod` |
| SSH 日志 | `docker exec workpod cat /var/log/auth.log` |
| MySQL 日志 | `docker exec workpod cat /var/log/mysql/error.log` |
---
## 9. 版本历史
| 版本 | 日期 | 变更说明 |
|------|------|---------|
| 1.0 | 2026-03-18 | 初始版本 |
---
## 附录 A:快速参考
### A.1 环境信息
## 附录 B: 文件总览
```
基础镜像:ubuntu:22.04
时区:Asia/Shanghai
语言:en_US.UTF-8
工作目录:/workspace
```
### A.2 默认账号
| 服务 | 用户名 | 密码 |
|------|-------|------|
| SSH | root | workpod123 |
| MySQL | root | - |
| Redis | - | - |
### A.3 文件位置
```
E:/workpod/
├── Dockerfile # 镜像构建配置
├── docker-compose.yml # 容器编排配置
├── entrypoint.sh # 启动脚本
├── SPECS.md # 本文档
── README.md # 使用说明
├── packages/ # 离线安装包
└── config/supervisor/ # Supervisor 配置
workpod/
├── Dockerfile # 基础镜像 (多阶段构建)
├── Dockerfile.flux # Flux 扩展镜像
├── entrypoint.sh # 容器入口 (信号/PATH/服务/信息)
├── ttyd-session.sh # tmux 会话管理
├── docker-compose.yml # 基础实例 (:2222/:7681)
├── docker-compose.flux.yml # Flux 实例 (:2201/:7701)
├── docker-compose-alpine.yml # 备用编排
├── auth-proxy.js # 认证代理 (可选)
├── download-packages.sh # 离线包下载 (归档)
├── entrypoint-test.sh # Test 入口 (归档)
├── wk.1216.conf # Nginx 配置
├── nginx-map-patch.sh # Nginx WS 补丁
├── connection_upgrade.map # Nginx map 片段
├── .dockerignore # 构建忽略
├── ISSUES.md # 问题记录
├── SPECS.md # 本文档 ← 你在这里
├── docs/
│ └── 05-问题处理/ # 5 份审核报告
├── config/ # 配置模板
├── static/ # auth-proxy 登录页
├── data/ # 运行时数据
── _archive/ # 历史版本归档
```