Flagsmith Docker Compose 部署实战

Flagsmith v2.287.0 Docker Compose 自托管部署实战:flags-only 三服务编排、数据库迁移、控制台初始化、组织/项目/环境与开关切换、SDK 端点验证、超管创建与备份,附官方 Helm Chart 的 Kubernetes 部署形态与九条排障实录,2026-10-28 实测。

FlagsmithDockerDocker ComposePostgreSQL特性开关2026/10/28

Flagsmith Docker Compose 部署实战

目标:在一台 Ubuntu 22.04 服务器上用 Docker Compose 从零部署 Flagsmith v2.287.0 自托管平台(flags-only 形态:统一服务 + 任务处理器 + PostgreSQL),完成数据库迁移、管理控制台初始化、组织/项目/环境创建、特性开关切换与 SDK 端点连通验证、Django 超管创建与数据备份。全部步骤与回显均在 2026-10-28 实测通过;文末附官方 Helm Chart 的 Kubernetes 部署形态溯源小节。

一、环境信息

项值
操作系统Ubuntu 22.04 LTS(x86_64)
Docker / ComposeDocker Engine 24+ / Compose v2(docker compose 子命令)
Flagsmith 版本v2.287.0(官方统一镜像,2026-10-28 拉取)
数据库PostgreSQL 15.5(postgres:15.5-alpine)
部署目录/opt/flagsmith
服务端口8142(映射到服务内部 8000)
专用子网10.89.60.0/24
Compose 项目名flagsmith-2.287.0-stack
部署形态flags-only(不含 Kafka/ClickHouse 实验分析栈)
示例账号root@flagsmith.local / admin@flagsmith.local,密码 Q1w2e3r4@2026

资源实测参考:API 服务约 583MB、任务处理器约 503MB、PostgreSQL 约 80MB(详见第十章),生产环境建议为该栈预留 ≥2GB 空闲内存。

二、镜像选型说明

Flagsmith 自 v2.x 起采用「统一镜像」交付:官方镜像 flagsmith/flagsmith 同时包含 Django REST API 与 React 管理控制台,通过入口命令 flagsmith 的子命令区分角色(serve API 服务、migrate 数据库迁移、run-task-processor 任务处理器、migrate-and-serve 默认先迁移后服务)。版本选型结论:

镜像标签说明选型建议
flagsmith/flagsmith:latest跟随最新稳定版(本次实测即 2.287.0,镜像内置 Gunicorn 23.0.0,拉取内容 116MB)快速验证可用,生产不建议
flagsmith/flagsmith:2.287.0版本化标签生产固定版本,便于回滚
docker.flagsmith.com/flagsmith/flagsmith官方自建仓库(官方 Compose 默认引用)直连拉取在国内网络实测失败,见第十二章 Q1

数据库镜像选官方 Compose 同款 postgres:15.5-alpine(官方编排固定版本,避免 16 大版本兼容性问题)。若需启用 A/B 实验分析,官方完整编排还会追加 Kafka 3.9.1、ClickHouse 25.12 等组件——资源开销显著,无实验需求时选 flags-only 形态(本文即此形态,对应官方仓库 docker-compose.flags-only.yml 的结构)。

三、前置条件

  • 服务器已安装 Docker Engine 与 Compose v2,docker compose version 可正常执行。
  • 端口 8142 未被占用(ss -ltn | grep 8142 无输出)。
  • 内存空闲 ≥2GB(free -m 确认)。
  • 如需从外网拉取镜像,确认网络可达(本环境经代理完成下载,见第十二章 Q1 的网络说明)。

四、部署步骤

4.1 创建部署目录与编排文件

mkdir -p /opt/flagsmith && cd /opt/flagsmith
vim docker-compose.yml

写入以下编排文件(依据官方 docker-compose.flags-only.yml 结构按本环境改造:显式子网、宿主端口 8142、固定项目名):

# Flagsmith v2.287.0 自托管(flags-only 形态,参照官方 docker-compose.flags-only.yml)
# 官方原版: https://github.com/Flagsmith/flagsmith/blob/main/docker-compose.flags-only.yml
name: flagsmith-2.287.0-stack

