angular - 如何根据从 docker-compose.yml 传递的环境变量修改 Dockerfile RUN 命令的效果
问题描述
总而言之,我的项目包括:
- /docker-compose.yml
- /backend/Dockerfile(用于“后端”服务的 Docker 文件,一个 Yii2 REST api)
- /backend/.env(未版本化)
- /frontend/Dockerfile(“前端”服务的 Docker 文件,一个 Angular2 应用程序)
- /frontend/.env(未版本化)
因此,在主 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,那么构建过程的其余部分就可以了,前端应用程序将获取这些值。
解决方案
正如您已经指出的那样,问题在于 docker compose 中的 environment/env_file 声明适用于 RUN,但不适用于构建。要通过 docker-compose 将参数传递给 docker build,您必须在 Dockerfile 中指定 ARGS,如此处所述。然后,您可以从 compose 文件中传入预定义的参数,如下所示。
但是,我觉得这种方法引入了太多的耦合和重复声明。我更倾向于您将环境定义分离到单独的文件中的方法。
除了您已经拥有的之外,您只需要为相应的容器定义一个入口点 shell 脚本,这些容器能够使用环境变量,并environment.prod.ts
在应用程序启动之前生成角度环境绑定。