Reactive Resume 6.0.8 Docker Compose 部署指南

Ubuntu 22.04 上用 Docker Compose 从零部署 Reactive Resume v6.0.8(应用 + PostgreSQL 18 官方精简双服务编排),覆盖镜像选型、部署验证、数据持久化、备份升级与排障,命令与回显逐条实测照抄。

Reactive ResumeReactive ResumeDocker简历PostgreSQL2026/10/30

Reactive Resume 6.0.8 Docker Compose 部署指南

目标:在一台 Ubuntu 22.04 服务器上,用 Docker Compose 从零部署 Reactive Resume v6.0.8(官方精简编排:应用 + PostgreSQL 18 双服务),覆盖镜像选型、部署、验证、数据持久化、备份、升级与排障。本文全部命令与回显均在 2026-10-29 于 Ubuntu 22.04 实测环境逐条执行并照抄,演示账号 admin / q1w2e3r4。产品定位与同类对比见《Reactive Resume 介绍与选型指南》,环境变量全量说明见《Reactive Resume 6.0.8 配置参数详解》,REST API 实测见《Reactive Resume 6.0.8 API 使用详解》。

一、环境信息

本文实测环境的关键信息如下,读者在同样规格的服务器上按步骤操作应得到一致结果:

项目值
操作系统Ubuntu 22.04(x86_64)
Docker Engine29.9.2(docker --version 实测)
Docker Composev5.6.1(docker compose version 实测)
应用版本Reactive Resume v6.0.8(发布于 2026-10-29,官方最新稳定版)
数据库PostgreSQL 18(postgres:18 官方镜像)
应用监听容器内 3000 端口,映射到宿主机 8150 端口
PostgreSQL 监听仅编排内网 5432,不向宿主机发布端口
编排目录/opt/reactive-resume/
编排项目名reactive-resume-6.0.8-stack
演示账号admin / q1w2e3r4

先确认本机工具链版本(输出为实测回显,下同):

docker --version
docker compose version
Docker version 29.9.2, build a82e528
Docker Compose version v5.6.1

v6 的官方镜像运行单进程 Node.js 服务:一个进程同时提供 Web 站点、REST API、认证、MCP 服务与上传文件下载,监听 3000 端口,镜像内置健康检查每 30 秒调用一次 GET /api/health。反向代理(若部署)只需转发这一个端口。

二、镜像选型说明

官方镜像发布到两个注册表、tag 完全一致:

注册表镜像路径
Docker Hubamruthpillai/reactive-resume
GitHub Container Registryghcr.io/reactive-resume/reactive-resume

可用 tag 与取舍:

Tag含义适用
v6.0.8精确版本生产推荐,升级完全可控
v6.0 / v6大/中版本浮动想自动获得同版本线内修复
latest最新发布追新,但大版本升级(v6→v7)会自动发生
nightlymain 分支每日构建仅测试,不用于生产

镜像提供 linux/amd64 与 linux/arm64 双架构,x86 服务器与树莓派 4+(64 位系统)均可运行。

💡 技术拓展:容器镜像 tag 不止「精确版本」一种钉法,常见策略对比——

策略做法取舍
精确版本v6.0.8升级显式可控,生产首选
浮动次版本v6.0自动拿补丁,偶发行为变化
浮动大版本v6省心,但需接受同大版本内的一切变更
latestlatest总是最新,升级不可预期
nightlynightly当日主干,随时可能坏

本文采用精确版本 v6.0.8:自托管简历平台数据价值高,升级节奏应由运维者显式决定,而不是被 docker compose pull 隐式推动。

数据库镜像选 postgres:18——与官方自托管文档完全一致;v6 应用启动时自动执行数据库迁移(Drizzle ORM 管理),无需手工建表。实测两个镜像的体积(docker images 回显,DISK USAGE 列):

amruthpillai/reactive-resume   v6.0.8   1.85GB
postgres                       18       650MB

拉取命令:

