给定一个文件
oneSourceOfTruth.env
:
FOO=42
... (many entries)
和一个
docker-compose.yml
:
services:
my-service:
dockefile: ./Dockerfile
env_file: oneSourceOfTruth.env
我希望通过
oneSourceOfTruth.env
在构建步骤中以及在运行时 (
Dockerfile
) 期间在容器中使用
docker compose build
中的所有变量。这些变量是“静态”的,因为它们一旦设置(在构建之前),然后对于特定构建和从构建生成的容器就不再更改。
不幸的是,它不适用于
docker compose up
选项,因为它仅将环境变量传递给 containers。环境变量在构建期间不可用(例如,在 Dockerfile 中使用 env_file
命令)。旁注
:我不一定需要直接访问
RUN
文件本身内的环境变量,例如我们的 docker-compose.yml
文件中没有
有类似以下内容。
docker-compose.yml
⭕约束
args:
- FOO=$FOO
文件相当长。出于可扩展性的原因和更好的代码质量,我想将此文件视为“事实的一个来源”,其中环境变量是设置
。也就是说,引入(删除)环境变量只意味着我必须在此文件中单独添加(删除)一行。❎ 在不考虑约束的情况下解决目标的方法。 来自对某个问题的评论
如果您有一个很大的环境文件,那么这不是一个实用的解决方案。如果您只能读取从撰写文件传递的环境变量,这会使开发变得乏味且不必要的烦人。硬编码变量从来都不好,因为如果您想添加更多环境变量,则必须编辑多个文件。
hereARG FOO
ENV FOO $FOO
提出的解决方案对我不起作用(环境变量未填充/为空)。here和here
docker-compose.yml
.env
如何在“docker build”期间将环境变量值获取到 Dockerfile 中?
env_file
中,我们使用以下Rails命令来预编译我们的资产:
Dockerfile
不幸的是,这将产生整个 Rails 机制(至少我们可以避免使用
RUN DB_ADAPTER=nulldb bundle exec rails assets:precompile
适配器从这里连接到数据库)。存在一个选项
DB_ADAPTER=nulldb
,可以将其设置为
initialize_on_precompile
以避免为此任务启动 Rails,请参阅此处)。但是,此选项已从 Rails 代码库中删除,请参阅此提交
。这意味着我们也被迫在
false
任务中加载环境变量。如前所述,通过 precompile
文件中的关键 env_file
,环境变量仅在容器中可用,而不是在构建期间可用(我们需要它们来执行
docker-compose.yml
任务)。到目前为止的解决方法是在 ruby on Rails 代码中的任何地方使用
precompile
,这样如果未指定,变量默认为
ENV("Foo", nil)
。这样一切就可以了:在
nil
任务期间,所有环境变量都是
precompile
但我们并不需要它们来完成预编译资产的任务。在生产运行时,环境变量将可用。
但是通过这种方法,当我们真的忘记设置环境变量时,我们会默默地忽略这种情况。然后,同样在生产过程中,变量将为
nil
,我们只能通过它引起的影响来识别这一点。因此,到目前为止,我们的解决方案实际上只是一种解决方法,应该予以修复。如果变量不可用,它应该在项目的构建步骤期间引发
nil
,而不仅仅是当用户抱怨我们的应用程序中的某些内容无法正常工作时。这可以通过使用 KeyError
而不是
ENV("Foo")
来实现,但现在我们在
ENV("Foo", nil)
任务期间遇到关键错误,因为环境变量在
precompile
中不可用(我们在其中执行
Dockerfile
任务) 。这正是问题所在;)
您的机器上有可用的
precompile
,Docker 构建发生在其中,对吗?
oneSourceOfTruth.env
请记住,最终的 Docker 镜像应该不
包含任何秘密。因此,我建议在完成构建之前再次从图像文件中删除# ...
WORKDIR /app
COPY oneSourceOfTruth.env /app/oneSourceOfTruth.env
RUN source /app/oneSourceOfTruth.env
RUN DB_ADAPTER=nulldb bundle exec rails assets:precompile
RUN rm -f /app/oneSourceOfTruth.env
# ...
,或者进行多阶段构建,在第一步中进行构建并将构建结果(不带oneSourceOfTruth.env
)复制到第二步构建步骤。
在运行时,像您已经做的那样在 Docker Compose 配置中传递
oneSourceOfTruth.env
。