Flagsmith 常用命令与运维实战
Flagsmith v2.287.0 自托管运维实战:manage.py 核心命令(migrate/collectstatic/createsuperuser/bootstrap/shell)实测、REST API 管理面与 SDK 求值端点全链路实测回显、Prometheus 指标观测、pg_dump 备份与卷盘点、升级回滚与高频排障。
Flagsmith 常用命令与运维实战
目标:面向已按部署篇完成 Flagsmith v2.287.0 自托管安装的运维/后端工程师,覆盖 Django
manage.py核心命令、REST API 管理面全链路(认证→组织/项目/环境→特性→分段→开关切换)、SDK 端点求值实测、Prometheus 指标观测、pg_dump备份与卷盘点,以及升级回滚与高频排障。所有命令与回显均在部署篇同环境(PostgreSQL 15.5 + 统一镜像三服务,端口 8142)实测采集,逐行真实。
一、环境信息
| 项 | 值 |
|---|---|
| Flagsmith 版本 | v2.287.0(flagsmith/flagsmith:latest,metrics 端点 flagsmith_build_info 实证) |
| 部署形态 | Compose 三服务(api / task-processor / postgres),服务端口 8142→8000 |
| 管理账号 | admin@flagsmith.local(会话 Token 认证)、root@flagsmith.local(Django 超管),密码 Q1w2e3r4@2026 |
| 示例数据 | 组织 Quzuo Demo Org(id=1)、项目 demo-app(id=1)、环境 Development/Production、特性 banner-toggle(id=1)/checkout-v2(id=2) |
| 密钥 | 客户端环境密钥 TinUTVci4mXtPVbBAyJjvw、服务端密钥 ser.S9JAfMUEgrtrPWmrqrw97E(实测值,生产请替换) |
| 管理会话 Token | 448f55d8eacc1475514de7ab2a71f71081303ef0(注册接口返回,下文 $TOKEN) |
二、常用命令速查
| 命令 | 用途 | 生效方式 |
|---|---|---|
docker compose ps / docker compose logs -f api | 服务状态/日志 | 即时 |
curl http://localhost:8142/health | 库/缓存健康自检 | 即时 |
curl http://localhost:9100/metrics(容器内端口) | Prometheus 指标 | 即时 |
python manage.py migrate | 数据库结构迁移 | 需进服务内部执行 |
python manage.py collectstatic --noinput | 收集静态资源(升级后) | 需进服务内部执行 |
python manage.py createsuperuser --noinput ... | 建 Django 超管 | 需进服务内部执行 |
python manage.py bootstrap | 空库一键初始化(超管+组织+项目) | 需 ALLOW_ADMIN_INITIATION_VIA_CLI=true |
python manage.py shell / dbshell | Django ORM / 数据库直连 | 需进服务内部执行 |
docker exec flagsmith-2.287.0-postgres pg_dump ... | 逻辑备份 | 即时 |
docker compose pull && docker compose up -d | 升级版本 | 自动补跑迁移 |
💡 「进服务内部执行」的统一姿势:
docker exec flagsmith-2.287.0-api sh -c "cd /app && python manage.py <命令>";服务默认工作目录为/app。
三、manage.py 命令实测
3.1 子命令全景
docker exec flagsmith-2.287.0-api sh -c "cd /app && python manage.py help"
实测回显(节选;按 Django 应用分组,重点组如下):
Available subcommands:
[api]
generate_mcp_tool_catalogue
[app_analytics]
migrate_analytics
populate_buckets
sendapiusagetoinflux
[auth]
changepassword
createsuperuser
[authtoken]
drf_create_token
[axes]
axes_list_attempts
axes_reset
axes_reset_failure_logs
axes_reset_ip
axes_reset_ip_username
axes_reset_logs
axes_reset_username
[core]
bootstrap
docgen
makemigrations
rollbackmigrationsappliedafter
start
waitfordb
[django]
check
compilemessages
createcachetable
运维高频组解读:[axes] 组是登录防爆破组件的解锁命令(axes_reset 清失败记录,误锁时救命);[core] 组的 waitfordb/start 是镜像入口内部使用;rollbackmigrationsappliedafter 用于迁移回滚场景。
3.2 migrate(迁移)
首次建库由部署篇编排的 migrate-db 服务完成(614 条 Applying ... OK,见部署篇 4.2)。升级或手动补跑时直接执行:
docker exec flagsmith-2.287.0-api sh -c "cd /app && python manage.py migrate"
实测回显(库已最新时的幂等输出,仅提示缓存表已存在,无任何迁移动作):
Cache table 'environment-documents' already exists.
Cache table 'onboarding-request-throttle' already exists.
3.3 collectstatic(静态资源)
docker exec flagsmith-2.287.0-api sh -c "cd /app && python manage.py collectstatic --noinput"
实测回显(镜像已内置收集产物,重复执行为零拷贝):
0 static files copied to '/app/static', 161 unmodified.
统一镜像内置控制台静态资源,正常运行无需手动执行;该命令主要在自定义前端构建/挂载场景下使用。
3.4 createsuperuser(创建超管)
Django Admin(/admin/)入口账号。实测(完整参数形态与缺参报错见部署篇 Q6):
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;重复执行同邮箱报 user with this Email address already exists.;对既有普通账号可经 manage.py shell 将 is_staff/is_superuser 置 True 提升为超管(运维篇推荐路径,避免重复账号)。
3.5 bootstrap(空库一键初始化)
官方设计的一键初始化命令(创建默认超管+组织+项目),先看参数面:
docker exec flagsmith-2.287.0-api sh -c "cd /app && python manage.py help bootstrap"
实测回显(节选):
usage: manage.py bootstrap [-h] [--email ADMIN_EMAIL]
[--organisation-name ORGANISATION_NAME]
[--project-name PROJECT_NAME] [--version]
...
options:
-h, --help show this help message and exit
--email ADMIN_EMAIL Email address for the superuser
--organisation-name ORGANISATION_NAME
Project name
--project-name PROJECT_NAME
Project name
实测两条关键行为(排障实录):
- 必须显式开开关:环境变量
ALLOW_ADMIN_INITIATION_VIA_CLI=true(settings 默认False,官方文档同口径)。实测不开时命令执行后无任何创建动作。 - 非空库静默跳过:在已有用户的库上执行(本环境实测),命令正常退出(exit 0)但不创建任何对象——源码判定为「库里存在任意用户即跳过」(
should_skip_create_initial_superuser()返回FFAdminUser.objects.exists()),组织/项目同构判定。因此 bootstrap 只适用于全新空库;已有实例要补账号/组织请走 3.4 与 REST API。
另注:bootstrap 创建的初始超管密码为空(源码 password=None),设计上配合首次登录设密流程;脚本化初始化建议直接用 3.4 的 createsuperuser + REST API 组合,行为更可控。官方还提供无控制台环境的 Web 初始化端点 /api/v1/users/config/init/(表单式,见官方文档)。
3.6 shell 与 dbshell(ORM/SQL 直连)
# ORM 通道:查任务队列积压、查运行时元数据等
docker exec flagsmith-2.287.0-api sh -c "cd /app && python manage.py shell -c \"
from task_processor.models import Task
print('total tasks:', Task.objects.count())
for t in Task.objects.all()[:5]: print(' -', t.task_name, t.status)\""
实测回显:
total tasks: 7
- create-environment 1 SUCCESS
- create-environment 2 SUCCESS
- create-project 1 SUCCESS
...
# SQL 通道
docker exec -it flagsmith-2.287.0-postgres psql -U postgres -d flagsmith
运维用法示例(创建服务端环境密钥,实测;服务端密钥无管理 API,ORM 是官方通道):
docker exec flagsmith-2.287.0-api sh -c "cd /app && python manage.py shell -c \"
from environments.models import Environment, EnvironmentAPIKey
key = EnvironmentAPIKey.objects.create(environment=Environment.objects.get(id=1), name='server-side-demo')
print('SERVER_KEY=' + key.key)\""
实测回显:
SERVER_KEY=ser.S9JAfMUEgrtrPWmrqrw97E
四、REST API 管理面实测
管理面统一以 Authorization: Token <管理Token> 认证(Token 来自注册/登录接口的 key 字段)。以下为组织/项目/环境/特性/分段全链路实测记录。
4.1 组织、项目与环境
# 建组织
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, ...}
# 建项目
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, ...}
# 建环境(v2.287.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 密钥):
id: 1 | name: Development | api_key(client): TinUTVci4mXtPVbBAyJjvw | server_key: ser.S9JAfMUEgrtrPWmrqrw97E
4.2 特性创建与环境状态
# 建特性(注意 initial_value 必须字符串形态)
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': 2, 'name': 'checkout-v2', 'description': '新版结算流程', 'default_enabled': False}
# 查环境特性状态(客户端密钥当路径段用)
curl -s "http://localhost:8142/api/v1/environments/TinUTVci4mXtPVbBAyJjvw/featurestates/" \
-H "Authorization: Token $TOKEN"
实测回显(精简):
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'}
4.3 开关切换(PATCH featurestates)
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}'
实测回显(version 自增,供 SDK 增量同步比对):
fs_id: 3 | enabled: True | value: True | version: 1
切换后 SDK 侧立即生效(求值实测见第五章)。
4.4 分段(Segment)与条件圈人
创建「email 含 @flagsmith.local 即 VIP」的分段(规则两层嵌套:ALL → ANY → conditions):
curl -s -X POST http://localhost:8142/api/v1/projects/1/segments/ \
-H "Authorization: Token $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"vip-users","rules":[{"type":"ALL","rules":[{"type":"ANY","conditions":[{"operator":"CONTAINS","property":"email","value":"@flagsmith.local"}]}],"conditions":[]}]}'
实测回显:
{'id': 1, 'name': 'vip-users', 'uuid': 'e21d0c0e-7f9c-42a8-bc37-4cfa25e37d68'}
给分段做特性覆盖(优先级高于环境默认值):先建覆盖关系,再建带 feature_segment 的状态:
# 建覆盖关系
curl -s -X POST http://localhost:8142/api/v1/features/feature-segments/ \
-H "Authorization: Token $TOKEN" -H 'Content-Type: application/json' \
-d '{"feature":1,"segment":1,"environment":1}'
# 实测:{'id': 1, 'feature': 1, 'segment': 1, 'environment': 1, 'priority': 1, 'uuid': '...'}
# 建覆盖状态(值用 {type, string_value} 包装结构;type 取 unicode/bool/int/float)
curl -s -X POST http://localhost:8142/api/v1/features/featurestates/ \
-H "Authorization: Token $TOKEN" -H 'Content-Type: application/json' \
-d '{"environment":1,"feature":1,"feature_segment":1,"enabled":true,"feature_state_value":{"type":"unicode","string_value":"vip-banner"}}'
实测回显:
fs_id: 4 | feature_segment: 1 | enabled: True | value: {'type': 'unicode', 'value': 'vip-banner'}
排障实录(结构踩坑三连,均为真实报错):
- 条件块字段名是
conditions而非rules(传错报{'rules': ['Invalid rule.']});操作符是CONTAINS等大写枚举(传%报{'operator': ['"%" is not a valid choice.']})。 - 覆盖值必须
{type, string_value}包装(裸字符串报{'feature_state_value': ['Invalid data. Expected a dictionary with keys...']})。 - 带覆盖值的 featurestate 用平铺端点
POST /api/v1/features/featurestates/创建(不是嵌套在 feature-segments 下)。
五、SDK 端点实测
5.1 客户端密钥拉取开关(GET /api/v1/flags/)
curl -s "http://localhost:8142/api/v1/flags/" -H "X-Environment-Key: TinUTVci4mXtPVbBAyJjvw"
实测回显(checkout-v2 切换开启后;switch 前该特性 enabled: false):
[
{
"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
}
]
5.2 身份求值(POST /api/v1/identities/)
对单个身份求值并落身份特征,分段命中实时体现(对照实验:user-1 命中 vip 分段,user-2 不命中):
curl -s -X POST http://localhost:8142/api/v1/identities/ \
-H "X-Environment-Key: TinUTVci4mXtPVbBAyJjvw" -H 'Content-Type: application/json' \
-d '{"identifier":"user-1","traits":[{"trait_key":"email","trait_value":"alice@flagsmith.local"}]}'
实测回显(精简,命中 vip-users 分段 → banner-toggle 值为覆盖值):
- banner-toggle | enabled: True | value: vip-banner | segment: True
- checkout-v2 | enabled: True | value: True | segment: False
对照身份(不匹配条件):
# user-2:email bob@example.com
实测回显:
- banner-toggle | enabled: True | value: None | segment: False
- checkout-v2 | enabled: True | value: True | segment: False
5.3 服务端密钥拉取环境文档(GET /api/v1/environment-document/)
本地求值(Local Evaluation)模式的数据源,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
六、备份与卷盘点
6.1 卷与网络清单
docker volume ls --format '{{.Name}}' | grep flagsmith
docker network ls --format '{{.Name}}' | grep flagsmith
实测回显(命名卷 1 个 + 专用网络 1 个;项目名的点号被规范化):
flagsmith-22870-stack_pgdata
flagsmith-22870-stack_flagsmith_net
盘点结论:Flagsmith 自托管的数据面只有 PostgreSQL 一处——pgdata 卷承载全部业务数据(组织/项目/环境/开关/身份/分段/任务记录),分析数据经 USE_POSTGRES_FOR_ANALYTICS 也在库内;镜像与静态资源无状态,可随时重建。
6.2 逻辑备份(pg_dump)
docker exec flagsmith-2.287.0-postgres \
pg_dump -U postgres -d flagsmith > /opt/flagsmith/backup/flagsmith_20261028.sql
实测产物:646K,标准 PostgreSQL 转储(头部 -- Dumped from database version 15.5),COPY 数据段 169 个。完整性核对命令与回显:
grep -c "^COPY" /opt/flagsmith/backup/flagsmith_20261028.sql
169
恢复(演练到新库的等价命令):
cat /opt/flagsmith/backup/flagsmith_20261028.sql | \
docker exec -i flagsmith-2.287.0-postgres psql -U postgres -d flagsmith
运维建议:升级前必备份;恢复目标库必须是空库(否则对象冲突);备份文件含用户敏感信息,按密级存放。
七、监控与日志
健康自检(DB/Cache 两项自检,均 Working 为健康):
curl http://localhost:8142/health
实测回显(HTML 表格形态,节选):
<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>
Prometheus 指标(PROMETHEUS_ENABLED=true 时容器内 :9100):
docker exec flagsmith-2.287.0-api sh -c \
"python -c \"import urllib.request; d=urllib.request.urlopen('http://localhost:9100/metrics').read().decode(); lines=[l for l in d.splitlines() if l.startswith('flagsmith')]; print(len(lines),'flagsmith lines'); print(chr(10).join(lines[:6]))\""
实测回显(961 条 flagsmith_* 指标行,摘录):
961 flagsmith lines
flagsmith_segment_membership_backfill_identities_total 0.0
flagsmith_segment_membership_refresh_failures_total 0.0
flagsmith_cohorts_csv_syncs_total 0.0
flagsmith_build_info{ci_commit_sha="c582d5b573e639c6343ee9c21913681baed9118a",version="2.287.0"} 1.0
flagsmith_http_server_requests_total{method="GET",response_status="200",route="/health"} 1.0
flagsmith_http_server_requests_total{method="POST",response_status="201",route="/api/v1/auth/users/"} 1.0
监控要点:flagsmith_build_info 直接暴露版本号(资产盘点/升级核对);flagsmith_http_server_requests_total 按 method/status/route 统计请求(SDK 流量水位);任务侧盯 flagsmith_segment_membership_refresh_failures_total 等失败计数。
日志:docker compose logs -f api(Gunicorn worker/请求日志)与 docker compose logs task-processor(任务轮询/执行日志);经 LOG_FORMAT=json 可切结构化采集。
资源水位实测(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
八、升级与回滚
标准升级路径(官方语义:结构变更由 Django Migrations 自动执行):
cd /opt/flagsmith
docker exec flagsmith-2.287.0-postgres pg_dump -U postgres -d flagsmith > backup/pre-upgrade.sql # 1. 先备份
docker compose pull # 2. 拉新镜像
docker compose up -d # 3. 滚动重建(migrate-db 服务自动补跑增量迁移)
curl -s http://localhost:8142/health | grep -c Working # 4. 健康自检(期望 2)
回滚:把编排镜像标签改回旧版本(生产建议固定版本标签而非 latest)后 docker compose up -d;数据库如需回退用 pre-upgrade.sql 恢复,或用 [core] 组的 rollbackmigrationsappliedafter 命令处理迁移点。升级后核对 flagsmith_build_info 指标的 version 标签与预期一致。
九、常见问题(运维向排障实录)
Q1:python manage.py bootstrap 执行成功但什么都没创建。
实测行为:exit 0、无输出、库无变化。原因有二(实测均验证):未设 ALLOW_ADMIN_INITIATION_VIA_CLI=true;或库里已有任意用户/组织/项目——初始化判定按「存在记录即跳过」实现(FFAdminUser.objects.exists()),bootstrap 仅适用于空库。解法:空库场景先设开关再跑;非空库用 createsuperuser + REST API。
Q2:createsuperuser --noinput 报 CommandError 缺参。
实测报错:
CommandError: You must use --noinput or --username and --email with --noinput, --first_name and --last_name and --sign_up_type with --noinput.
解法:v2.287.0 用户模型要求全名与注册类型,完整形态见 3.4;密码经 DJANGO_SUPERUSER_PASSWORD 注入。注意密码过弱会命中「too common」校验,用 Q1w2e3r4@2026 这类强口令。
Q3:登录接口多次失败后被锁。
内置 django-axes 防爆破(阈值 AXES_FAILURE_LIMIT 默认 10)。解锁命令(实测可用 [axes] 命令组):
docker exec flagsmith-2.287.0-api sh -c "cd /app && python manage.py axes_reset --username admin@flagsmith.local"
(另有 axes_reset_ip/axes_reset_logs 等变体,见 3.1 清单。)
Q4:任务积压/异步任务长时间不执行。
排查三步(实测路径):确认 TASK_RUN_METHOD=TASK_PROCESSOR 时 task-processor 服务在运行(docker compose ps);经 3.6 的 ORM 查询看 Task 表状态分布;看 docker compose logs task-processor 是否有周期性空转(空闲时每分钟轮询一轮,日志周期性输出属正常)。若误把 TASK_RUN_METHOD 设为 TASK_PROCESSOR 却没起该服务,任务会永久积压——退回默认 SEPARATE_THREAD 或补服务。
Q5:切换开关后部分 SDK 读到旧值。
环境级切换经 PATCH featurestates 即时生效(本篇 4.3→5.1 实测闭环);读到旧值的典型原因是 SDK 本地求值缓存——本地求值模式按轮询/版本号刷新环境文档(featurestate 的 version 自增即为此设计),核对 SDK 轮询周期配置;或改用远程求值模式验证平台侧状态。
Q6:/admin/ 脚本化登录 403。
实测报错 403 Forbidden — CSRF cookie not set.:Django Admin 的 CSRF/会话校验不接受裸 curl 模拟。解法:浏览器登录;脚本验证用 manage.py shell 内 django.test.Client().login(...)(实测 login ok: True);管理面操作统一走 Token 认证的 REST API(本篇第四章)。
Q7:环境列表查不到刚建的项目环境。
v2.287.0 实测行为:项目创建不自动建环境(GET /api/v1/environments/?project=1 短暂 count: 0)。解法:显式 POST /api/v1/environments/(4.1),创建即返回 SDK 密钥。
Q8:服务端密钥在哪查/怎么建。
服务端密钥(ser. 前缀)无管理 API 端点,官方通道为 ORM:3.6 的 EnvironmentAPIKey.objects.create(...) 实测可建;建好后用 5.3 端点验证连通。密钥泄露时同表删除记录即可吊销。
十、参考链接
- 官方 Docker 部署文档(含 createsuperuser 与访问入口):https://docs.flagsmith.com/deployment/docker
- Django Admin 管理文档(超管与权限):https://docs.flagsmith.com/deployment/configuration/django-admin
- API 管理面端点参考(REST API 文档):https://docs.flagsmith.com/api-reference
- 无控制台初始化端点说明:https://docs.flagsmith.com/deployment/hosting/locally-api
- 容量与扩缩指引:https://docs.flagsmith.com/deployment/configuration/sizing-and-scaling
- Prometheus 环境变量(metrics 开关与桶配置):https://docs.flagsmith.com/deployment/hosting/locally-api
- 本系列姊妹篇:《Flagsmith 介绍与选型指南》、《Flagsmith Docker Compose 部署实战》、《Flagsmith 配置参数详解》