docker - 如何生成密钥并在 docker-compose 中的两个容器之间共享?可能吗?
问题描述
问题:我想在我的项目中使用imgproxy,但我需要一些方法来在容器首次运行时生成签名密钥。然后,我需要在两个容器之间共享该密钥:imgproxy,它在环境变量中接受它,以及我的服务器应用程序,我可以从任何需要的地方读取它。对于每个部署,密钥必须是唯一且随机的。避免在docker-compose up
生成这些密钥之前必须运行任何其他命令会很棒。
到目前为止我考虑的:
- 有docker-compose secrets。那些存在于文件中。在开始任何事情之前,您仍然需要创建和填充这些文件。
- 我可以简单地指示用户生成密钥并编辑
docker-compose.yml
以将其添加到那里。
无论如何,解决这个问题的最佳/正确方法是什么?这感觉像是一个流行的用例,所以肯定有我错过的东西吗?
解决方案
处理这个问题的最好方法是在外部创建秘密;在 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 对象是打算用于此用途,但随后又回到了“单独创建秘密”的原始模式。)