ChiefOnboarding v2.5.0 Docker Compose 部署指南

Docker Compose 从零部署 ChiefOnboarding v2.5.0:PostgreSQL 依赖链、首次启动自动迁移与初始化向导、首启必踩坑、Nginx 反代 HTTPS、升级备份与故障排查,全流程实测。

ChiefOnboardingChiefOnboardingDocker ComposePostgreSQL2026/10/30

ChiefOnboarding v2.5.0 Docker Compose 部署指南

目标:在一台 Linux 服务器上,用 Docker Compose 从零把 ChiefOnboarding v2.5.0 部署到可用状态,覆盖 PostgreSQL 依赖链、首次启动的自动迁移、组织初始化向导、反向代理与 HTTPS、升级与备份。全部命令与回显均来自 2026-10-30 在 Ubuntu 22.04 实机(Docker 28.x)上的部署实测。组件定位与选型背景先读 《ChiefOnboarding 介绍与选型指南》;环境变量逐项说明见 《ChiefOnboarding v2.5.0 配置参数详解》;API 调用见 《ChiefOnboarding v2.5.0 API 使用详解》。

一、部署形态与前置准备

1.1 版本与拓扑

项实测值(2026-10-30)
应用版本v2.5.0(官方镜像 chiefonboarding/chiefonboarding:latest)
镜像基座python:3.13 + supervisor 托管 gunicorn 与 django-q2 进程
数据库PostgreSQL(唯一受支持数据库,本篇用 postgres:17-alpine)
应用内端口8000(gunicorn 监听)
部署形态单机双服务:web + db

官方镜像把 Web 应用与 django-q2 任务进程打包在同一镜像内、由 supervisord 同时拉起,因此 Compose 拓扑只需两个服务;不需要额外的 Redis/RabbitMQ(任务队列用 PostgreSQL 数据库表,见 《ChiefOnboarding 介绍与选型指南》 2.2 节)。

1.2 服务器要求

  • 1 核 2GB 起步(实测 2GB 内存余量充足,Python 应用 + PostgreSQL 合计常驻 < 800MB);
  • 已安装 Docker 与 Docker Compose v2 插件(docker compose version 可用);
  • 若数据库需要独立规划高可用,可将 db 服务替换为外部 PostgreSQL 地址,数据库底座建设参考 《PostgreSQL 18.6 Docker Compose 部署指南》。

1.3 准备部署目录

mkdir -p /opt/chiefonboarding && cd /opt/chiefonboarding

本篇所有文件均落在该目录下执行。

二、编写 docker-compose.yml

2.1 官方最小样例

官方文档(docs.chiefonboarding.com 的 Deploy with Docker 页)给出的最小可用编排为「web + db」两个服务,db 用 expose 只在内网暴露 5432,web 通过 ports 对外发布:

services:
  db:
    image: postgres:latest
    restart: always
    expose:
      - "5432"
    volumes:
      - pgdata:/var/lib/postgresql/data/
    environment:
      - POSTGRES_DB=chiefonboarding
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres

  web:
    image: chiefonboarding/chiefonboarding:latest
    restart: always
    expose:
      - "8000"
    environment:
      - SECRET_KEY=somethingsupersecret
      - DATABASE_URL=postgres://postgres:postgres@db:5432/chiefonboarding
      - ALLOWED_HOSTS=test.chiefonboarding.com
    depends_on:
      - db

volumes:
  pgdata:

2.2 生产化改造后的完整编排(本篇实测采用)

在官方样例基础上做五点改造:镜像版本固定(postgres:latest 收敛为 postgres:17-alpine)、发布端口到宿主机、显式网络与子网、补齐 HTTP 直访所需变量(HTTP_INSECURE)、开启 API(后续篇章要用)。写入 docker-compose.yml:

name: chiefonboarding-v2.5.0-stack

services:
  db:
    image: postgres:17-alpine
    restart: always
    expose:
      - "5432"
    volumes:
      - pgdata:/var/lib/postgresql/data/
    environment:
      - POSTGRES_DB=chiefonboarding
      - POSTGRES_USER=chief
      - POSTGRES_PASSWORD=q1w2e3r4
    networks:
      - global

  web:
    image: chiefonboarding/chiefonboarding:latest
    restart: always
    ports:
      - "8131:8000"
    environment:
      - SECRET_KEY=chiefonboarding-demo-secret-2026
      - DATABASE_URL=postgres://chief:q1w2e3r4@db:5432/chiefonboarding
      - ALLOWED_HOSTS=192.168.1.200,localhost
      - BASE_URL=http://192.168.1.200:8131
      - HTTP_INSECURE=True
      - API_ACCESS=True
    depends_on:
      - db
    networks:
      - global

