首页 > 解决方案 > 如何根据从 docker-compose.yml 传递的环境变量修改 Dockerfile RUN 命令的效果

问题描述

总而言之,我的项目包括:

因此,在主 docker-compose.yml 中声明了 2 个服务,它们每个都有自己的(非版本化).env 文件,我在其中声明特定于给定服务的“环境特定”参数。例如,对于后端服务,我定义了数据库用户名/密码;对于前端服务,我声明了前端应该通过 Ajax 检索其数据的 REST API URL。

我使用参数通过主 docker-compose.yml 将 /backend/.env 传递给后端服务,并将 /frontend/.env 传递给前端服务env_file

两种服务都托管在不同的域(example.com 和 api.example.com)上。

鉴于 Angular 2 如何处理其配置,您不能声明操作系统级别的环境变量并让 Angular 在运行时在应用程序内使用它们(例如,从 env 变量中读取“BACKEND_URL”并对其进行 Ajax 调用)。相反,它希望在构建过程中所有环境参数都存在于一个名为 /src/app/environment.prod.ts 的文件中。我设法通过 /frontend/Dockerfile 中的 RUN 命令创建了这个配置文件,但我正在努力用未版本化的 /frontend/.env 中声明的动态值填充它。我不想在 /frontend/Dockerfile 中硬编码东西。

一旦 /frontend/Dockerfile 生成具有正确值(例如BACKEND_URL=http://api.example.com)的静态 /src/app/environment.prod.ts,那么构建过程的其余部分就可以了,前端应用程序将获取这些值。

标签: angulardockerdocker-composedockerfile

解决方案


正如您已经指出的那样,问题在于 docker compose 中的 environment/env_file 声明适用于 RUN,但不适用于构建。要通过 docker-compose 将参数传递给 docker build,您必须在 Dockerfile 中指定 ARGS,如此所述。然后,您可以从 compose 文件中传入预定义的参数,如下所示

但是,我觉得这种方法引入了太多的耦合和重复声明。我更倾向于您将环境定义分离到单独的文件中的方法。

除了您已经拥有的之外,您只需要为相应的容器定义一个入口点 shell 脚本,这些容器能够使用环境变量,并environment.prod.ts在应用程序启动之前生成角度环境绑定。


推荐阅读