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 创建好的 Secret
  • my_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 流程中值得掌握的重要技能。


原始标题:Introduction to Docker Secrets