Docker Compose up/run交互问题:Flask API需输入数据库密码
我有一个运行Python Flask REST API的Docker应用,希望用户通过getpass()输入数据库密码,而非将密码明文存储在配置文件中。由于使用Docker网络进行DNS解析,倾向于用docker compose up而非docker compose run(run会创建新容器,干扰DNS解析)。
当前docker-compose.yml相关服务配置如下:
version: '3.4' services: rest-api: image: rest_api:latest container_name: rest_api tty: true stdin_open: true ports: - 5000:5000 networks: - mynetwork networks: mynetwork: name: any_network
使用docker compose up启动服务时,终端仅处于等待状态,无输入提示且不响应用户操作;使用docker compose run时,输入功能正常,但因容器名称变化导致DNS解析失效。现针对以下方向寻求解决方案:
- 是否应为所有服务在compose文件中定义静态IP?
- 是否可使用加密配置文件存储密码?但我不想使用硬编码密码来解密配置文件。
run命令自带终端交互配置,能否让compose up实现相同特性?需在compose文件中添加哪些配置?- 是否应停止后删除容器,始终使用
docker compose run --name指定容器名?但这样需逐个启动服务,且run需手动指定端口(不读取compose配置),是否正确?
1. 静态IP配置方案
可以给服务指定静态IP,但这并非最优解。静态IP会增加配置复杂度,后续服务扩容或网络调整时容易引发问题。如果一定要使用,可在compose文件的网络配置中为服务添加固定IP:
services: rest-api: # 保留原有配置 networks: mynetwork: ipv4_address: 172.20.0.10 networks: mynetwork: name: any_network ipam: config: - subnet: 172.20.0.0/16
但更建议优先解决compose up的交互问题,而非依赖静态IP。
2. 加密配置文件的可行性
此方案不适用。因为解密加密配置必须依赖密钥,要么硬编码在代码中,要么仍需用户输入密钥,本质和直接输入数据库密码无区别,反而增加了额外复杂度。
3. 让docker compose up支持终端交互
你当前的compose配置已经添加了tty: true和stdin_open: true,但docker compose up默认会聚合所有服务的输出,不会直接绑定当前终端的标准输入。只需在启动时添加--attach参数指定要交互的服务即可:
docker compose up --attach rest-api
执行该命令后,终端会绑定到rest-api服务的标准输入输出,就能正常响应getpass()的输入请求。如果希望默认启动就绑定,可以将该命令封装成启动脚本。
4. docker compose run --name的用法评估
不建议这么做。docker compose run的设计初衷是临时运行服务的一次性命令,而非启动长期运行的服务。手动指定端口会脱离compose配置,后续维护易出错;逐个启动服务效率低下,也违背了compose编排多服务的初衷。
直接使用docker compose up --attach rest-api启动服务,既保留了compose的网络DNS解析(容器名称不变),又能实现终端交互输入密码,无需修改现有compose配置,仅需调整启动命令即可。
内容的提问来源于stack exchange,提问作者m1ch4

