Flipt Docker Compose 部署实战

基于 Flipt v2.14.1 的 Docker Compose 全流程实测:单容器起栈、声明式 features.yaml 与 Git 远端双向同步(GitOps 热加载)、静态 token 认证加固、文件即状态的备份策略,沉淀数据目录权限、file:// remote 失效等真实排障案例,并溯源官方 Kubernetes/Helm 部署形态。

FliptDockerDocker Compose运维自动化2026/10/28

Flipt Docker Compose 部署实战

本文基于 Flipt v2.14.1(2026-10-23 发布,当前 v2 主线稳定版)实测撰写。Flipt v2 是 Go 单二进制架构、以 Git 仓库为状态源,Docker Compose 部署形态比传统"应用 + 数据库"栈简单得多——只需一个官方镜像容器,再配好数据目录与配置文件即可。本文覆盖三个递进主题:

  1. 单容器快速起栈(本地 Git 存储后端);
  2. 声明式 features.yaml 的挂载与 Git 远端同步(GitOps 工作流);
  3. 认证加固、数据备份与故障排查实录;最后附官方 Kubernetes 部署形态溯源。

实验环境约定:真实服务器视角,Compose 项目名 flipt-v2.14.1-stack,HTTP 端口 8135、gRPC 端口 8136(生产可换回官方默认 8080/9000)。

一、部署前置认知:Flipt v2 的存储模型

动手之前必须先理解 v2 与 v1 的根本差异,否则部署思路会完全跑偏:

事项Flipt v1Flipt v2(本文版本)
状态存储PostgreSQL/SQLite/MySQLGit 仓库(本地目录或内存 + 远端 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。

三个高频踩坑点先划重点(后文均有实测还原):

  1. 数据目录属主:容器以非 root 用户(uid/gid 10001)运行,bind mount 的宿主目录属主不对会直接启动失败;
  2. remote 不支持 file:// 协议:Git 远端要配成 git:// / https:// / ssh://,file:// 会被静默忽略;
  3. 推送失败的写操作不生效: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"}}]}

两点务必记住:

  1. 静态 token 的嵌套层级是 methods.token.storage.tokens.<id>.credential。官方文档《配置总览》的参数表写成 authentication.methods.token.tokens,实测该写法不生效(服务照常启动,但 token 无法认证,静默 401)——以《认证》文档与实测为准;
  2. 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):

  1. Flipt v2 安装文档:https://docs.flipt.io/v2/installation
  2. Git Sync with GitHub 指南:https://docs.flipt.io/v2/guides/operations/environments/git-sync
  3. Deploy to Kubernetes 指南:https://docs.flipt.io/v2/guides/operations/deployment/deploy-to-kubernetes
  4. Flipt v2 认证配置:https://docs.flipt.io/v2/configuration/authentication
  5. Docker 镜像:https://hub.docker.com/r/flipt/flipt/tags