Flipt Docker Compose 部署实战
基于 Flipt v2.14.1 的 Docker Compose 全流程实测:单容器起栈、声明式 features.yaml 与 Git 远端双向同步(GitOps 热加载)、静态 token 认证加固、文件即状态的备份策略,沉淀数据目录权限、file:// remote 失效等真实排障案例,并溯源官方 Kubernetes/Helm 部署形态。
Flipt Docker Compose 部署实战
本文基于 Flipt v2.14.1(2026-10-23 发布,当前 v2 主线稳定版)实测撰写。Flipt v2 是 Go 单二进制架构、以 Git 仓库为状态源,Docker Compose 部署形态比传统"应用 + 数据库"栈简单得多——只需一个官方镜像容器,再配好数据目录与配置文件即可。本文覆盖三个递进主题:
- 单容器快速起栈(本地 Git 存储后端);
- 声明式
features.yaml的挂载与 Git 远端同步(GitOps 工作流); - 认证加固、数据备份与故障排查实录;最后附官方 Kubernetes 部署形态溯源。
实验环境约定:真实服务器视角,Compose 项目名 flipt-v2.14.1-stack,HTTP 端口 8135、gRPC 端口 8136(生产可换回官方默认 8080/9000)。
一、部署前置认知:Flipt v2 的存储模型
动手之前必须先理解 v2 与 v1 的根本差异,否则部署思路会完全跑偏:
| 事项 | Flipt v1 | Flipt v2(本文版本) |
|---|---|---|
| 状态存储 | PostgreSQL/SQLite/MySQL | Git 仓库(本地目录或内存 + 远端 Git) |
| Compose 形态 | flipt + database 两容器 | 单容器即可 |
| 开关定义来源 | UI/API 直写数据库 | 声明式 features.yaml,UI/API 修改自动提交回 Git |
| 持久化关键 | 备份数据库 | 备份整个 Git 仓库目录(或配置远端) |
来源:docs.flipt.io/v2/installation(查询日期 2026-10-28)。v2 官方 Docker 示例为
docker run -d -p 8080:8080 -p 9000:9000 -v $HOME/flipt:/var/opt/flipt docker.flipt.io/flipt/flipt:v2,数据目录挂载点为/var/opt/flipt。
三个高频踩坑点先划重点(后文均有实测还原):
- 数据目录属主:容器以非 root 用户(uid/gid 10001)运行,bind mount 的宿主目录属主不对会直接启动失败;
remote不支持file://协议:Git 远端要配成git:///https:///ssh://,file://会被静默忽略;- 推送失败的写操作不生效:Flipt 的"提交 + 推送"是事务性的,远端不可写时 API 创建开关会直接报错。
二、单容器快速起栈(本地 Git 存储后端)
2.1 目录结构
在服务器上创建部署目录:
mkdir -p /opt/flipt/{data,config}
cd /opt/flipt
最终结构:
/opt/flipt
├── compose.yml # 编排定义
├── config.yml # Flipt 服务器配置
└── data/ # 持久化数据(Flipt 会在其下初始化 Git 仓库)
2.2 编排文件 compose.yml
name: flipt-v2.14.1-stack
services:
flipt:
image: flipt/flipt:v2.14.1
container_name: flipt-v2.14.1-server
restart: unless-stopped
ports:
- "8135:8080" # HTTP:REST API + Web UI
- "8136:9000" # gRPC:评估与管理 API
volumes:
- ./data:/var/opt/flipt
- ./config.yml:/etc/flipt/config/default.yml:ro
environment:
TZ: Asia/Shanghai
networks:
default:
name: flipt-net
driver: bridge
ipam:
config:
- subnet: 10.89.57.0/24
要点说明:
- 镜像固定到
v2.14.1版本标签,避免v2浮动标签在升级时行为漂移; - 配置文件挂载到镜像默认读取路径
/etc/flipt/config/default.yml(Flipt 的配置查找顺序:--config标志 > 用户配置目录 >/etc/flipt/config/default.yml); - 官方镜像为多架构(x86-64/ARM64),Docker Engine 需 20.10+。
2.3 最小可用配置 config.yml
log:
level: INFO
encoding: console
meta:
check_for_updates: false
telemetry_enabled: false
server:
http_port: 8080
grpc_port: 9000
storage:
default:
backend:
type: local
path: /var/opt/flipt/repo
environments:
default:
name: default
default: true
storage: default
directory: default
storage.default.backend.type: local:状态存本地 Git 仓库(目录/var/opt/flipt/repo);environments.default.directory: default:环境default映射到仓库中的default/目录,多个环境可共享同一存储的不同目录;meta两项关闭外联检查与遥测,内网部署建议保持关闭。
2.4 启动与验证
先修复数据目录属主(容器内运行用户为 uid 10001):
chown -R 100:1000 /opt/flipt/data
实测注记:实验宿主上以
100:1000放行(uid 10001 用户可写即可);若属主为 root 且无写权限,容器日志会直接报 permission denied,服务无法初始化 Git 仓库。
启动:
docker compose up -d
查看启动日志:
$ docker logs flipt-v2.14.1-server
_________ __
/ ____/ (_)___ / /_
/ /_ / / / __ \/ __/
/ __/ / / / /_/ / /_
/_/ /_/_/ .___/\__/
/_/
Version: 2.14.1
Commit: 3f59af5a2755d17c4e65b9a341d0c184135621fa
Build Date: 2026-10-23T02:48:17Z
Go Version: go1.27.3
OS/Arch: linux/amd64
...
INFO environment configured successfully {"key": "default", "hash": "8637d52d0fa8453c1e07a87d01895cd77eae986e"}
INFO grpc server listening on [::]:9000
INFO listening on [::]:8080...
INFO starting internal http server on localhost:8081
WARN no license key provided; additional features are disabled.
INFO flipt started
(日志为实测回显摘录,hash 每次初始化不同;no license key 为未装 Pro 许可的正常提示,不影响社区功能。)
验证健康检查与数据目录初始化:
$ curl -s http://localhost:8135/health
{"status":"ok"}
$ curl -s 'http://localhost:8135/health?service=evaluation'
{"status":"ok","service":"evaluation"}
$ curl -s 'http://localhost:8135/health?service=management'
{"status":"ok","service":"management"}
$ ls /opt/flipt/data/repo
config HEAD objects README.md refs
此时 Flipt 已在 data/repo 下自动初始化一个裸 Git 仓库,并写入两个文件:README.md(声明该仓库是 Flipt 状态的唯一可信源,请勿直接修改)与初始 features.yaml。浏览器访问 http://<服务器IP>:8135 即可进入 Web 控制台(UI <title> 为 Flipt)。
重要:此形态下官方 README 会明确警告——未配置远端 remote 时,所有变更只存在于本地目录,"storage directory 被删除则数据全部丢失"。单机试水可以接受,生产必须接入 2.3 节的 Git 远端。
三、声明式 feature 文件与 Git 远端同步
3.1 features.yaml 是什么、长什么样
Flipt v2 通过管理 API(或 UI)创建的每一个开关/分群/规则,都会转成对仓库中 features.yaml 的提交。文件按 <环境目录>/<命名空间>/features.yaml 组织,本例路径为 default/default/features.yaml。以下为本实验最终形态的完整实测文件(schema version 1.6):
version: "1.6"
environments:
default:
namespaces:
default:
flags:
- key: checkout-dark-mode
name: Checkout Dark Mode
description: 结算页暗色主题灰度开关
enabled: false
type: BOOLEAN_FLAG_TYPE
rollouts:
- type: SEGMENT_ROLLOUT_TYPE
description: 内测用户直接开启
segment:
value: true
segments:
- beta-users
segmentOperator: OR_SEGMENT_OPERATOR
- type: THRESHOLD_ROLLOUT_TYPE
description: 按实体 20% 灰度
threshold:
percentage: 50
value: true
- key: checkout-button-color
name: Checkout Button Color
description: 结算按钮颜色实验
enabled: true
type: VARIANT_FLAG_TYPE
defaultVariant: blue
variants:
- key: blue
name: Blue
- key: red
name: Red
rules:
- segments:
- beta-users
segmentOperator: OR_SEGMENT_OPERATOR
distributions:
- variant: blue
rollout: 30
- variant: red
rollout: 70
segments:
- key: beta-users
name: Beta Users
description: 内测用户群
match_type: ALL_MATCH_TYPE
constraints:
- type: STRING_COMPARISON_TYPE
property: plan
operator: eq
value: beta
这份文件同时展示了 v2 的三类核心对象:
- 布尔开关
checkout-dark-mode:带两段 rollout——内测分群(beta-users)直接放行,其余流量按 50% 阈值灰度; - 变体开关
checkout-button-color:内测分群内 blue/red 按 30/70 分发,分群外命中defaultVariant: blue; - 分群
beta-users:约束plan == beta。
3.2 配置 Git 远端(GitOps 工作流入口)
给存储后端加上 remote,让 Flipt 双向同步:API/UI 修改自动推送上去,仓库侧提交自动拉取下来。
storage:
default:
backend:
type: local
path: /var/opt/flipt/repo
remote: git://10.89.57.1/flags.git # 远端仓库地址
branch: main
poll_interval: 5s # 轮询周期,生产常用 30s
fetch_policy: lenient # 首次启动远端不可达时不阻塞
官方文档示例使用 GitHub + Personal Access Token 的形态(查询日期 2026-10-28,docs.flipt.io/v2/guides/operations/environments/git-sync):
credentials:
github:
type: access_token
access_token: ${env:GITHUB_TOKEN} # 环境变量注入,避免明文
storage:
github:
remote: "https://github.com/<your-username>/<your-repo>.git"
branch: "main"
poll_interval: "30s"
credentials: "github" # 引用上面的凭据
backend:
type: local
path: "/path/to/local/clone"
注意 v2 的环境变量替换语法是 ${env:VAR}(v1 的 ${VAR} 已不支持)。
3.3 实测:API 写入 → 自动提交推送
先在服务器上起一个可写的 Git 服务(实验用 git daemon --enable=receive-pack;生产直接用 GitHub/GitLab)。创建一个布尔开关:
$ curl -s -H 'Content-Type: application/json' \
-X POST http://localhost:8135/api/v2/environments/default/namespaces/default/resources \
-d '{"key":"search-ranker-v2","payload":{"@type":"flipt.core.Flag","key":"search-ranker-v2","name":"Search Ranker V2","description":"新排序服务灰度","type":"BOOLEAN_FLAG_TYPE","enabled":false}}'
{"revision":"66c29e6..."}
$ git --git-dir=/srv/git/flags.git log --oneline main | head -3
66c29e6 create flag default/search-ranker-v2
9a8770c rollout checkout-dark-mode threshold 20 -> 50
5cb9542 update flag default/checkout-dark-mode
服务端日志同步记录了完整链路(DEBUG 级别实测回显):
DEBUG starting update and push operation {"remoteConfig": {"Name":"origin","URLs":["git://10.89.57.1/flags.git"]}}
DEBUG creating commit {"message": "create flag default/search-ranker-v2"}
DEBUG commit created successfully {"hash": "0351ed3cc553fd91a0ba2aeb734bf51d1e4489eb"}
DEBUG pushing to remote {"refSpec": "refs/heads/main:refs/heads/main"}
3.4 实测:仓库改 YAML → 轮询热加载
反向链路是 GitOps 的核心价值。在外部克隆仓库,直接修改 default/default/features.yaml,把灰度阈值从 20% 调到 50%:
$ sed -i 's/percentage: 20/percentage: 50/' default/default/features.yaml
$ git add -A && git commit -m "rollout checkout-dark-mode threshold 20 -> 50"
$ git push origin main
Flipt 在下一个轮询周期(本实验 poll_interval: 5s)完成 fetch 并重建评估快照,日志实测回显:
DEBUG preparing refspec for fetch {"refspec": "+refs/heads/main:refs/remotes/origin/main"}
DEBUG fetch successful {"git_storage_type": "filesystem", "git_storage_path": "/var/opt/flipt/repo"}
DEBUG view {"branch": "main", "hash": "9a8770c3941e54e48b0e391fd303ec821d5e0ca2"}
无需任何重启,评估结果随即翻转(实测将阈值调大后,原本命中 20%~50% 分桶灰度的实体如 u13、u17、u18、u21 的 enabled 由 false 变为 true)。日志中还能看到另一条 refspec +refs/heads/flipt/default/*——这是 v2 分支环境(Branch Environments)特性的取回规则。
这一"PR 合并即生效"的链路,就是 Flipt 团队把特性开关发布与代码评审流程整合的落点:CI 中配合 flipt validate(见《Flipt 常用命令与运维实战(核心篇)》)即可实现开关变更的流水线门禁。
四、认证加固:让管理面不再裸奔
默认配置下 API 与 UI 完全开放,生产必须开启认证。实测配置:
authentication:
required: true
session:
token_lifetime: 24h
exclude:
evaluation: true # 评估接口保持匿名(应用侧高频调用)
methods:
token:
enabled: true
storage:
tokens:
docs_ci:
credential: "ft_docs_ci_1a2b3c4d5e6f" # 生产用强随机值
metadata:
name: "CI Pipeline Token"
实测验证(重启后):
# 评估接口:豁免认证,匿名可访问
$ curl -s -o /dev/null -w '%{http_code}\n' -H 'Content-Type: application/json' \
http://localhost:8135/evaluate/v1/boolean \
-d '{"flagKey":"checkout-dark-mode","entityId":"u13","context":{"plan":"pro"}}'
200
# 管理 API:无 token / 错 token 均拒绝
$ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8135/api/v2/environments
401
$ curl -s -o /dev/null -w '%{http_code}\n' -H 'Authorization: Bearer wrong-token' http://localhost:8135/api/v2/environments
401
# 管理 API:携带正确静态 token
$ curl -s -H 'Authorization: Bearer ft_docs_ci_1a2b3c4d5e6f' http://localhost:8135/api/v2/environments
{"environments":[{"key":"default","name":"default","default":true,"configuration":{"ref":"main","directory":"default","remote":"git://10.89.57.1/flags.git"}}]}
两点务必记住:
- 静态 token 的嵌套层级是
methods.token.storage.tokens.<id>.credential。官方文档《配置总览》的参数表写成authentication.methods.token.tokens,实测该写法不生效(服务照常启动,但 token 无法认证,静默 401)——以《认证》文档与实测为准; token方法不是 session-compatible 的:它只能供 API 客户端使用,UI 登录需要 OIDC 等 session 方法(启用authentication.required且无 session 方法时,浏览器控制台无法登录)。
凭据建议改用 secret 引用(如 ${secret:file:ci-token} 映射 /etc/flipt/secrets/ci-token),避免明文落盘。
五、备份与恢复:文件即状态
v2 的备份策略比 v1 简单得多——Git 仓库目录即全部状态:
| 备份对象 | 方式 |
|---|---|
| 标准形态(配置了 remote) | 状态在远端 Git 服务器(GitHub/GitLab/自建),天然多副本;本地目录可随时重建 |
| 纯本地形态(无 remote) | git bundle create /backup/flipt-$(date +%F).bundle --all 或直接 tar data/repo,务必加定时任务 |
| 服务器配置 | config.yml 与 Compose 文件纳入运维配置库 |
| 会话数据(可选 Redis) | 仅影响登录会话,丢失可重新认证 |
恢复演练思路:新服务器装好 Docker → 恢复 config.yml → 若无 remote,则将备份仓库解包回 data/repo → docker compose up -d。配置了 remote 的实例,Flipt 启动后自动从远端 fetch 重建快照,无需额外导入。
六、排障实录沉淀
以下是本实验过程中真实踩到并复现的坑,按"现象 → 原因 → 解法"沉淀:
6.1 数据目录权限导致启动失败
- 现象:
docker compose up后服务反复初始化失败,日志报 Git 仓库无法创建/写入(permission denied)。 - 原因:镜像内运行用户为 uid/gid 10001,宿主 bind mount 目录属主为 root,容器用户无写权限。
- 解法:
chown -R 100:1000 ./data(或至少保证 uid 10001 可写)后再启动。
6.2 remote 配 file:// 静默失效
- 现象:配置
remote: file:///var/opt/flipt/upstream.git后,外部仓库的提交永远不会被拉取;日志中environment configured successfully {"remoteConfig": null}——remote 压根没被解析。 - 原因:v2 的 remote 仅支持真实 Git 协议(
https://、ssh://、git://),file://不在支持之列,且不报错、静默忽略。 - 解法:改用
git://(实验)/https://+ token(生产);确认日志出现"remoteConfig": {"Name":"origin","URLs":[...]}才算配置成功。
6.3 git-daemon 默认只读,推送被拒
- 现象:API 创建开关返回错误:
{"code":13,"message":"resource type \"flipt.core.Flag\": access denied or repository not exported: /flags.git"}。 - 原因:自建
git daemon默认关闭 receive-pack(只读服务),Flipt 的 push 被拒。 - 解法:git-daemon 加
--enable=receive-pack(仅实验环境;生产用带认证的 HTTPS/SSH 远端)。另注意:推送失败时写操作整体回滚——commit 已落本地但 push 失败,API 直接报错,随后本地也被远端状态覆盖回退,开关"创建失败"。这验证了 v2 写路径的"提交 + 推送"事务性,也提醒我们:远端仓库的可用性直接决定管理面的可用性。
6.4 静态 token 嵌套层级写错 → 静默 401
- 现象:按《配置总览》参数表把 token 写在
methods.token.tokens下,服务正常启动,但携带 token 的请求仍返回 401,日志无显式报错。 - 原因:实际生效的层级是
methods.token.storage.tokens.<id>.credential(以《认证》文档为准);错误层级的字段被静默忽略。 - 解法:调整嵌套层级;验证标准是带
Authorization: Bearer <token>访问管理 API 返回 200。
6.5 未配 remote 的本地存储形态
- 现象:仓库
README.md中出现官方警告:"You have configured Flipt with a local storage backend without a remote. In this mode all changes will be lost if the storage directory is deleted!" - 原因/解法:非故障,是官方对纯本地形态的风险声明。生产部署务必配置 remote,把状态副本放到 Git 服务器上。
七、Kubernetes 部署形态(官方文档溯源)
本节为联网溯源内容(来源:docs.flipt.io/v2/installation 与 docs.flipt.io/v2/guides/operations/deployment/deploy-to-kubernetes,查询日期 2026-10-28),供 K1 批次集群实测前参考;文内命令未在本文实验环境执行。
7.1 官方 Helm Chart
Flipt v2 提供官方 Helm 仓库与独立 Chart(chart 名为 flipt-v2,与 v1 的 flipt chart 分离,确保 v2 配置兼容性):
# 添加官方 Helm 仓库
helm repo add flipt https://helm.flipt.io
helm repo update
# 安装 Flipt v2
helm install my-flipt-v2 flipt/flipt-v2
# 或以自定义 values 安装
helm install my-flipt-v2 flipt/flipt-v2 -f values.yaml
官方文档列出该 Chart 的关键特性:
- Git-native storage:开箱即用,无需外部数据库;
- Environment support:可从不同 Git 分支部署多环境;
- Flexible configuration:支持全部 v2 配置项;
- Production ready:内置安全、可观测性与扩展选项。
7.2 values.yaml 配置示例(官方文档形态)
flipt:
config:
log:
level: INFO
encoding: json
server:
grpc_port: 9000
http_port: 8080
cors:
enabled: true
allowed_origins:
- "http://localhost:3000"
- "https://your-frontend-domain.com"
ui:
default_theme: dark
topbar:
color: "#7C3AED"
meta:
check_for_updates: false
telemetry_enabled: false
metrics:
enabled: true
exporter: prometheus
storage:
default:
backend:
type: memory
官方部署指南(Deploy Flipt v2 to Kubernetes)演示了 Kind 本地集群 + Helm 安装 + kubectl port-forward 验证的完整流程,并配套《Kubernetes Troubleshooting》排障文档。生产接入 Git 存储时,结合《Git Sync with GitHub》指南为 Chart 配置 credentials(PAT 走 ${env:GITHUB_TOKEN} 注入)。
7.3 k8s 形态的认证与探针要点(溯源)
- 认证:Flipt 支持 Kubernetes 服务账号 Token 认证方法——同集群内部署的应用可自动获得认证身份,无需管理静态 token,这是 k8s 场景相对裸机的独特优势;
- 健康探针:
/health支持?service=evaluation与?service=management查询参数(本文单机形态已实测),gRPC 探针走 9000 端口,可直接映射为 liveness/readiness probe; - 资源形态:单 Pod 即可运行(Git 存储在 Pod 卷或远端),横向扩容时注意会话存储从 memory 切换为 Redis。
八、部署形态小结
| 形态 | 适用 | 关键配置 |
|---|---|---|
| 单容器 + 本地存储 | 个人试水、PoC | 仅 storage.backend + 数据目录权限 |
| 单容器 + Git 远端 | 生产推荐(单机) | remote + poll_interval + credentials + 认证加固 |
| Compose + 可写 Git 服务 | 自建 GitOps 闭环 | git-daemon --enable=receive-pack 或 Gitea/GitLab |
| Kubernetes + Helm | 集群化生产 | Chart flipt-v2,values 注入 v2 配置,k8s SA 认证 |
延伸阅读
参考资料(查询日期 2026-10-28):
- Flipt v2 安装文档:https://docs.flipt.io/v2/installation
- Git Sync with GitHub 指南:https://docs.flipt.io/v2/guides/operations/environments/git-sync
- Deploy to Kubernetes 指南:https://docs.flipt.io/v2/guides/operations/deployment/deploy-to-kubernetes
- Flipt v2 认证配置:https://docs.flipt.io/v2/configuration/authentication
- Docker 镜像:https://hub.docker.com/r/flipt/flipt/tags