本文说明本项目如何用 Infisical 管理密钥/覆盖配置,并与现有 Docker Compose 工作流结合。目标是:.env 负责编排与非密钥默认值,.env.local 由 Infisical 在启动时导出,注入到 WordPress 容器。Infisical 的 Project、Environment 与登录连接信息一律通过环境变量提供。
相关文件:
start:启动前通过infisical/cli登录并导出.env.localdocker-compose.yml:wordpress_frankenphp同时加载.env与.env.local.env.default:可提交的本地默认环境变量模板.env.infisical.example:Infisical 连接参数模板(可提交);复制为.env.infisical后填写真实值
自托管地址示例:https://secret-manager.it-consultis.net。
Infisical 环境变量
| 环境变量 | 用途 |
|---|---|
INFISICAL_DOMAIN | 自托管或 Cloud API 地址 |
INFISICAL_ORGANIZATION_ID | 登录时的 Organization ID |
INFISICAL_PROJECT_ID | Infisical Project ID,export / run 时传给 --projectId |
INFISICAL_ENV | Infisical Environment slug,如 local、production-us |
INFISICAL_EMAIL / INFISICAL_PASSWORD | 本机个人登录(勿提交) |
INFISICAL_CLIENT_ID / INFISICAL_CLIENT_SECRET | Machine Identity(CI / 服务器推荐) |
变量分层
| 类型 | 示例 | 存放位置 |
|---|---|---|
| Compose 编排 | COMPOSE_PROJECT_NAME、WORDPRESS_HTTP_PORT、VERSION、CONTAINER_REGISTRY、DOCKER_NETWORK_* | .env(由 .env.default 生成) |
| 环境差异配置 | ENVIRONMENT、WORDPRESS_SITE_URL、DB host | 可放 .env,逐步迁移到 Infisical |
| 密钥 / 敏感覆盖 | WORDPRESS_*_KEY、WORDPRESS_*_SALT、JWT_AUTH_SECRET_KEY、DB 密码、管理员密码等 | Infisical → 导出为 .env.local |
| Infisical 连接与认证 | Domain、Organization ID、Project ID、INFISICAL_ENV、登录凭据 | 本机 .env.infisical(勿提交) |
不要把 Infisical 个人邮箱/密码、Machine Identity Client Secret 写进 start 或任何会提交的文件。
文件约定
.env # 本地编排与默认配置(gitignore)
.env.default # 可提交模板;首次启动由 start 复制为 .env
.env.local # Infisical export 产物(gitignore)
.env.infisical # Infisical 连接/认证(gitignore)
.env.infisical.example # 可提交模板,不含真实密码
请确保 .gitignore 至少包含:
.env
.env.local
.env.infisical
启动流程
./start 中的逻辑顺序:
- 若无
.env,从.env.default复制生成。 - 从
.env.infisical(或已导出的环境变量)读取 Infisical 连接信息。 - 使用
infisical/cli镜像登录,拿到短期INFISICAL_TOKEN。 infisical export --projectId=... --env=...写出.env.local。source .env,创建网络并执行./docker-compose up。
docker-compose.yml 中 WordPress 服务示例:
services:
wordpress_frankenphp:
env_file:
- path: ./.env
required: true
- path: ./.env.local
required: false
- 后加载的
.env.local会覆盖.env中的同名变量(仅对 serviceenv_file合并生效)。 required: false:导出失败或本地未配置 Infisical 时,仍可仅靠.env启动(视业务是否依赖密钥而定)。
本机认证文件示例
复制模板并填写:
cp .env.infisical.example .env.infisical
.env.infisical 内容示例:
INFISICAL_DOMAIN=https://secret-manager.it-consultis.net
INFISICAL_ORGANIZATION_ID=<organization-id>
INFISICAL_PROJECT_ID=<project-id>
INFISICAL_ENV=local
# 开发机可用个人登录(仅本机)
INFISICAL_EMAIL=<your-email>
INFISICAL_PASSWORD=<your-password>
# 或改用 Machine Identity(推荐用于 CI / 共享服务器)
# INFISICAL_CLIENT_ID=<client-id>
# INFISICAL_CLIENT_SECRET=<client-secret>
start 中建议先加载该文件,再调用 CLI,例如:
if [ -f .env.infisical ]; then
# shellcheck disable=SC1091
source .env.infisical
fi
: "${INFISICAL_DOMAIN:?INFISICAL_DOMAIN is required}"
: "${INFISICAL_PROJECT_ID:?INFISICAL_PROJECT_ID is required}"
: "${INFISICAL_ORGANIZATION_ID:?INFISICAL_ORGANIZATION_ID is required}"
export INFISICAL_TOKEN=$(docker run --rm infisical/cli login \
--domain "${INFISICAL_DOMAIN}" \
--email "${INFISICAL_EMAIL}" \
--password "${INFISICAL_PASSWORD}" \
--organization-id "${INFISICAL_ORGANIZATION_ID}" \
--plain \
--silent)
docker run --rm infisical/cli export \
--domain "${INFISICAL_DOMAIN}" \
--env="${INFISICAL_ENV:-local}" \
--projectId="${INFISICAL_PROJECT_ID}" \
--token="${INFISICAL_TOKEN}" > .env.local
多环境时通过 INFISICAL_ENV(也可映射自 ENVIRONMENT)选择 Infisical environment,例如 local、develop-us、production-eu。
Machine Identity(CI / 服务器)
export INFISICAL_TOKEN=$(docker run --rm infisical/cli login \
--domain "${INFISICAL_DOMAIN}" \
--method=universal-auth \
--client-id "${INFISICAL_CLIENT_ID}" \
--client-secret "${INFISICAL_CLIENT_SECRET}" \
--plain \
--silent)
凭据放在部署平台或服务器私密配置中,不要写入 Git。
Compose 插值与覆盖顺序(重要)
Docker Compose 里有两套「环境变量」机制,容易混淆:
- 项目级
.env(或--env-file):用于 compose 文件里的${VAR}插值(镜像名、端口、网络名等)。 - service
env_file:注入到容器进程环境。
同时注意:若服务还写了 environment:,其值会覆盖 env_file 中的同名键;而 ${WORDPRESS_DB_PASSWORD:-root} 这类插值只读项目级 .env,不会自动读 .env.local。
因此:
- 仅放在
.env.local的密钥,不要再在environment:里用${...}写一遍,否则会被项目.env的默认值盖掉。 - Compose 编排所需变量继续放在
.env。 - 密钥与运行时覆盖放在 Infisical →
.env.local,并尽量通过env_file注入,而不是重复出现在environment:。
推荐的容器侧优先级:
.env(默认) → .env.local(Infisical 覆盖) → environment:(仅保留非密钥、确实需要写死的项)
Infisical 侧配置建议
- 在 Infisical 中为仓库创建 Project,把 Project ID 写入本机
INFISICAL_PROJECT_ID。 - 按部署环境建立 Environment(建议与现有
ENVIRONMENT对齐,如local、uat-us、production-eu),对应值写入INFISICAL_ENV。 - 将密钥与需要按环境覆盖的变量导入对应 Environment。
- 本地开发:个人账号或开发用 Machine Identity,只读
local。 - CI / 各区域服务器:独立 Machine Identity,最小权限,只读对应 Environment。
原先 deploy/scripts/modify-dot-env-*.sh 中与密钥、区域差异相关的 sed 修改,可逐步改为「按环境 infisical export」,减少在磁盘上长期维护多份手工改过的 .env。
日常使用
# 1. 准备 .env(首次)
cp .env.default .env # 或由 ./start 自动复制
# 2. 准备 Infisical 连接参数(首次)
cp .env.infisical.example .env.infisical
# 编辑 .env.infisical,填写 Project ID、Organization ID、登录凭据等
# 3. 在 Infisical 对应 environment 中维护密钥
# 4. 启动(会刷新 .env.local 并 up 容器)
./start -d
验证容器是否拿到 Infisical 变量:
./docker-compose exec wordpress_frankenphp env | grep -E 'INFISICAL_TEST|WP_REDIS_PREFIX|JWT_AUTH'
安全注意
- 不要将 Infisical 密码、Client Secret、完整
.env.local提交到 Git 或打进镜像。 - 若凭据曾写入
start或聊天记录,应立即在 Infisical / 账号侧轮换密码或撤销 Client Secret。 INFISICAL_TOKEN为短期令牌,仅用于当次 export;不要持久化进镜像层。- 生产环境优先 Machine Identity,避免个人账号密码出现在服务器脚本中。
后续可选演进
当前方案(主机侧 export → .env.local → env_file)改动小,适合本地与现有部署脚本平滑过渡。
若后续希望减少服务器磁盘上的密钥落盘,可再演进为:
- 镜像内安装 Infisical CLI;
- 容器
CMD使用infisical run --projectId=... --env=... -- ... /start; - Compose 仅传入
INFISICAL_TOKEN(及自托管时的INFISICAL_DOMAIN)。
编排用薄 .env 仍需保留,因为 Compose 解析 ${...} 发生在容器启动拉密之前。