docker pull amruthpillai/reactive-resume:v6.0.8
docker pull postgres:18
v6.0.8: Pulling from amruthpillai/reactive-resume
...
Status: Downloaded newer image for amruthpillai/reactive-resume:v6.0.8
docker.io/amruthpillai/reactive-resume:v6.0.8

⚠️ 网络说明:本次实测从 Docker Hub 直连拉取应用镜像时曾在解压阶段出现 read: connection reset by peer 中断,重新执行 docker pull 断点续传后完成。若拉取反复失败,可改用 GitHub Container Registry(docker pull ghcr.io/reactive-resume/reactive-resume:v6.0.8,tag 与 Docker Hub 一致)或为本机 Docker 配置镜像加速/代理后重试。实测当日可用的渠道为 Docker Hub 直连重试 + 代理兜底。

三、前置条件

  1. 硬件:应用本体 1 vCPU + 1 GB 内存起步,与 PostgreSQL 同机部署建议 2 GB;磁盘 10 GB 起步(含图片上传空间)。
  2. 软件:Docker Engine 与 Docker Compose 插件已安装(见第一章版本核验);openssl 命令可用(用于生成密钥,Ubuntu 22.04 默认自带)。
  3. 端口:宿主机 8150 端口空闲。验证方法与实测回显:
ss -ltn | grep 8150 || echo "8150 端口空闲"
8150 端口空闲
  1. 无需安装 Chromium:v4 时代需要外挂浏览器渲染 PDF,v6 改用内置 Forme PDF 引擎在应用进程内直接渲染,官方文档明确「PDFs are rendered by the app itself, so there is no printer service to configure」。
  2. 无需手工初始化数据库:应用容器每次启动自动执行迁移(多实例并发启动时以数据库咨询锁协调,只有一个实例执行)。

四、部署步骤

本节从空目录开始,三份文件(.env、compose.yml)加一条启动命令完成部署。所有文件放在 /opt/reactive-resume/。

4.1 创建目录与 .env 配置

mkdir -p /opt/reactive-resume && cd /opt/reactive-resume

先生成两个 64 位十六进制密钥(会话签名密钥与个人密钥加密盐,生产环境必须各自独立生成):

openssl rand -hex 32
openssl rand -hex 32
0e267e3527f632dcbc4220a6c30ab02a44b6c4311cc28589c2a6298db1b57a6f
677df7be6cc66b50ea27265d90fde2be068143c0042946a059d4aafd495239c6

⚠️ 上面两行是本文实测实例的真实输出,仅作示例展示。你的实例必须用自己执行 openssl rand -hex 32 的结果替换,且 AUTH_SECRET 与 ENCRYPTION_SECRET 不要相同:AUTH_SECRET 变更会使全体用户会话失效、两步验证不可用;ENCRYPTION_SECRET 变更使用户保存的个人 AI/网络访问密钥不可读。服务器在生产模式下会拒绝启动仍在使用 .env.example 示例值的 AUTH_SECRET 或 ENCRYPTION_SECRET(官方安全设计)。

写入 .env(本文件全部值为实测实例所用):

cat > /opt/reactive-resume/.env <<'EOF'
APP_URL=http://<服务器IP或域名>:8150
POSTGRES_PASSWORD=q1w2e3r4
DATABASE_URL=postgresql://postgres:q1w2e3r4@postgres:5432/postgres
AUTH_SECRET=0e267e3527f632dcbc4220a6c30ab02a44b6c4311cc28589c2a6298db1b57a6f
ENCRYPTION_SECRET=677df7be6cc66b50ea27265d90fde2be068143c0042946a059d4aafd495239c6
EOF

关键项说明:

