您如何使用 docker-compose v3.1 管理秘密值?

how do you manage secret values with docker-compose v3.1?

docker-compose.yml 规范的 3.1 版引入了对 secrets 的支持。

我试过这个:

version: '3.1'

services:
  a: 
    image: tutum/hello-world
  secret: 
    password: the_password
  b:
    image: tutum/hello-world

$ docker-compose up returns:

Unsupported config option for services.secret: 'password'

我们如何在实践中使用秘密功能?

我猜关键字是 secrets 而不是 secret。这至少是我阅读 schema.

的理解

这是您 docker-compose.yml 文件的准确缩进吗?我认为secretsecrets应该嵌套在a下(即其中一项服务),而不是直接在 services 部分下。

假定您有服务 myapp 和机密文件 secrets.yml:

创建合成文件:

version: '3.1'

services:
  myapp:
    build: .
    secrets:
      secrets_yaml

使用此命令提供机密:

docker secret create secrets_yaml secrets.yml

使用此命令部署您的服务:

docker deploy --compose-file docker-compose.yml myappstack

现在您的应用程序可以访问位于 /run/secrets/secrets_yaml 的秘密文件。您可以在应用程序中硬编码此路径或创建符号 link.


不同的问题

这个答案可能是对问题 "how do you provision your secrets to your docker swarm cluster" 的回答。

原始问题 "how do you manage secret values with docker compose" 暗示 docker-compose 文件包含秘密值。它没有。

有一个不同的问题:"Where do you store the canonical source of the secrets.yml file"。这取决于你。您可以将其存储在脑海中,打印在 sheet 纸上,使用密码管理器,使用专用的秘密 application/database。见鬼,如果 git 存储库自身安全,您甚至可以使用它。当然,切勿将其存储在您使用它保护的系统中:)

我会推荐 vault。存储秘密:

# create a temporary secret file
cat secrets.yml | vault write secret/myappsecrets -

检索秘密并将其放入您的 docker 群:

vault read -field=value secret/myappsecrets | docker secret create secrets_yaml -

当然,您可以使用 docker 集群本身作为您秘密的单一真实来源,但如果您的 docker 集群崩溃,您就会丢失您的秘密。所以一定要在别处备份。


没人问的问题

第三个问题(没有人问)是如何为开发人员的机器提供秘密。当存在无法在本地模拟的外部服务或无法复制的大型数据库时,可能需要它。

同样,docker 与它无关(目前)。它没有指定哪些开发人员可以访问哪些机密的访问控制列表。它也没有任何身份验证机制。

理想的解决方案似乎是这样的:

  • 开发人员打开了一些 Web 应用程序。
  • 使用某种单点登录机制进行身份验证。
  • 复制一长串 docker secret create 命令并在终端中执行它们。

我们还没有看到这样的应用程序是否弹出。

您可以阅读corresponding section from the official documentation

要使用机密,您需要在 docker-compose.yml 文件中添加两件事。首先,定义所有秘密的 top-level secrets: 块。然后,每个服务下的另一个 secrets: 块指定 服务应接收哪些 机密。

例如,创建 Docker 可以理解的两种类型的机密:外部 机密和 文件 机密。

1。使用 docker secret create

创建一个 'external' 秘密

第一件事:要使用 Docker 的秘密,您所在的节点必须是群的一部分。

$ docker swarm init

接下来,创建一个 'external' 秘密:

$ echo "This is an external secret" | docker secret create my_external_secret -

(确保包含最后一个破折号 -。这很容易错过。)

2。将另一个秘密写入文件

$ echo "This is a file secret." > my_file_secret.txt

3。创建一个使用两个秘密的 docker-compose.yml 文件

现在两种类型的机密都已创建,这里是 docker-compose.yml 文件,它将读取这两种机密并将它们写入 web 服务:

version: '3.1'

services:
  web:
    image: nginxdemos/hello
    secrets:                    # secrets block only for 'web' service
     - my_external_secret
     - my_file_secret

secrets:                        # top level secrets block
  my_external_secret:
    external: true
  my_file_secret:
    file: my_file_secret.txt

Docker 可以从它自己的数据库(例如 docker secret create 生成的秘密)或文件中读取秘密。以上显示了两个示例。

4。部署您的测试堆栈

使用以下方法部署堆栈:

$ docker stack deploy --compose-file=docker-compose.yml secret_test

这将创建一个 web 服务实例,名为 secret_test_web

5。验证服务创建的容器是否具有两个秘密

使用 docker exec -ti [container] /bin/sh 验证秘密是否存在。

(注意:在下面的 docker exec 命令中,m2jgac... 部分在您的机器上会有所不同。运行 docker ps 以查找您的容器名称。)

$ docker exec -ti secret_test_web.1.m2jgacogzsiaqhgq1z0yrwekd /bin/sh

# Now inside secret_test_web; secrets are contained in /run/secrets/
root@secret_test_web:~$ cd /run/secrets/

root@secret_test_web:/run/secrets$ ls
my_external_secret  my_file_secret

root@secret_test_web:/run/secrets$ cat my_external_secret
This is an external secret

root@secret_test_web:/run/secrets$ cat my_file_secret
This is a file secret.

如果一切顺利,我们在步骤 1 和 2 中创建的两个秘密应该在我们部署堆栈时创建的 web 容器中。

您还可以使用 secrets 对象中的 file: 键指定 secrets 本地存储在文件中。那么您就不必自己 docker secret create 它们,Compose / docker stack deploy 会为您完成。

version: '3.1'

secrets:
  password:
    file: ./password

services:
  password_consumer:
    image: alpine
    secrets:
      - password

参考:Compose file version 3 reference: Secrets

这里的评论提出了一个问题,如果我只需要秘密,为什么还要初始化一个swarm?我的回答是,秘密是为集群创建的,在集群中,您拥有多个节点,并且您希望以一种安全的方式管理和共享秘密。但是如果你有一个节点,如果有人可以访问你拥有一个节点群的主机,这将不会(几乎)增加任何额外的安全性,因为秘密可以从 运行 容器中检索,或者直接在host 如果秘密是从文件创建的,比如私钥。

查看此博客:https://www.docker.com/blog/docker-secrets-management/

并阅读评论: "非常感谢您的介绍文章。在工作节点上创建redis容器时,提到查看容器中秘密内容的步骤将不起作用。"

关键字是secrets而不是secret。 它也应该在服务 a.

下正确缩进