1. 简介
在12-Factor App的诸多原则中,有一条非常关键:配置应通过环境变量注入,而非硬编码在代码中。这意味着,配置应与代码分离,独立管理。
在本篇文章中,我们将介绍 Docker 提供的 Secrets 功能,它可以帮助我们安全地管理敏感信息。我们会讲解如何创建和管理 Secrets,并在应用部署中使用它们。
2. 什么是 Secrets?
简单来说,Secrets 是一种安全存储敏感数据的机制,应用在运行时可以读取这些数据。Secrets 在现代应用架构中扮演着关键角色,主要用于保存如数据库密码、SSH 密钥、API 密钥、TLS 证书等敏感信息。
举个例子,我们的应用需要连接数据库,这就需要主机名、用户名和密码。而开发、测试和生产环境使用的数据库信息通常不同。
通过使用 Secrets,每个环境都可以提供自己的配置,应用本身不需要关心当前运行在哪一个环境,只需要以统一的方式获取配置即可。
虽然 Docker Secrets 是相对较新的功能,但大多数云平台早已提供了类似机制:
- AWS 提供了 Secrets Manager
- Azure 提供了 Key Vault
- Kubernetes 也原生支持 Secret 资源
Docker 的 Secrets 实现借鉴了这些系统的优点:
✅ 支持独立创建和管理
✅ 支持最小权限原则
✅ 支持多种数据类型(文本、二进制等)
接下来我们来看看如何管理 Docker Secrets。
3. 管理 Docker Secrets
3.1. Docker 环境要求
⚠️ 注意:Docker Secrets 仅支持在 Swarm 模式下运行的服务。也就是说,普通的 Docker 容器(通过 docker run
启动)无法访问 Secrets。
因此,使用前需要先初始化 Swarm 模式:
docker swarm init --advertise-addr <MANAGER-IP>
如果你使用的是 Windows 或 Mac 上的 Docker Desktop,可以直接运行:
docker swarm init
初始化完成后,就可以开始创建 Secrets。
3.2. 创建 Docker Secrets
Docker Secrets 可以存储几乎所有以字符串或二进制形式表示的数据,例如:
- 用户名和密码
- 主机名和端口号
- SSH 密钥
- TLS 证书
注意:单个 Secret 的大小不能超过 500KB。
你可以通过命令行手动输入创建 Secret:
docker secret create my_secret -
系统会提示你输入内容,输入完成后按 Ctrl+D
(Unix)或 Ctrl+Z
(Windows)结束输入。
不过这种方式在自动化流程中并不实用,更推荐使用文件方式创建:
docker secret create my_secret /path/to/secret/file.txt
3.3. 查看 Docker Secrets
创建完成后,你可以通过以下命令查看所有已创建的 Secrets:
docker secret ls
输出示例:
ID NAME DRIVER CREATED UPDATED
2g9z0nabsi6v7hsfra32unb1o my_secret 30 minutes ago 30 minutes ago
你也可以查看某个 Secret 的详细信息:
docker secret inspect my_secret
返回结果类似如下结构(简化):
[
{
"ID": "2g9z0nabsi6v7hsfra32unb1o",
"Version": {
"Index": 15
},
"CreatedAt": "2022-05-13T00:34:41.2802246Z",
"UpdatedAt": "2022-05-13T00:34:41.2802246Z",
"Spec": {
"Name": "my_secret",
"Labels": {}
}
}
]
3.4. 删除 Docker Secrets
建议在 Secret 不再使用后及时删除,以减少安全风险。删除命令如下:
docker secret rm my_secret
⚠️ 注意:如果该 Secret 正在被某个服务使用,则无法删除。
4. 使用 Docker Secrets
了解了如何管理 Secrets 后,接下来我们看看如何在应用中使用它们。
4.1. 通过 Docker Service 使用
由于 Docker Secrets 只能在 Swarm 模式下使用,因此必须通过 docker service
命令来创建服务,并挂载 Secret:
docker service create --name my_app --secret my_secret openjdk:19-jdk-alpine
这样,服务 my_app
就可以访问名为 my_secret
的 Secret。
4.2. 通过 Docker Compose 使用
从 Docker Compose v3 开始也支持 Secret 的定义。下面是一个简单示例:
version: '3.1'
services:
my_app:
image: my_app:latest
secrets:
- my_external_secret
- my_file_secret
secrets:
my_external_secret:
external: true
my_file_secret:
file: /path/to/secret/file.txt
说明:
my_external_secret
是提前通过docker secret create
创建好的 Secretmy_file_secret
是直接从本地文件创建的 Secret
⚠️ 注意:使用文件方式创建 Secret 会绕过 Docker 的加密机制,存在一定安全风险。此外,该文件必须存在于所有可能运行服务的节点上。
4.3. 应用中访问 Secrets
Docker 会将 Secret 以文件形式挂载到容器中,默认路径为 /run/secrets
。
例如,Secret 名为 my_secret
,则其内容会保存在 /run/secrets/my_secret
文件中。
你也可以自定义挂载路径:
docker service create \
--name my_app \
--secret source=my_secret,target=/different/path/to/secret/file.txt,mode=0400 \
openjdk:19-jdk-alpine
这样,Secret 会被挂载到 /different/path/to/secret/file.txt
,权限为 0400
(只读,仅限所有者)。
这个功能非常实用,比如你想用 Secret 来挂载一个 Nginx 配置文件,可以直接挂载到 /etc/nginx/conf.d/site.conf
。
5. 总结
✅ Secrets 是容器化架构中不可或缺的一部分,它帮助我们实现“配置与代码分离”的目标。
✅ Docker Secrets 提供了一种安全、集中、可管理的方式来存储敏感信息,并通过服务访问机制实现安全注入。
✅ 它特别适合用于生产环境的敏感配置管理,但需要注意它仅支持 Swarm 模式下的服务。
📌 建议:
- 不要使用文件方式代替 Docker Secrets,除非你有特殊需求
- 注意 Secret 的生命周期管理(创建、更新、删除)
- 如果你使用 Kubernetes,建议使用其原生的 Secret 资源管理机制
使用 Docker Secrets,可以有效提升应用配置的安全性和灵活性,是现代 DevOps 流程中值得掌握的重要技能。