Skip to content

Commit 31e0d6b

Browse files
committed
docs: add start-container config isolation design
1 parent 3744a68 commit 31e0d6b

2 files changed

Lines changed: 219 additions & 3 deletions

File tree

config/dockerfiles/compose/docker-compose.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,14 @@ services:
285285
TZ: "Asia/Shanghai"
286286
ports: ["5432:5432"]
287287
volumes:
288-
# 官方文档建议将数据持久化到 /var/lib/postgresql 目录
289-
- "${DATA_PATH}/paradedb:/var/lib/postgresql"
288+
# ParadeDB/PG17 默认使用 PGDATA=/var/lib/postgresql/data,直接挂载该目录可避免父目录嵌套挂载生成匿名 volume
289+
- "${DATA_PATH}/paradedb/data:/var/lib/postgresql/data"
290290
healthcheck:
291-
test: ["CMD-SHELL", "pg_isready -U ${DEFAULT_USER:-postgres} -d ${POSTGRES_DB:-paradedb}"]
291+
test:
292+
[
293+
"CMD-SHELL",
294+
"pg_isready -U ${DEFAULT_USER:-postgres} -d ${POSTGRES_DB:-paradedb}",
295+
]
292296
interval: 10s
293297
timeout: 5s
294298
retries: 3
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
# Start-Container Config Isolation Design
2+
3+
## Context
4+
5+
`scripts/pwsh/devops/start-container.ps1` 目前通过全局环境变量驱动 `docker compose`,并在脚本运行过程中直接把 `.env``.env.local``-Env` 与解析后的默认值写入当前 PowerShell 进程环境。这个模型对大多数服务是方便的,但会带来两个问题:
6+
7+
1. 同一 PowerShell 会话内,不同服务之间会通过进程环境互相污染。例如先启动 `minio``rustfs` 后残留的 `DEFAULT_USER=root`,会影响后续 `postgre``paradedb` 的解析结果。
8+
2. 脚本把“读取配置来源”和“应用环境变量”耦合在一起,导致后续脚本难以复用,也让排查最终值来源变得困难。
9+
10+
最近一次 `postgre` / `paradedb` 默认用户修复已经把服务级默认值收口到 `postgres`,但当前优先级仍允许通用 `DEFAULT_*` 被历史会话状态覆盖。这说明问题的根因不是默认值函数本身,而是配置来源与环境隔离模型。
11+
12+
## Goals
13+
14+
- 修复 `start-container.ps1` 的环境污染问题,避免同一会话内前一次调用影响后一次调用。
15+
- 保留现有易用性:继续支持 `-DefaultUser``-DefaultPassword``-Env``.env``.env.local`
16+
-`psutils` 沉淀一套可复用的“配置解析 + 作用域环境执行”基础能力。
17+
-`postgre` / `paradedb` 继续兼容 `DEFAULT_*` 用法,但只接受“本次调用明确提供的来源”。
18+
- 提供足够的调试信息,能回答“某个键最终来自哪里”。
19+
20+
## Non-Goals
21+
22+
- 不重写 `start-container.ps1` 的整体 CLI 形态。
23+
- 不要求所有服务立即改为专用变量。
24+
- 不自动迁移已有 PostgreSQL/ParadeDB 数据目录中的用户、密码或默认库。
25+
- 不在第一版支持复杂 JSON 映射、嵌套对象展开或变量插值。
26+
27+
## Approach Options
28+
29+
### Option 1: 仅在 `start-container.ps1` 中快照并恢复环境
30+
31+
进入脚本时记录相关环境变量,退出时统一恢复。
32+
33+
优点是改动最小,但环境隔离能力仍沉在单个脚本中,后续其他脚本容易重复实现,因此不推荐。
34+
35+
### Option 2: 在 `psutils` 中新增双层通用能力
36+
37+
新增一个通用配置解析器和一个通用作用域环境执行器,`start-container.ps1` 只负责声明来源、优先级和服务特例。
38+
39+
这是推荐方案,因为它既能修复当前问题,又能沉淀公共基础设施,兼顾复用性与兼容性。
40+
41+
### Option 3: 改为临时 env 文件驱动 `docker compose`
42+
43+
每次调用先渲染临时 env 文件,再用 `docker compose --env-file` 执行。
44+
45+
优点是来源非常显式,但实现更重,dry-run、文件清理和兼容性处理也更复杂,因此本次不采用。
46+
47+
## Design
48+
49+
### 1. `psutils` 配置解析器
50+
51+
`psutils` 中新增通用配置解析器,例如 `Resolve-ConfigSources`。该函数只负责读取和合并配置,不直接写入当前进程环境。
52+
53+
第一版支持以下来源类型:
54+
55+
- `Hashtable`
56+
- `EnvFile`
57+
- `JsonFile`
58+
- `ProcessEnv`
59+
60+
调用方显式传入来源列表和优先级顺序。解析器返回一个结构化对象,至少包含:
61+
62+
- `Values`:最终合并后的键值对
63+
- `Sources`:每个键最终命中的来源标识
64+
- `Trace`:可选调试信息,记录候选值和覆盖顺序
65+
66+
第一版 JSON 只支持顶层 key-value 对象,例如:
67+
68+
```json
69+
{
70+
"DEFAULT_USER": "postgres",
71+
"DEFAULT_PASSWORD": "12345678",
72+
"COMPOSE_PROJECT_NAME": "dev-paradedb"
73+
}
74+
```
75+
76+
不支持嵌套展开、数组映射或变量插值。
77+
78+
### 2. `psutils` 作用域环境执行器
79+
80+
`psutils` 中新增通用作用域环境执行器,例如 `Invoke-WithScopedEnvironment`。该函数接收一组环境变量覆盖值和一个 `ScriptBlock`,在执行前注入进程级环境变量,执行结束后无论成功或失败都恢复原值。
81+
82+
其职责与配置解析器严格分离:
83+
84+
- 不关心配置来自哪里
85+
- 只负责临时应用与恢复
86+
- 支持变量原本不存在时在退出后清理
87+
88+
该能力与现有 PostgreSQL 工具中的临时环境恢复模式保持一致,但上提为公共基础设施。
89+
90+
### 3. `start-container.ps1` 的接入方式
91+
92+
`start-container.ps1` 改为“解析本次调用配置,再局部执行 compose”的模式:
93+
94+
1. 收集本次调用显式来源
95+
- CLI 参数
96+
- `-Env`
97+
- 脚本目录下的 `.env`
98+
- 脚本目录下的 `.env.local`
99+
- 服务默认值
100+
2. 调用 `Resolve-ConfigSources`
101+
3. 根据服务类型构造本次调用的 compose 环境变量集合
102+
4. 使用 `Invoke-WithScopedEnvironment` 包裹 `Invoke-DockerCompose`
103+
104+
脚本不再把解析后的 `DEFAULT_*``DATA_PATH``COMPOSE_PROJECT_NAME` 等值长期写回当前会话环境。
105+
106+
### 4. `postgre` / `paradedb` 的特例规则
107+
108+
本次不改变用户的使用习惯。数据库服务仍继续支持:
109+
110+
- `-DefaultUser`
111+
- `-DefaultPassword`
112+
- `-Env @{ DEFAULT_USER = ... }`
113+
- `.env` / `.env.local` 中的 `DEFAULT_*`
114+
115+
但它们默认不再读取“历史会话残留的 `ProcessEnv`”。换句话说,数据库服务继续兼容 `DEFAULT_*`,但只接受“本次调用明确提供的来源”。
116+
117+
普通服务可继续维持当前行为,允许按既有方式消费通用 `DEFAULT_*`
118+
119+
### 5. 旧数据目录保护性提示
120+
121+
针对 `postgre``paradedb`,在启动前检查对应数据目录中是否存在 `PG_VERSION`。若存在,输出明确提示:
122+
123+
- 当前用户名、密码、库名配置仅影响新初始化实例
124+
- 已有数据目录不会自动迁移内部角色、密码或默认库
125+
- 如需变更旧实例内部状态,需要手工迁移或重新初始化数据目录
126+
127+
该提示只负责澄清行为,不阻止启动。
128+
129+
### 6. 调试与可观测性
130+
131+
当用户需要排查来源时,脚本应能基于配置解析器返回的 `Sources` / `Trace` 输出信息,例如:
132+
133+
- `DEFAULT_USER` 最终来自 `-Env`
134+
- `COMPOSE_PROJECT_NAME` 最终来自 `.env.local`
135+
- `DEFAULT_PASSWORD` 最终来自服务默认值
136+
137+
第一版可先提供内部结构和测试,不强制在常规输出中展示所有 trace;后续需要时可扩展为 `-Verbose` 或专门调试输出。
138+
139+
## Priority Rules
140+
141+
配置优先级不在解析器内部写死,而由调用方传入。
142+
143+
`start-container.ps1` 的默认推荐顺序为:
144+
145+
1. CLI 显式参数与 `-Env`
146+
2. `.env.local`
147+
3. `.env`
148+
4. 服务默认值
149+
5. `ProcessEnv`(仅普通服务启用;数据库服务默认关闭)
150+
151+
其中数据库服务通过关闭 `ProcessEnv` 来源来避免历史会话污染,而不是彻底放弃 `DEFAULT_*` 兼容性。
152+
153+
## Testing Strategy
154+
155+
### `psutils` 配置解析器
156+
157+
- `.env``.env.local` 的优先级覆盖
158+
- JSON 与 env 文件的覆盖顺序
159+
- `ProcessEnv` 关闭时不参与解析
160+
- `Trace` 正确记录最终命中来源
161+
- 缺失文件的默认忽略行为
162+
163+
### `psutils` 作用域环境执行器
164+
165+
- 正常执行后恢复环境
166+
- 异常执行后仍恢复环境
167+
- 原本不存在的变量在退出后被移除
168+
169+
### `start-container.ps1`
170+
171+
- `postgre` / `paradedb` 不再读取历史会话残留 `DEFAULT_*`
172+
- `postgre` / `paradedb` 继续接受 `.env``.env.local``-Env`、CLI 参数中的 `DEFAULT_*`
173+
- 普通服务继续保留当前通用变量行为
174+
- 检测到 `PG_VERSION` 时输出迁移提示
175+
- 现有默认用户测试按新优先级更新
176+
177+
## Compatibility and Migration
178+
179+
此改动属于脚本行为收敛,不是数据迁移:
180+
181+
- 普通服务现有使用方式基本保持不变
182+
- `postgre` / `paradedb` 的命令行和 `.env` 用法保持不变
183+
- 唯一被刻意收紧的是数据库服务对“历史会话残留环境”的读取行为
184+
185+
因此:
186+
187+
- 依赖 shell 中长期保留 `DEFAULT_USER` 驱动数据库服务的用法会变化
188+
- 通过本次调用的 `-Env``.env``.env.local`、CLI 参数显式提供值的用法不受影响
189+
190+
## Risks
191+
192+
- 如果配置解析器抽象过重,可能增加脚本理解成本。
193+
- 如果数据库服务与普通服务的优先级差异没有写清楚,可能造成新的认知偏差。
194+
- 如果测试只覆盖解析器,不覆盖 `start-container.ps1` 接入层,仍可能出现“解析正确、接入错误”的问题。
195+
196+
对应缓解方式:
197+
198+
- 第一版只支持 env/json/process hashtable 四类来源
199+
- 明确把数据库服务特例写进文档与测试
200+
-`psutils``start-container.ps1` 两层同时加测试
201+
202+
## Recommended Outcome
203+
204+
本次推荐采用:
205+
206+
- `psutils` 新增通用配置解析器
207+
- `psutils` 新增通用作用域环境执行器
208+
- `start-container.ps1` 改为“解析本次调用配置,再局部注入环境执行 compose”
209+
- `postgre` / `paradedb` 继续兼容 `DEFAULT_*`,但只接受本次调用显式来源
210+
- 新增旧 `PGDATA` 检测提示与来源追踪测试
211+
212+
这样既能修掉当前 `start-container.ps1` 的环境污染问题,又不会把常用的通用变量模型整体推翻。

0 commit comments

Comments
 (0)