变量本例取值说明
APP_URLhttp://<服务器IP或域名>:8150必须与浏览器地址栏完全一致(含协议与端口)。它决定登录回跳地址、OAuth 回调、邮件链接与公开简历链接;不一致会导致登录后回跳错位、会话 Cookie 不生效。<服务器IP或域名> 按你的实际访问地址填写,如 http://192.168.1.10:8150
POSTGRES_PASSWORDq1w2e3r4PostgreSQL 密码,与 DATABASE_URL 中的密码保持一致
DATABASE_URLpostgresql://postgres:q1w2e3r4@postgres:5432/postgres连接串中主机名 postgres 是 compose.yml 里的数据库服务名,容器内网解析;不要写 localhost(那指向应用容器自身)
AUTH_SECRET(64 位 hex)会话签名密钥,生产环境至少 32 字符,生命周期内保持不变
ENCRYPTION_SECRET(64 位 hex)个人密钥加密盐,至少 32 字符;不启用用户自带 AI 密钥功能时暂不生效,但建议部署时一并设置以免日后变更

4.2 编写 compose.yml

cat > /opt/reactive-resume/compose.yml <<'EOF'
name: reactive-resume-6.0.8-stack

services:
  postgres:
    image: postgres:18
    container_name: reactive-resume-6.0.8-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: postgres
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: q1w2e3r4
    networks:
      - app_network
    volumes:
      - postgres_data:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"]
      interval: 10s
      timeout: 5s
      retries: 10

  reactive-resume:
    image: amruthpillai/reactive-resume:v6.0.8
    container_name: reactive-resume-6.0.8-server
    restart: unless-stopped
    networks:
      - app_network
    ports:
      - "8150:3000"
    env_file: .env
    volumes:
      - reactive_resume_data:/app/data
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  postgres_data:
  reactive_resume_data:

networks:
  app_network:
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.74.0/24
EOF

逐项说明:

配置项作用
name: reactive-resume-6.0.8-stackCompose 项目名。必须显式指定:多套编排共存于一台宿主机时,docker compose down 只会操作本项目名的资源,避免同名项目互删
container_name固定容器名,便于 docker logs/docker exec 直接引用
restart: unless-stopped开机自启、异常退出自动拉起;人工 docker stop 后不自动重启
healthcheck(postgres)pg_isready 每 10 秒探测数据库就绪,最多重试 10 次
depends_on: service_healthy应用容器等数据库健康后再启动,避免迁移在数据库未就绪时执行失败
ports: "8150:3000"宿主机 8150 → 容器 3000
env_file: .env将环境变量注入应用容器
reactive_resume_data:/app/data上传文件持久化卷(头像、附件等)
postgres_data:/var/lib/postgresql数据库数据持久化卷(PostgreSQL 18 的数据根目录)
networks 显式网段固定 10.89.74.0/24 网段,避免 Docker 随机分配与其他 compose 项目网段冲突;若该网段已被占用,换一个空闲 /24 即可

4.3 启动并等待健康

cd /opt/reactive-resume
docker compose up -d --wait --wait-timeout 240

实测回显(--wait 会阻塞直到两个服务都通过健康检查):

[+] Running 5/5
 ✔ Network reactive-resume-608-stack_app_network      Created
 ✔ Volume "reactive-resume-608-stack_postgres_data"   Created
 ✔ Volume "reactive-resume-608-stack_reactive_resume_data"  Created
 ✔ Container reactive-resume-6.0.8-postgres  Healthy
 ✔ Container reactive-resume-6.0.8-server    Healthy

4.4 验证部署

三步验证:服务状态、启动日志、健康端点。

docker compose -f /opt/reactive-resume/compose.yml ps
NAME                             IMAGE                                 COMMAND                  SERVICE           CREATED         STATUS                   PORTS
reactive-resume-6.0.8-postgres   postgres:18                           "docker-entrypoint.s…"   postgres          9 minutes ago   Up 9 minutes (healthy)   5432/tcp
reactive-resume-6.0.8-server     amruthpillai/reactive-resume:v6.0.8   "docker-entrypoint.s…"   reactive-resume   9 minutes ago   Up 9 minutes (healthy)   0.0.0.0:8150->3000/tcp, [::]:8150->3000/tcp

应用首启日志(实测,迁移与应用启动过程):

docker logs reactive-resume-6.0.8-server 2>&1 | head -4
Running database migrations...
Database migrations completed
Validating local storage path: /app/data
🚀 Up and running on http://localhost:3000