x-flagsmith-env: &flagsmith-env
  DATABASE_URL: postgresql://postgres:q1w2e3r4@postgres:5432/flagsmith
  USE_POSTGRES_FOR_ANALYTICS: 'true'
  ENVIRONMENT: production
  DJANGO_ALLOWED_HOSTS: '*'
  FLAGSMITH_DOMAIN: localhost:8142
  DJANGO_SECRET_KEY: flagsmith-demo-secret-key-2f8d
  TASK_RUN_METHOD: TASK_PROCESSOR
  PROMETHEUS_ENABLED: 'true'

networks:
  flagsmith_net:
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.60.0/24

volumes:
  pgdata:

services:
  postgres:
    image: postgres:15.5-alpine
    container_name: flagsmith-2.287.0-postgres
    environment:
      POSTGRES_PASSWORD: q1w2e3r4
      POSTGRES_DB: flagsmith
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - flagsmith_net
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -d flagsmith -U postgres']
      interval: 2s
      timeout: 2s
      retries: 20
      start_period: 20s

  migrate-db:
    image: flagsmith/flagsmith:latest
    container_name: flagsmith-2.287.0-migrate
    command: ['migrate']
    environment:
      <<: *flagsmith-env
    networks:
      - flagsmith_net
    depends_on:
      postgres:
        condition: service_healthy

  api:
    image: flagsmith/flagsmith:latest
    container_name: flagsmith-2.287.0-api
    command: ['serve']
    environment:
      <<: *flagsmith-env
    ports:
      - '8142:8000'
    networks:
      - flagsmith_net
    depends_on:
      migrate-db:
        condition: service_completed_successfully

  task-processor:
    image: flagsmith/flagsmith:latest
    container_name: flagsmith-2.287.0-task-processor
    command: ['run-task-processor']
    environment:
      <<: *flagsmith-env
    networks:
      - flagsmith_net
    depends_on:
      migrate-db:
        condition: service_completed_successfully

关键点说明:

  • migrate-db 是一次性任务:跑完 Django 迁移即退出,api/task-processor 通过 condition: service_completed_successfully 确保迁移完成后才启动。
  • x-flagsmith-env 锚点让三个 Flagsmith 服务共享同一份环境变量,避免漂移。
  • DJANGO_SECRET_KEY 多实例必须一致(本文为演示值,生产请换成 50 位以上随机串);DJANGO_ALLOWED_HOSTS 生产应收紧为实际域名。

4.2 启动与数据库迁移验证

docker compose up -d

实测回显(首次启动,创建网络/卷 → PostgreSQL 就绪 → 迁移退出 → 双服务启动):

 Network flagsmith-22870-stack_flagsmith_net Created
 Volume flagsmith-22870-stack_pgdata Created
 Container flagsmith-2.287.0-postgres Starting
 Container flagsmith-2.287.0-postgres Started
 Container flagsmith-2.287.0-postgres Waiting
 Container flagsmith-2.287.0-postgres Healthy
 Container flagsmith-2.287.0-migrate Starting
 Container flagsmith-2.287.0-migrate Started
 Container flagsmith-2.287.0-migrate Waiting
 Container flagsmith-2.287.0-migrate Exited
 Container flagsmith-2.287.0-task-processor Starting
 Container flagsmith-2.287.0-api Starting
 Container flagsmith-2.287.0-task-processor Started
 Container flagsmith-2.287.0-api Started

💡 注意:Compose 会把项目名 flagsmith-2.287.0-stack 规范化为小写字母数字(去掉点号),网络/卷实际命名为 flagsmith-22870-stack_flagsmith_net、flagsmith-22870-stack_pgdata,属正常现象。

查看迁移任务日志确认建表完成:

docker logs flagsmith-2.287.0-migrate

实测回显(节选,全程共 614 条 Applying ... OK;开头先等数据库就绪,末尾处理完最后一个应用):

2026-10-28T04:13:30.340742Z [info     ] Checking if database is ready for connections. [common.core.management.commands.waitfordb] positional_args=()
2026-10-28T04:13:30.352443Z [info     ] Successfully connected to the database. [common.core.management.commands.waitfordb] positional_args=()
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  ...
  Applying workflows_core.0012_alter_changerequest_options... OK
  Applying workflows_core.0013_reverse_change_request_ordering... OK