volumes:
  pgdata:

networks:
  global:
    name: chiefonboarding-v2.5.0-net
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.60.0/24

逐项解说:

配置说明
SECRET_KEYDjango 加密签名密钥,生产必须换成长随机串(openssl rand -hex 32),泄露等于会话可伪造
DATABASE_URL标准连接串格式 postgres://用户:密码@主机:5432/库名;主机名填服务名 db,Compose 内置 DNS 解析
ALLOWED_HOSTSDjango 请求 Host 白名单,逗号分隔;填访问时浏览器地址栏里的主机名/IP,缺了直接 400
BASE_URL系统对外完整地址,邮件里的激活链接用它拼接;与 ALLOWED_HOSTS 保持同源
HTTP_INSECURE=True走 HTTP 直访必须加;否则应用强制 Secure Cookie,HTTP 下登录后会话不生效(见第四章踩坑 2)
API_ACCESS=True默认关闭;开启后才有 REST API 与 Token 表(API 篇的前提)
ports 8131:8000宿主 8131 → 应用 8000,按需修改;被占用时报 bind: address already in use(见第四章踩坑 1)

每个环境变量的完整行为(含默认值与源码逻辑)见 《ChiefOnboarding v2.5.0 配置参数详解》。

2.3 PostgreSQL 依赖链说明

ChiefOnboarding 是 Django + psycopg 技术栈,数据库为硬依赖:不提供 SQLite/MySQL 方言,应用启动第一步就是连库执行迁移。因此 Compose 里的 depends_on: - db 只保证「启动顺序」,不保证「数据库就绪」——PostgreSQL 初始化完成前 web 连库会报 connection refused 并自动重启,直到数据库可接受连接为止(官方未配置 healthcheck,靠 restart 兜底)。若把数据库换成外部实例,把 DATABASE_URL 的主机部分改为可达地址、删除 db 服务即可。

三、首次启动与组织初始化

3.1 启动并观察自动迁移

docker compose up -d

首次启动时,应用入口 supervisord 会先执行全量数据库迁移、再拉起 gunicorn,日志里能看到几十条 Applying ... OK:

web-1  |  Applying users.0030_alter_user_timezone... OK
web-1  |  Applying users.0033_alter_user_timezone... OK
web-1  |  Applying users.0043_integrationuser_updating... OK
web-1  | [2026-10-30 01:53:48 +0000] [47] [INFO] Starting gunicorn 26.2.0
web-1  | [2026-10-30 01:53:48 +0000] [47] [INFO] Listening at: http://0.0.0.0:8000 (47)
web-1  | [2026-10-30 01:53:48 +0000] [48] [INFO] Booting worker with pid: 48

⚠️ 首启耗时约 1 分钟(迁移 40+ 张表)。期间端口已映射但 HTTP 未就绪,curl 会返回连接失败——看到日志出现 Booting worker 才算就绪,不要在迁移完成前判定部署失败。

3.2 健康检查

应用内置 /health 端点(官方明确它忽略 ALLOWED_HOSTS,任何来源都可探活):

$ curl -w '\nHTTP %{http_code}\n' http://192.168.1.200:8131/health
ok
HTTP 200

把它配到负载均衡或监控探针即可。

3.3 组织初始化向导

首次访问首页会 302 跳到初始化向导:

$ curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\n' http://192.168.1.200:8131/
302 -> http://192.168.1.200:8131/setup/

浏览器打开 http://<服务器IP>:8131,向导表单共 8 个字段:组织名称(name)、时区(timezone)、语言(language)、管理员姓/名、管理员邮箱(即登录账号,登录方式为邮箱 + 密码)、密码两遍。实测填入:

字段实测值
Organization nameQuzuo Demo
TimezoneAsia/Shanghai
LanguageEnglish(界面无中文,内容可自写中文)
Emailadmin@example.com
Password见下方密码策略坑