健康端点返回 200 与各依赖状态(curl 实测):

curl -s http://localhost:8150/api/health
{"service":"reactive-resume","version":"6.0.8","revision":"84b19140c7a6f80e1da0381a09f5597b56815d3f","status":"healthy","timestamp":"2026-10-29T14:09:01.939Z","uptime":"10.09s","database":{"status":"healthy","latencyMs":0},"storage":{"type":"local","status":"healthy","message":"Local filesystem storage is accessible and has read/write permission.","latencyMs":0}}

字段含义:status: healthy 且 database、storage 均为 healthy 即部署成功;若配置了 Redis 还会多出 redis 字段;任一依赖异常时整体返回 503,对应项显示 unhealthy。

4.5 创建账号

浏览器打开 APP_URL(本例 http://<服务器IP>:8150),点 Sign up 注册第一个账号:用户名 admin、邮箱任意、密码 q1w2e3r4(演示环境约定值)。注册后立即处于登录态。

未配置 SMTP 时验证邮件不会真正发出,而是写入应用日志(实测回显):

docker logs reactive-resume-6.0.8-server 2>&1 | grep "Verify your email"
SMTP not configured; skipping email send. { to: 'admin@example.com', subject: 'Verify your email' }

邮件内容只写日志、验证链接不真正投递——自托管单人使用可无视邮件验证直接使用全部功能。第一个账号建好后,若要禁止他人注册,在 .env 追加 FLAG_DISABLE_SIGNUPS=true 后 docker compose up -d 重建生效。

五、数据持久化说明

数据落在两个命名卷里,卷名自动带上项目名前缀(reactive-resume-6.0.8-stack 中的点被规范化,实测前缀为 reactive-resume-608-stack):

docker volume ls | grep reactive-resume
local     reactive-resume-608-stack_postgres_data
local     reactive-resume-608-stack_reactive_resume_data
卷容器内挂载点内容
reactive-resume-608-stack_postgres_data/var/lib/postgresql全部业务数据:账号、简历、求职信、申请看板、AI 会话等
reactive-resume-608-stack_reactive_resume_data/app/data上传文件:头像、简历照片、申请附件、助手附件

两个要点:

  1. 应用以 node 用户(UID 1000)运行。若改用 bind mount(宿主目录直挂 /app/data),目录属主必须可被 UID 1000 写入,否则启动时自检 Local storage path is not writable 直接退出;命名卷由 Docker 自动处理属主,无需关心。
  2. 重建容器不丢数据,down -v 会丢。docker compose down 默认保留卷,down -v 连卷一起删除——生产环境严禁对带卷编排执行 -v,除非确认已有备份。

六、环境变量表

.env 中与应用相关的变量分两类:必填(缺一不可启动)与可选(按需追加)。本部署实际用到的前 5 项,可选行为按需启用:

变量必填默认作用
APP_URL是—对外访问地址,必须与浏览器地址栏完全一致
DATABASE_URL是—PostgreSQL 连接串,主机名用服务名 postgres
AUTH_SECRET是—会话签名密钥,≥32 字符,生命周期内不变
POSTGRES_PASSWORD是—数据库密码(供 postgres 服务初始化,需与 DATABASE_URL 一致)
ENCRYPTION_SECRET建议未设置个人 AI/网络访问密钥的加密盐,≥32 字符且与 AUTH_SECRET 不同
STORAGE_BACKEND否自动(本形态为 local)上传存储后端:local/s3/blob/r2
LOCAL_STORAGE_PATH否/app/data本地存储目录,绝对路径
REDIS_URL否未设置可选 Redis;单机不配也能完整运行
FLAG_DISABLE_SIGNUPS否false设 true 关闭注册入口
SMTP_HOST/SMTP_PORT/SMTP_USER/SMTP_PASS/SMTP_FROM否未设置四项 SMTP_HOST/SMTP_USER/SMTP_PASS/SMTP_FROM 全配齐才发真实邮件
STRICT_SCHEMA_CHECK否false启动时校验数据库 schema,不匹配则拒绝启动
FLAG_DISABLE_API_RATE_LIMIT否false关闭 API 与认证限流(仅测试环境使用)

以上为部署常用子集;服务器可读的全量变量(双域名、字体镜像、AI 供应商、特性开关、Vercel 部署别名等)逐条释义见《Reactive Resume 6.0.8 配置参数详解》。

七、配置参数说明

对第四章 compose.yml 中容易踩坑的三处再展开:

  1. --wait 与健康检查是部署验证的一部分。docker compose up -d --wait 会等 postgres 的 pg_isready 通过、应用内置健康检查(调 /api/health)通过才返回 0;任一服务起不来会以非零码退出并打印失败服务,比「起来再看日志」更适合写进自动化脚本。
  2. depends_on 只保证顺序,不保证可用。condition: service_healthy 让应用容器等数据库健康检查通过才创建,这是本编排能在空库上一次启动成功的关键;去掉该条件时应用可能抢跑,迁移失败退出(容器 Restarting 循环),等待 restart: unless-stopped 拉起重试直到数据库就绪。
  3. APP_URL 与端口映射必须自洽。本例把 3000 映射到 8150,则 APP_URL 必须写成 http://<主机>:8150;若前端再挂反向代理提供 HTTPS 域名,则 APP_URL 应改为 https://resume.example.com 并重启应用,否则登录回跳与公开页链接仍指向旧地址。

八、配置文件挂载

部署产生的三份东西与挂载关系:

文件/目录位置挂载方式
compose.yml/opt/reactive-resume/compose.yml不挂载,是编排定义本身
.env/opt/reactive-resume/.env经 env_file 注入应用容器环境变量,不落盘到容器内
数据卷Docker 管理的命名卷postgres_data→/var/lib/postgresql、reactive_resume_data→/app/data

改 .env 后必须重建容器才生效(环境变量在容器创建时注入):

cd /opt/reactive-resume && docker compose up -d

Compose 检测到环境变化会只重建应用容器,数据库卷不受影响。

九、等价 docker run

不用 Compose 时,以下三条命令与上述编排完全等价(先建网络,再先后启动数据库与应用):

docker network create --driver bridge --subnet 10.89.74.0/24 reactive-resume-6.0.8-net
docker run -d \
  --name reactive-resume-6.0.8-postgres \
  --network reactive-resume-6.0.8-net \
  --restart unless-stopped \
  -e POSTGRES_DB=postgres \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=q1w2e3r4 \
  -v reactive-resume-608-stack_postgres_data:/var/lib/postgresql \
  --health-cmd "pg_isready -U postgres -d postgres" \
  --health-interval 10s \
  --health-timeout 5s \
  --health-retries 10 \
  postgres:18
docker run -d \
  --name reactive-resume-6.0.8-server \
  --network reactive-resume-6.0.8-net \
  --restart unless-stopped \
  -p 8150:3000 \
  --env-file /opt/reactive-resume/.env \
  -v reactive-resume-608-stack_reactive_resume_data:/app/data \
  amruthpillai/reactive-resume:v6.0.8

说明:--env-file 直接引用同一份 .env;docker run 没有 depends_on,需等数据库 healthy 后再执行第三条(docker ps 看 STATUS 出现 (healthy))。日常运维仍建议用 Compose,升级与重建更可控。

十、常用运维命令

以下命令均在 /opt/reactive-resume/ 目录内执行。

状态与日志:

docker compose ps                      # 两服务应显示 (healthy)
docker compose logs --tail=50 reactive-resume    # 应用最近 50 行日志
docker compose logs -f postgres        # 跟踪数据库日志

重启与停止:

docker compose restart reactive-resume   # 只重启应用
docker compose stop                      # 停止(保留容器与卷)
docker compose down                      # 删除容器与网络,保留卷
docker compose down -v                   # ⚠️ 连卷一起删,等于清空全部数据,先备份

版本升级(官方流程,先备份再升级):

docker compose pull reactive-resume      # 拉取新版本镜像
docker compose up -d reactive-resume     # 只重建应用容器
docker compose logs -f reactive-resume   # 观察新版本迁移与启动日志

应用启动时自动执行新版本的数据库迁移,PostgreSQL 容器保持运行不受影响。compose.yml 中的镜像 tag 改为目标版本(如 v6.0.9)后再执行上述命令;大版本升级(如未来 v6→v7)前先读官方迁移说明。

数据库备份与恢复(实测):

docker exec reactive-resume-6.0.8-postgres pg_dump -U postgres -d postgres --format=custom > /opt/reactive-resume/rr-backup.dump
ls -la /opt/reactive-resume/rr-backup.dump
-rw-r--r-- 1 root root 151127 Oct 29 22:18 /opt/reactive-resume/rr-backup.dump

验证备份可读(实测回显):

docker exec -i reactive-resume-6.0.8-postgres pg_restore --list < /opt/reactive-resume/rr-backup.dump | head -7
;
; Archive created at 2026-10-29 14:18:07 UTC
;     dbname: postgres
;     TOC Entries: 311
;     Compression: gzip
;     Dump Version: 1.16-0
;     Format: CUSTOM

恢复到空库(灾难重建时使用):

docker exec -i reactive-resume-6.0.8-postgres pg_restore -U postgres -d postgres --clean --if-exists < /opt/reactive-resume/rr-backup.dump

上传文件备份:直接打包数据卷内容(本地存储形态下备份即拷贝 /app/data):

docker run --rm -v reactive-resume-608-stack_reactive_resume_data:/data -v /opt/reactive-resume:/backup alpine tar czf /backup/rr-uploads.tar.gz -C /data .

⚠️ 备份要同时覆盖数据库与上传文件两处,并保留一份 .env 副本:没有原 AUTH_SECRET,恢复出的实例会让所有会话失效、两步验证不可用;没有原 ENCRYPTION_SECRET,用户保存的个人 AI 密钥不可读。

十一、常见问题(FAQ)

Q1:docker compose up 时应用容器反复重启,日志报 Database migrations failed 或 ECONNREFUSED? DATABASE_URL 错误或数据库不可达。逐项核对:主机名必须是服务名 postgres(不是 localhost);密码与 POSTGRES_PASSWORD 一致;密码含特殊字符时要在连接串里做 URL 编码。实测在本编排中应用由 depends_on: service_healthy 保护,正常配置下不会出现抢跑。

Q2:/api/health 返回 503? 看响应 JSON 里哪个依赖是 unhealthy:database 异常查数据库连接与状态;storage 异常查 /app/data 挂载可写性(UID 1000)或 S3 配置;redis 异常查 REDIS_URL。修复对应依赖后健康检查在 30 秒内自动恢复。实测正常实例返回 database/storage 双 healthy(见 4.4 节回显)。

Q3:登录后跳回登录页,或登录后页面功能异常? APP_URL 与浏览器实际访问地址不一致(协议、域名、端口任一不符都会导致会话 Cookie 不生效)。把 .env 的 APP_URL 改成与地址栏完全一致的值后 docker compose up -d 重建。

Q4:拉取镜像时出现 failed to copy: ... connection reset by peer? 网络中断导致层下载失败,重新执行 docker pull 断点续传即可(本次实测即靠重试完成)。反复失败时改用 GHCR 路径或配置代理/镜像加速(见第二章 ⚠️ 网络说明)。

Q5:升级后上传的头像、附件消失了? /app/data 没有挂持久卷,历史数据留在旧容器里随重建丢失。按第四章编排补上 reactive_resume_data:/app/data 卷;此前未落卷的旧文件无法找回,重建后重新上传。

Q6:想在生产收口注册入口? 第一个账号创建完成后,在 .env 追加 FLAG_DISABLE_SIGNUPS=true 并 docker compose up -d。已注册账号不受影响,新访客无法注册(邮箱、社交登录、来宾模式三条路全关)。

十二、参考链接