日志中的 axes.W004/axes.W006 是平台内置防暴力破解组件(django-axes)的配置告警,官方镜像自带、不影响功能,见第十二章 Q8。

4.3 服务就绪验证

docker compose ps
curl http://localhost:8142/health

实测回显(compose ps 显示三个 Flagsmith 服务均为内置健康检查的 healthy 状态;/health 返回两行 working):

NAME                               IMAGE                        COMMAND                  SERVICE   STATUS                    PORTS
flagsmith-2.287.0-api              flagsmith/flagsmith:latest   "flagsmith serve"        api       Up 19 minutes (healthy)   0.0.0.0:8142->8000/tcp, [::]:8142->8000/tcp
flagsmith-2.287.0-postgres         postgres:15.5-alpine         "docker-entrypoint.s…"   postgres  Up 20 minutes (healthy)   5432/tcp
flagsmith-2.287.0-task-processor   flagsmith/flagsmith:latest   "flagsmith run-task-…"   task-processor Up 19 minutes (healthy)  8000/tcp
<!DOCTYPE html>
<html>
  <head>
    <title>Flagsmith</title>
  </head>
  <body>
    <h1>Working</h1>
    <table style="text-align: center;">
      <tr>
        <td style="text-align: center; background-color: #464646;">
            <p style="font-size: 1.2em">DB</p>
        </td>
        <td style="text-align: center; background-color: #3c763d;">
            <p style="font-size: 1.2em">Working</p>
        </td>
      </tr>
      <tr>
        <td style="text-align: center; background-color: #464646;">
            <p style="font-size: 1.2em">Cache</p>
        </td>
        <td style="text-align: center; background-color: #3c763d;">
            <p style="font-size: 1.2em">Working</p>
        </td>
      </tr>
    </table>
  </body>
</html>

API 服务启动日志末尾可见 Gunicorn 工作进程与 Prometheus 指标端点就绪:

2026-10-28T04:14:09.575766Z [info     ] Prometheus metrics server started on port 9100 [common.gunicorn.metrics_server] positional_args=(9100,)
2026-10-28T04:14:09.580445Z [info     ] Booting worker with pid: 8     [gunicorn.error] positional_args=(8,)
2026-10-28T04:14:09.606369Z [info     ] Booting worker with pid: 9     [gunicorn.error] positional_args=(9,)
2026-10-28T04:14:09.679961Z [info     ] Booting worker with pid: 10    [gunicorn.error] positional_args=(10,)

4.4 初始化管理控制台(注册首个账号)

浏览器访问 http://<服务器IP>:8142/,进入控制台首页后点 Sign Up 注册首个账号(该账号默认即组织所有者)。本实测通过 REST API 完成等价操作:

curl -s -X POST http://localhost:8142/api/v1/auth/users/ \
  -H 'Content-Type: application/json' \
  -d '{"email":"admin@flagsmith.local","first_name":"Admin","last_name":"User","password":"Q1w2e3r4@2026"}'

实测回显(key 即会话 Token,后续管理 API 用 Authorization: Token <key> 认证):

{"id":1,"email":"admin@flagsmith.local","first_name":"Admin","last_name":"User","key":"448f55d8eacc1475514de7ab2a71f71081303ef0",...}

⚠️ 注意:注册密码必须通过平台内置强度校验——实测用示例弱口令 q1w2e3r4 注册会被拒绝并返回 "This password is too common.",改用含大小写+数字+符号的 Q1w2e3r4@2026 后成功。完整报错回显见第十二章 Q3。

4.5 创建组织、项目与环境

用上一步拿到的会话 Token 依次创建组织与项目:

TOKEN=448f55d8eacc1475514de7ab2a71f71081303ef0

curl -s -X POST http://localhost:8142/api/v1/organisations/ \
  -H "Authorization: Token $TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"Quzuo Demo Org"}'

实测回显:

{'id': 1, 'name': 'Quzuo Demo Org', 'created_date': '2026-10-28T04:16:02.913385Z', 'stop_serving_flags': False, 'persist_trait_data': True, 'num_seats': 3, 'subscription': {...}, 'require_join': False, 'restrict_project_create_to_admin': False}
curl -s -X POST http://localhost:8142/api/v1/projects/ \
  -H "Authorization: Token $TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"demo-app","organisation":1,"hide_disabled_flags":false}'

实测回显(精简展示):

{'id': 1, 'name': 'demo-app', 'organisation': 1, 'minimum_change_request_approvals': None}

⚠️ 注意(v2.287.0 实测行为):新版本创建项目后不会自动创建默认环境,查询 GET /api/v1/environments/?project=1 在任务处理器处理完成前返回 count: 0。需显式创建环境:

curl -s -X POST http://localhost:8142/api/v1/environments/ \
  -H "Authorization: Token $TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"Development","project":1}'

实测回显(环境创建成功即返回两类 SDK 密钥:api_key 为客户端密钥,server_side_api_key 为 ser. 前缀服务端密钥):

id: 1 | name: Development | api_key(client): TinUTVci4mXtPVbBAyJjvw | server_key: ser.S9JAfMUEgrtrPWmrqrw97E

同法再创建 Production 环境(id=2)。所有环境的密钥后续随时可用 GET /api/v1/environments/?project=1(带 Token)重新查询。

4.6 创建特性开关并切换

# 创建第一个特性(多变量形态,创建时即初始化环境状态)
curl -s -X POST http://localhost:8142/api/v1/projects/1/features/ \
  -H "Authorization: Token $TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"banner-toggle","description":"首页横幅开关","initial_value":true,"type":"MULTIVARIATE","default_enabled":true,"multivariate_options":[]}'

# 创建第二个特性(普通开关)
curl -s -X POST http://localhost:8142/api/v1/projects/1/features/ \
  -H "Authorization: Token $TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"checkout-v2","description":"新版结算流程","initial_value":"false","default_enabled":false}'

实测回显:

{'id': 1, 'name': 'banner-toggle', 'description': '首页横幅开关', 'initial_value': True, 'default_enabled': True, 'type': 'MULTIVARIATE', 'multivariate_options': [], 'is_archived': False, 'tags': [], 'owners': None, 'uuid': '2c78d40c-70a2-4377-a30e-6c1cda9a872f'}
{'id': 2, 'name': 'checkout-v2', 'description': '新版结算流程', 'default_enabled': False}

⚠️ 注意:initial_value 字段实测要求字符串("false"/"true"),直接传布尔 false 会返回 400({'initial_value': ['A valid integer is required.']} 之类的校验错误),见第十二章 Q5。

特性在环境中的实际状态由 featurestate 记录承载。查询 Development 环境全部特性状态:

curl -s "http://localhost:8142/api/v1/environments/TinUTVci4mXtPVbBAyJjvw/featurestates/" \
  -H "Authorization: Token $TOKEN"

实测回显(节选;feature_state_value 为 {"type": ..., "value": ...} 包装结构):

count: 3
 fs_id: 1 | feature: banner-toggle | enabled: True | value: {'type': 'unicode', 'value': None}
 fs_id: 2 | feature: checkout-v2 | enabled: False | value: {'type': 'unicode', 'value': 'false'}

把 checkout-v2 在 Development 环境切换为开启(fs_id: 3 为该环境 checkout-v2 的 featurestate id):

curl -s -X PATCH http://localhost:8142/api/v1/environments/TinUTVci4mXtPVbBAyJjvw/featurestates/3/ \
  -H "Authorization: Token $TOKEN" -H 'Content-Type: application/json' \
  -d '{"enabled":true,"feature_state_value":true}'

实测回显:

fs_id: 3 | enabled: True | value: True | version: 1

4.7 SDK 端点连通验证

用客户端环境密钥请求 SDK 求值接口(X-Environment-Key 请求头认证):

curl -s "http://localhost:8142/api/v1/flags/" \
  -H "X-Environment-Key: TinUTVci4mXtPVbBAyJjvw"

实测回显(切换 checkout-v2 为开启后):

