首页 > 解决方案 > 如何生成密钥并在 docker-compose 中的两个容器之间共享?可能吗?

问题描述

问题:我想在我的项目中使用imgproxy,但我需要一些方法来在容器首次运行时生成签名密钥。然后,我需要在两个容器之间共享该密钥:imgproxy,它在环境变量中接受它,以及我的服务器应用程序,我可以从任何需要的地方读取它。对于每个部署,密钥必须是唯一且随机的。避免在docker-compose up生成这些密钥之前必须运行任何其他命令会很棒。

到目前为止我考虑的:

无论如何,解决这个问题的最佳/正确方法是什么?这感觉像是一个流行的用例,所以肯定有我错过的东西吗?

标签: dockerdocker-compose

解决方案


处理这个问题的最好方法是在外部创建秘密;在 Compose 中,也许在一个.env文件中。这将很好地转化为其他环境,并且根本不需要更改代码。这也适用于需要一些用户干预才能设置的机密(例如,签署 TLS 证书),它会在docker-compose down.

如果这些考虑对您来说并不重要,并且启动自主性非常重要,您可以将秘密放入共享文件中。确定其中一个容器是“第一个”。编写一个在启动时运行的脚本来生成密钥:

#!/bin/sh
# Create a random token if it doesn't already exist
if [ ! -f /secrets/token ]; then
  dd if=/dev/random bs=48 count=1 | base64 > /secrets/token
fi
# Read back the token into an environment variable
SECRET_TOKEN=$(cat /secrets/token)
# Run the main container process
exec "$@"

在您的 Dockerfile 中,COPY将此脚本放入并使其成为图像的ENTRYPOINT. 这必须使用 JSON 数组语法,ENTRYPOINT ["entrypoint.sh"]. 如果您通过 启动应用程序ENTRYPOINT,请将该命令移入CMD(或将拆分ENTRYPOINT/CMD合并为CMD)。

现在在您的 Compose 设置中,您需要创建一个卷并在两个容器之间共享它。

version: '3.8'
volumes:
  secrets: # empty
services:
  imgproxy:
    image: ...
    volumes:
      - secrets:/secrets # matches the path in the entrypoint script
  server:
    image: ...
    volumes:
      - secrets:/secrets # could be a different path

(特别是如果您考虑最终在 Kubernetes 上运行此应用程序,这种方法将无法正常工作。在 Kubernetes 支持的卷类型中,很少有可以同时挂载到多个容器中的。有一个原生 Kubernetes Secret 对象是打算用于此用途,但随后又回到了“单独创建秘密”的原始模式。)


推荐阅读