Dockerfile
Rama main · réplica de lectura del repositorio original.
# OpenWorkBuddy 服务端镜像
#
# 构建 + 启动,一条命令:bash deploy.sh
# 手动:docker build -t openworkbuddy . && docker compose up -d
#
# ⚠️ 容器里的 agent 能执行 shell、能读写文件。容器本身是一层隔离,但请务必:
# 1. 端口只暴露给反向代理,别 -p 0.0.0.0:3800:3800 直接挂公网
# 2. 前面套 HTTPS(deploy.sh --domain 会自动配好 caddy)
# 3. 起来之后第一件事就是注册管理员账号——第一个注册的就是管理员,
# 空库对外挂着等于谁先访问谁是管理员
FROM node:20-bookworm-slim
# agent 常用的外部程序:python 跑技能脚本、git/curl 取东西、
# fonts-noto-cjk 是为了生成的 Word/PPT 里中文不变方块。
# bubblewrap 是 Linux 上的系统沙箱(src/platform/sandbox.js):多人共用时成员的命令没有它就不跑,这个不能删。
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 python3-pip ca-certificates git curl fonts-noto-cjk bubblewrap \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# 先只拷 package*.json:只要依赖没变,下面这层 npm ci 就走缓存,
# 改一行业务代码重建只要几秒,不用重装几百个包。
COPY package*.json ./
# electron 是桌面壳,服务端用不上,跳过它那个上百 MB 的二进制下载
ENV ELECTRON_SKIP_BINARY_DOWNLOAD=1
# 用 ci 不用 install:install 会按 package.json 的 semver range 重新解析,同一个 commit
# 隔一个月 build 出来的镜像依赖版本就能不一样,线上出问题时「服务器上那个镜像」和本地对不上,
# 排查就没有基准了。ci 严格照 package-lock.json 装,跟 CI 流水线(release.yml 也是 npm ci)一致。
RUN npm ci --omit=dev
# 真正拷代码。哪些不拷见 .dockerignore——config.json、data/、workspace/
# 这些一律挡在外面,镜像层是只读快照,进去了就删不掉了。
COPY . .
# 所有会被写的东西都落在 /data:config.json、账号、会话、成果文件、技能、备份。
# compose 把宿主机的 ./openworkbuddy-data 挂到这儿。
# 这里故意不写 VOLUME:写了的话每次重建容器都会多出一个匿名卷,
# 攒着占磁盘,还容易让人以为数据存在里面(其实挂载点被 compose 覆盖了)。
ENV NODE_ENV=production \
HOST=0.0.0.0 \
PORT=3800 \
OPENWORKBUDDY_HOME=/data
RUN mkdir -p /data
EXPOSE 3800
# 健康检查打的是不需要登录的 /api/auth/state。deploy.sh 靠它判断「真起来了」,
# compose 里的 caddy 也靠它决定什么时候开始转发。
HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=5 \
CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||3800)+'/api/auth/state').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
CMD ["node", "server.js"]