[
    {
        "enabled": true,
        "feature_state_value": null,
        "feature": {
            "id": 2,
            "name": "checkout-v2",
            "type": "STANDARD"
        },
        "feature_segment": null
    },
    {
        "enabled": true,
        "feature_state_value": null,
        "feature": {
            "id": 1,
            "name": "banner-toggle",
            "type": "MULTIVARIATE"
        },
        "feature_segment": null
    }
]

服务端 SDK 的本地求值场景改用 ser. 前缀服务端密钥拉取整份环境文档:

curl -s "http://localhost:8142/api/v1/environment-document/" \
  -H "X-Environment-Key: ser.S9JAfMUEgrtrPWmrqrw97E"

实测回显(结构精简):

api_key: ser.S9JAfMUEgrtrPWmrqrw97E
project: demo-app | env: Development
 - banner-toggle | enabled: True | value: None
 - checkout-v2 | enabled: True | value: True
 - another-flag | enabled: False | value: None

至此控制台初始化与开关链路全部打通。分段(Segment)圈人、身份级求值等进阶用法见本系列运维实战篇。

4.8 创建 Django 超管(Admin 后台)

Flagsmith 保留 Django Admin 后台(/admin/),用于核心数据表 CRUD。用 createsuperuser --noinput 非交互创建(密码经 DJANGO_SUPERUSER_PASSWORD 注入):

docker exec flagsmith-2.287.0-api sh -c \
  "cd /app && DJANGO_SUPERUSER_PASSWORD='Q1w2e3r4@2026' \
   python manage.py createsuperuser --noinput \
   --email root@flagsmith.local --first_name Root --last_name Admin \
   --sign_up_type NO_INVITE"

实测回显(成功创建无输出、退出码 0;若缺参数会报错,见第十二章 Q6)。

浏览器访问 http://<服务器IP>:8142/admin/,用 root@flagsmith.local / Q1w2e3r4@2026 登录即可。用 curl 脚本模拟登录会因 CSRF 校验被拒(403,见第十二章 Q7),属预期安全行为。

4.9 数据库备份

mkdir -p /opt/flagsmith/backup
docker exec flagsmith-2.287.0-postgres \
  pg_dump -U postgres -d flagsmith > /opt/flagsmith/backup/flagsmith_20261028.sql
ls -lh /opt/flagsmith/backup/flagsmith_20261028.sql

实测回显(产物头部为 PostgreSQL 标准转储头):

--
-- PostgreSQL database dump
--

-- Dumped from database version 15.5
-- Dumped by pg_dump version 15.5 (Debian 15.5-1.pgdg120+1)
-rw-r--r-- 1 root root 646K Oct 28 04:40 /opt/flagsmith/backup/flagsmith_20261028.sql

数据段完整性用 COPY 语句数核对:

grep -c "^COPY" /opt/flagsmith/backup/flagsmith_20261028.sql
169

(备份策略与恢复演练详见本系列运维实战篇。)

五、数据持久化说明

数据落盘位置说明
全部业务数据命名卷 flagsmith-22870-stack_pgdata → PostgreSQL 数据目录组织/项目/环境/开关/身份/分段全部在库
开关分析数据同上(USE_POSTGRES_FOR_ANALYTICS: 'true')未启用时存内存,重启丢失
控制台静态资源镜像内置无需挂载

要点:

  • 首次启动执行 docker compose up 时自动完成建库迁移;官方文档明确「升级时由 Django Migrations 自动执行结构变更」,升级仅需换镜像标签重启(migrate-db 服务会自动补跑增量迁移)。
  • 销毁数据用 docker compose down -v(会删除卷),仅停服用 docker compose down。
  • 备份以 pg_dump 为主,恢复 cat xxx.sql | docker exec -i <postgres> psql -U postgres -d flagsmith。

六、环境变量表

本编排涉及的环境变量(完整体系详见本系列配置参数篇,此处列部署强相关项):