提交成功后 302 跳转登录页 /accounts/login/,用刚才的邮箱密码即可进入管理仪表盘(落在 /#/admin/people/ 新员工列表页)。

3.4 演示数据

初始化完成后系统自带一套演示数据(官方原文:"There will be some demo data in there already, feel free to delete everything"):实测内含 1 名演示新员工(id=3,John Doe)、若干序列与模板。正式启用前在管理界面逐个删除即可,不影响后续功能。

四、首次启动必踩坑清单(实测)

以下 4 个坑全部在本次部署中实际踩到,逐个给出现象与解法:

坑 1:宿主端口冲突,web 服务停在 Created 不启动

现象:docker compose up -d 后 web 状态为 Created 而非 Up,日志无报错。原因:ports 指定的宿主端口被其他进程/部署占用,启动时 bind: address already in use。实测本机 8131 已被其他应用占用,改为空闲端口后正常:

$ docker ps -a --format '{{.Names}}\t{{.Status}}' | grep chief
chiefonboarding-v2.5.0-stack-web-1   Created          # 卡住
# 修改 docker-compose.yml 端口为 8132 后
$ docker compose up -d
web-1 Recreated ... Started
chiefonboarding-v2.5.0-stack-web-1   Up

排查命令:ss -tlnp | grep <端口>,或直接 docker compose up(前台)看完整报错。

坑 2:HTTP 直访必须显式 HTTP_INSECURE=True,否则登录不生效

应用在「非 DEBUG 且未声明 HTTP_INSECURE」时强制 SESSION_COOKIE_SECURE=True:会话 Cookie 只允许 HTTPS 传输。此时用 HTTP 访问,登录请求返回 302 成功,但 Cookie 被浏览器丢弃,刷新即被踢回登录页。两种解法:HTTP 内网试跑加 HTTP_INSECURE=True;生产走 HTTPS(第五章)则不要加。

坑 3:初始化向导拒绝弱密码(This password is too common.)

Django 内置密码校验器(长度 ≥8、防常见密码、防纯数字)在初始化向导同样生效。实测密码 q1w2e3r4 被拒:

This password is too common.

换带大小写与符号的 Q1w2E3r4! 通过。管理员密码需强度足够,这不是 bug 而是安全设计;创建后续员工时不受此校验(员工密码由激活链接自设)。

坑 4:ALLOWED_HOSTS 缺主机名返回 400 DisallowedHost

Django 对 Host 头强校验。浏览器访问 http://192.168.1.200:8131,则 ALLOWED_HOSTS 必须包含 192.168.1.200;用 localhost 访问就要含 localhost。建议内网 IP 与 localhost 都配上(逗号分隔)。配置错误的完整表现:任何页面返回 400,日志刷 Invalid HTTP_HOST header。

补充:进入已部署应用的容器执行管理命令时,直接 python manage.py 会报 ModuleNotFoundError: No module named 'django'——镜像用 uv 管理依赖,解释器在 /app/.venv/bin/python,需用 docker compose exec web /app/.venv/bin/python manage.py <命令> 的形式(API 篇生成 Token 时会再次遇到)。

五、反向代理与 HTTPS

生产环境不建议直接暴露 8000/映射端口,用 Nginx 反向代理并上 HTTPS。假设域名为 hr.example.com,在已有 Nginx 上加一个 server 块:

server {
    listen 443 ssl http2;
    server_name hr.example.com;

    ssl_certificate     /etc/letsencrypt/live/hr.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hr.example.com/privkey.pem;

    client_max_body_size 64m;   # 员工上传文件(头像/硬件图片等)

    location / {
        proxy_pass http://127.0.0.1:8131;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen 80;
    server_name hr.example.com;
    return 301 https://$host$request_uri;
}

配套要点:

  1. Compose 侧改回安全形态:删除 HTTP_INSECURE,ALLOWED_HOSTS=hr.example.com,BASE_URL=https://hr.example.com;
  2. 前置证书由 certbot 申请,Nginx 安装与证书配置独立成篇,参考 《Ubuntu 22.04 安装 Nginx 指南(apt/官方源/编译多方案)》 与 《Nginx HTTPS 与证书配置方案(certbot/自签名)》;
  3. 若需要强制 HTTP→HTTPS 跳转在应用层完成(如 Heroku 类平台无法改反代),可加 SSL_REDIRECT=True 让 Django 自己做 301。

六、核心链路验证(实测记录)

部署完成后按以下顺序走一遍核心链路,全部通过即认为部署合格。

① 管理员登录:登录页提交后 302 到 /redirect/,最终落在 /admin/people/(New hires 列表):

login: 302 -> http://192.168.1.200:8131/redirect/
follow: 200 -> http://192.168.1.200:8131/admin/people/

② 创建序列与待办模板:管理界面 Sequences 菜单创建入职序列,Templates → To do 添加待办模板并拖入序列时间线(块类型与触发规则见 《ChiefOnboarding 介绍与选型指南》 3.2 节)。

③ 创建新员工并指派序列:New hires → Add new hire 填姓名/邮箱/入职日/时区/语言,勾选序列。实测 POST 后 302 回列表页,新员工(James Weller,id=4)出现在列表,进入其 overview 页可见序列时间线已生成(页面含 sequence has been added 标记),入职日前的块自动挂到预入职区。

④ API 通道:API_ACCESS=True 时用 Token 访问 /api/employees/ 返回员工 JSON 数组、无 Token 返回 401——实测回显:

$ curl -s -H "Authorization: Token 88922630..." http://192.168.1.200:8131/api/employees/
[{"id":1,"first_name":"Admin",...},{"id":4,"first_name":"James",...}]
$ curl -s -o /dev/null -w '%{http_code}' http://192.168.1.200:8131/api/employees/
401

完整 API 用法(Token 生成、四个接口域、字段表)见 《ChiefOnboarding v2.5.0 API 使用详解》。

⑤ 任务进程:序列的定时触发由 django-q2 执行,确认方式为日志中看到 [Q] INFO Process-... pushing tasks at N(队列模型为 PostgreSQL 表,无需额外中间件)。

七、升级与备份

7.1 升级镜像(官方流程)

官方升级路径是「先停、再拉、再起」,升级前必须先备份数据库(升级会自动执行增量迁移,不可回退):

docker compose exec db pg_dump -U chief chiefonboarding > backup_$(date +%F).sql   # 先备份
docker compose down
docker compose pull
docker compose up -d
docker compose logs -f web   # 观察增量迁移日志直到 Booting worker

7.2 数据备份与恢复

全部状态都在 PostgreSQL 的 pgdata 卷里,每日定时备份示例:

# 备份
docker compose exec db pg_dump -U chief chiefonboarding | gzip > /opt/backups/chief_$(date +%F).sql.gz
# 恢复(到空库)
gunzip -c chief_2026-10-30.sql.gz | docker compose exec -T db psql -U chief chiefonboarding

上传的文件默认存数据库本地目录(未配置对象存储时),一并纳入备份范围;接入 S3 后文件在对象存储侧,见 《ChiefOnboarding v2.5.0 配置参数详解》 第八章。

八、故障排查速查

现象定位处置
web 状态 Created 不启动端口冲突ss -tlnp 找空闲端口,改 ports 后重新 up -d
首页 400 DisallowedHostALLOWED_HOSTS 缺主机名补上访问用的 IP/域名,逗号分隔
登录后刷新即退出HTTPS 语义强制内网 HTTP 加 HTTP_INSECURE=True,生产上 HTTPS
curl 连接失败但端口已映射首启迁移未完成docker compose logs -f web 等 Booting worker
web 反复重启连不上数据库核对 DATABASE_URL 与 db 服务名/密码;看 db 是否初始化完成
登录被锁django-axes 防爆破默认 10 次失败锁 24 小时,等冷却或调整 AXES_*(配置篇第九章)
容器内 python manage.py 报 No module named djangouv 虚拟环境改用 docker compose exec web /app/.venv/bin/python manage.py ...

九、参考链接

  1. 官方 Docker 部署文档:https://docs.chiefonboarding.com/deployment/docker.html (Compose 样例与健康检查说明,2026-10-30 读取)
  2. 官方镜像仓库:https://hub.docker.com/r/chiefonboarding/chiefonboarding (latest 对应 v2.5.0)
  3. GitHub 仓库:https://github.com/chiefonboarding/chiefonboarding (AGPLv3)

本专栏系列: