对,这里是我前面没说清楚,确实自相矛盾。先认错。
核心事实是:
docker secret create 的时候,Docker 必须拿到一次明文。这个动作绕不开。
但"拿到一次明文"不等于"把明文长期持久化到 /etc/django-seo/secrets"。
你现在的 /etc/django-seo/secrets/*.txt 是明文持久化存储 ,这是错误现状,不是目标方案。
我前面把它写成创建 secret 的常规步骤,是错的。它只能算"你已经有明文文件时,不得已的一次性迁移动作",而且创建完必须立刻销毁。
一、为什么创建时必须给明文?
因为 Docker Swarm Secrets 不是"从加密文件解密"。
它的流程是:
text
你把明文交给 Docker
↓
docker secret create
↓
Docker 把明文加密后存入 Swarm Raft 日志
↓
容器运行时,Docker 解密并以 tmpfs 挂到 /run/secrets
所以:
- 创建前:明文必须存在一次。
- 创建后:长期存储是加密的,宿主机不需要再保留明文。
- 运行时 :容器内
/run/secrets是内存文件,不落盘。
"不要持久化明文存储"指的是:
不要长期把明文放在 /etc/django-seo/secrets 这种磁盘文件里。
不是指"创建 secret 时不需要明文"。
二、正确的创建方式:明文不落盘
不要从 /etc/django-seo/secrets/*.txt 读。
直接管道进 docker secret create。
方式 1:交互输入
bash
read -rsp "DB password: " DB_PASS; echo
printf '%s' "$DB_PASS" | docker secret create django_seo_db_password -
unset DB_PASS
注意用 printf '%s',不要用 echo,否则会多一个换行。
方式 2:从密码管理器读
比如 pass:
bash
pass show docker/db_password | docker secret create django_seo_db_password -
方式 3:随机生成
bash
openssl rand -base64 32 | tr -d '\n' | docker secret create django_seo_secret_key -
这些方式明文只经过:
- 你的终端输入
- shell 变量,短暂
- 管道
- Docker 进程内存
不落盘。
三、如果你现在的明文已经在 /etc/django-seo/secrets 怎么办?
那就把它当成"已经泄露过"。
因为明文已经在磁盘上存在过,可能被备份、快照、日志、审计抓到。
正确顺序:
- 先初始化 Swarm:
bash
docker swarm init --advertise-addr 192.168.0.118
-
在数据库、Redis 端修改密码,生成新密码。
-
用新密码直接管道创建 secret,不要再写
/etc:
bash
read -rsp "New DB password: " NEW_DB_PASS; echo
printf '%s' "$NEW_DB_PASS" | docker secret create django_seo_db_password_v2 -
unset NEW_DB_PASS
- 更新服务使用新 secret:
bash
docker service update \
--secret-rm django_seo_db_password \
--secret-add source=django_seo_db_password_v2,target=django_seo_db_password \
django-seo_web
- 删除旧 secret:
bash
docker secret rm django_seo_db_password
- 彻底删除
/etc明文:
bash
sudo shred -u /etc/django-seo/secrets/*.txt
sudo rmdir /etc/django-seo/secrets
- 以后永远不要再往
/etc/django-seo/secrets写明文。
四、以后轮换密码怎么做?
永远不要写回 /etc。直接:
bash
read -rsp "New DB password: " NEW_DB_PASS; echo
printf '%s' "$NEW_DB_PASS" | docker secret create django_seo_db_password_v3 -
unset NEW_DB_PASS
docker service update \
--secret-rm django_seo_db_password_v2 \
--secret-add source=django_seo_db_password_v3,target=django_seo_db_password \
django-seo_web
docker secret rm django_seo_db_password_v2
数据库那边也要同步改密码。
顺序要小心,最好在维护窗口做,避免服务连不上。
五、最终原则
- 创建 secret 时:明文必须提供一次,但走 stdin / 密码管理器 / 随机生成,不落盘。
- 长期存储:加密在 Swarm Raft 日志里。
- 运行时 :容器内
/run/secrets,tmpfs,不落盘。 - Django 读取 :直接从
/run/secrets/xxx读文件,不要转成环境变量。 - 禁止 :
/etc/django-seo/secrets明文、root:docker 640、docker compose up当 Swarm secret 用、把密码写进镜像或 Git 明文。
一句话:
创建时必须给一次明文,但给完就完了,不能把明文长期放在 /etc。
你现在的 /etc/django-seo/secrets 是必须清理掉的错误现状,不是目标方案。