变量本编排取值说明
DATABASE_URLpostgresql://postgres:q1w2e3r4@postgres:5432/flagsmith数据库连接串,唯一强依赖
DJANGO_SECRET_KEYflagsmith-demo-secret-key-2f8d(演示值)会话/加密基钥,多实例必须一致,生产换强随机值
DJANGO_ALLOWED_HOSTS*Host 头白名单,生产收紧为实际域名
FLAGSMITH_DOMAINlocalhost:8142对外访问域名/端口(构造绝对链接用)
ENVIRONMENTproduction运行模式标记
USE_POSTGRES_FOR_ANALYTICS'true'API 调用/开关分析数据落 PostgreSQL
TASK_RUN_METHODTASK_PROCESSOR异步任务交给独立 task-processor 服务
PROMETHEUS_ENABLED'true'开启 :9100 指标端点
POSTGRES_PASSWORD / POSTGRES_DBq1w2e3r4 / flagsmith数据库镜像初始化参数,须与 DATABASE_URL 匹配
ALLOW_REGISTRATION_WITHOUT_INVITE未设置(默认开放注册)封闭场景可禁邀请注册
PREVENT_SIGNUP未设置设 'true' 完全关闭注册入口

七、配置参数说明

编排文件中与稳定性直接相关的参数逐项解释:

  • healthcheck(postgres):pg_isready -d flagsmith -U postgres,2 秒间隔/20 次重试/20 秒缓冲,保证迁移在库真正就绪后才执行——Flagsmith 服务本身还带镜像内置健康检查(compose ps 可见 healthy),探活 URL 即 /health 的库/缓存自检逻辑。
  • depends_on 条件:service_healthy(等库就绪)与 service_completed_successfully(等迁移成功)两级串联,避免「库没起就迁移」「没迁移就服务」两类经典启动竞态。
  • ports: '8142:8000':统一服务同时承载控制台与 API/SDK,只需暴露这一个端口;task-processor 无需对外端口。
  • ipam.subnet: 10.89.60.0/24:显式子网避免与宿主机网段及其他栈冲突,多套栈并存时按 10.89.x.x 依次错开。
  • name: flagsmith-2.287.0-stack:固定项目名,保证卷/网络命名稳定(点号会被规范化为空,见 4.2 提示)。

八、配置文件挂载

flags-only 形态无需挂载任何配置文件——全部配置经环境变量注入(Django 侧 DATABASE_URL、DJANGO_SECRET_KEY 等),这是 Flagsmith 官方推荐的配置方式。需要挂载的典型场景只有两类:

  1. TLS 反向代理:在编排中追加 Nginx/Caddy 服务并挂载证书目录,对外 443、对内转发 8000,同时把 DJANGO_ALLOWED_HOSTS、FLAGSMITH_DOMAIN 改为真实域名(官方文档「Access Flagsmith Remotely」章节推荐的正是反代 + 环境变量组合)。
  2. 自定义字体等静态资源:控制台支持经 FLAGSMITH_FRONTEND_BASE 相关变量与挂载定制品牌资源,一般部署用不到。

九、等价 docker run(单机快速验证)

无编排文件时,可用两条命令拉起最小可用验证环境(与上文编排等价的简化形态,数据不持久化,仅供冒烟):

docker network create flagsmith-smoke

docker run -d --name flagsmith-smoke-db \
  --network flagsmith-smoke \
  -e POSTGRES_PASSWORD=q1w2e3r4 -e POSTGRES_DB=flagsmith \
  postgres:15.5-alpine

docker run -d --name flagsmith-smoke-app \
  --network flagsmith-smoke -p 8142:8000 \
  -e DATABASE_URL=postgresql://postgres:q1w2e3r4@flagsmith-smoke-db:5432/flagsmith \
  -e DJANGO_SECRET_KEY=flagsmith-demo-secret-key-2f8d \
  -e DJANGO_ALLOWED_HOSTS='*' \
  -e FLAGSMITH_DOMAIN=localhost:8142 \
  -e ENVIRONMENT=production \
  flagsmith/flagsmith:latest migrate-and-serve

migrate-and-serve 是镜像默认子命令:先执行迁移再启动服务,等待数据库就绪的重试由 waitfordb 内置完成。生产部署仍以第四章 Compose 编排为准(含任务处理器与显式健康检查)。

十、常用运维命令

# 状态与健康
docker compose ps
curl -s http://localhost:8142/health | grep -o '<p style="font-size: 1.2em">Working</p>'

# 日志
docker compose logs -f api
docker compose logs task-processor | tail -50

# 重启与更新版本(示例:升级镜像标签后)
docker compose pull && docker compose up -d

# 扩容 API 实例(无状态,可横向扩)
docker compose up -d --scale api=2

# 数据库直连
docker exec -it flagsmith-2.287.0-postgres psql -U postgres -d flagsmith

# 停止与彻底清理
docker compose down
docker compose down -v   # 连同数据卷一起删除(危险)

资源占用实测(docker stats --no-stream,空载稳定状态):

flagsmith-2.287.0-api: CPU 0.11% MEM 583.5MiB / 15.36GiB
flagsmith-2.287.0-task-processor: CPU 0.09% MEM 503.5MiB / 15.36GiB
flagsmith-2.287.0-postgres: CPU 0.01% MEM 80.1MiB / 15.36GiB

任务处理器空闲时表现为常驻轮询(每分钟拉取待执行任务,日志为周期性循环输出),属正常现象。

十一、Kubernetes 部署形态(官方 Helm Chart)

本节为联网溯源内容:以下信息均来自 Flagsmith 官方文档与官方 Chart 仓库(查询日期 2026-10-28),本批次未做集群实测(集群实测由 K1 批次另行开展,请勿将本节视为实测结论)。

Flagsmith 官方维护 Helm Chart(仓库 Flagsmith/flagsmith-charts,Chart Museum 地址 https://flagsmith.github.io/flagsmith-charts/ ),2026-10-28 实查版本为 chart 0.85.0、appVersion: 2.286.0。标准接入方式:

helm repo add flagsmith https://flagsmith.github.io/flagsmith-charts/
helm repo update
helm install flagsmith flagsmith/flagsmith -f values.yaml

官方 Chart 的架构事实(源自 Chart 源码与官方 K8s 文档):

  • 组件拓扑:默认 allInOne: true —— API 与前端合并为单个 frontend Deployment(flagsmith.allInOne Deployment);taskProcessor Deployment 独立。设置 separateApiAndFrontend: true 可拆分为 frontend + api 两个 Deployment。
  • 数据库:默认捆绑 Bitnami PostgreSQL 子 Chart(依赖 postgresql 12.5.8,别名 devPostgresql,官方标注仅开发用途);生产用 databaseExternal.enabled=true + databaseExternal.url 指向外部 PostgreSQL(官方文档给出以 K8s Secret 组装 URL 的示例)。
  • 密钥管理:secretKey(即 DJANGO_SECRET_KEY)通过 existingSecret/existingSecretKey 引用 Secret,或由 Chart 生成;官方升级注意事项特别提示 chart 0.12.0 起该值变更路径,升级前必须显式固定,否则会话失效。
  • 暴露方式:Chart 内置 Ingress 资源(ingress.enabled),可选 cert-manager 注解;frontend.ingress.url/api.ingress.url 分别指定前端与 API 域名(合并部署时同一域名)。
  • 副本与资源建议(官方 values 默认值):allInOne.replicas: 2、api.replicas: 4、taskProcessor.replicas: 2;官方文档「Sizing and Scaling」给出每 pod 建议基线 1 vCPU / 2GB 内存,API 扩容无状态可直接横向加副本。
  • 可观测:Chart 预置 Prometheus 指标与 ServiceMonitor 支持(serviceMonitor.enabled),自托管仓库的参考示例即以 kube-prometheus-stack 抓取 API 与 task processor 指标。
  • 企业镜像:flagsmith.flagsmith-frontend/flagsmith.flagsmith-api 镜像默认 docker.flagsmith.com/flagsmith/flagsmith:2.286.0(Enterprise 渠道),社区可改回 Docker Hub 官方镜像。

选型结论:单机/中小规模用本文 Compose 形态即可;多团队共享、需要滚动升级/HPA/Ingress 体系时走官方 Helm Chart,且两者数据模型一致(PostgreSQL 单库),迁移成本低。

十二、常见问题(排障实录)

以下问题全部在本次部署实测中真实遇到,回显为原始报错。

Q1:拉取 docker.flagsmith.com/flagsmith/flagsmith:latest 报「no such host」。 实测报错(官方 Compose 文件默认引用官方自建仓库,国内网络直连解析失败):

Error response from daemon: Get "https://docker.flagsmith.com/v2/": dial tcp: lookup docker.flagsmith.com: no such host

解法:改用 Docker Hub 官方同名镜像 flagsmith/flagsmith(本环境经代理 192.168.1.62:7897 拉取,版本标签一致,镜像 OCI 标签确认 org.opencontainers.image.version=2.287.0)。生产可自行同步镜像到私有仓库。

Q2:docker compose up 报端口冲突。 实测报错(本环境 8140 被同机其他栈占用):

Error response from daemon: driver failed programming external connectivity on endpoint flagsmith-2.287.0-api: Bind for 0.0.0.0:8140 failed: port is already allocated

解法:ss -ltn | grep <端口> 先确认,再改编排端口映射(本实录最终使用 8142)。多套栈并存时端口规划先行。

Q3:注册接口拒绝弱密码。 实测报错(POST /api/v1/auth/users/,密码 q1w2e3r4):

{'password': ["This password is too common."]}

解法:改用满足强度要求的密码(大小写+数字+符号,如 Q1w2e3r4@2026)。平台内置 Django 密码校验器,q1w2e3r4 命中「常见密码」规则被拒。

Q4:创建项目后查不到环境。 实测现象:POST /api/v1/projects/ 返回 201,随后 GET /api/v1/environments/?project=1 返回 {'count': 0, ...},且任务处理器启动日志同时出现启动横幅。解法:v2.287.0 项目创建不保证自动建环境,显式 POST /api/v1/environments/ 创建(见 4.5),创建返回体即含客户端/服务端两类密钥。

Q5:创建特性时 initial_value 传布尔报 400。 实测报错(initial_value: false):

{'initial_value': ['A valid integer is required.']}

解法:该字段按字符串传("false"/"true"/数值字符串),平台内部按特性值类型解释。改传 "false" 后创建成功(见 4.6)。

Q6:createsuperuser --noinput 缺参数报错。 实测报错(v2.287.0 的用户模型为全名制 + 注册类型必填):

CommandError: You must use --noinput or --username and --email with --noinput, --first_name and --last_name and --sign_up_type with --noinput.

解法:完整参数形如 4.8 示例:--email、--first_name、--last_name、--sign_up_type NO_INVITE 加 DJANGO_SUPERUSER_PASSWORD 环境变量。若超管账号与普通账号同邮箱,也可直接把既有用户提升:is_staff=True; is_superuser=True(manage.py shell 两行)。

Q7:curl 模拟 /admin/ 登录 403。 实测报错(POST /admin/login/):

403 Forbidden — CSRF cookie not set.

原因:Django Admin 对 CSRF 校验严格,且登录页 cookie 是 Secure/会话级,curl 裸模拟拿不到合法 CSRF token;另平台内置 django-axes 防爆破,多次失败会触发锁定告警。解法:浏览器正常登录即可;脚本化验证可用 manage.py shell 内的 django.test.Client().login(...)(实测返回 login ok: True 并成功 GET /admin/),或走管理 REST API(Token 认证)。

Q8:启动日志出现 axes.W004 / axes.W006 告警。 实测回显:

?: (axes.W004) You have a deprecated setting AXES_ONLY_USER_FAILURES configured in your project settings
?: (axes.W006) AXES_LOCKOUT_PARAMETERS does not contain 'ip_address'. This configuration allows attackers to bypass rate limits by rotating User-Agents or Cookies.

原因:官方镜像内置 django-axes 的默认配置沿用了旧参数名,属上游已知告警,功能不受影响。公网暴露时建议在反代层叠加限流,不要尝试在环境变量里「修」这两个告警(属代码内配置)。

Q9:照官方文档克隆 Flagsmith/self-hosted 仓库后发现不是 Compose 工程。 现象:官方文档「Deployment → Docker」开头引导 git clone https://github.com/Flagsmith/self-hosted.git && docker-compose up,但该仓库 main 分支当前是「Flagsmith Enterprise 的 Kubernetes/Helmfile 参考示例」。解法:自托管 Compose 的权威来源改用主仓库根目录的 docker-compose.yml / docker-compose.flags-only.yml(本文编排即基于后者),文档滞后问题已在本文成文时点(2026-10-28)核实。

十三、参考链接