在构建时使用 docker-compose 将环境变量传递给 docker 映像

Posted

技术标签:

【中文标题】在构建时使用 docker-compose 将环境变量传递给 docker 映像【英文标题】:Passing environment variable to docker image at build time with docker-compose 【发布时间】:2018-12-18 19:38:50 【问题描述】:

我在 Dockerfile 和 docker compose 引用之后尝试将环境变量传递给 Docker 映像的所有方法都不起作用。

我想在使用 docker-compose 时在 docker build 期间使这个 env var 可用。

在我拥有的 Docker 主机上:

export BUILD_VERSION=1.0

app.js

console.log('BUILD_VERSION: ' + process.env.BUILD_VERSION);

Dockerfile:

FROM node
ADD app.js /
ARG BUILD_VERSION
ENV BUILD_VERSION=$BUILD_VERSION
RUN echo Build Time: $BUILD_VERSION
RUN node /app.js
CMD echo Run Time: $BUILD_VERSION

docker-compose.yml:

version: '3'
services:
  app:
    build:
      context: .
      args:
        - BUILD_VERSION

如果我直接构建图像,则 env var 可以正常传递:

docker build -t test --no-cache --build-arg BUILD_VERSION .

并且在运行时也可用:

$ docker run --rm test
Run Time: 1.0
$ docker run --rm test node /app
BUILD_VERSION: 1.0

但不适用于 docker compose。

docker-compose up --build

...
Step 5/7 : RUN echo Build Time: $BUILD_VERSION
 ---> Running in 6115161f33bf
Build Time:
 ---> c691c619018a
Removing intermediate container 6115161f33bf
Step 6/7 : RUN node /app.js
 ---> Running in f51831cc5e1e
BUILD_VERSION:

它只在运行时可用:

$ docker run --rm test
Run Time: 1.0
$ docker run --rm test node /app
BUILD_VERSION: 1.0

我还尝试在 docker-compose.yml 中使用environment,如下所示,这再次使其在运行时可用,但在构建时不可用:

version: '3'
services:
  app:
    build:
      context: .
    environment:
      - BUILD_VERSION

请指教,我怎样才能让它以最不复杂的方式工作?

【问题讨论】:

只要 Dockerfile 有 ENV AA=$BB 并且之前你已经完成了 export BB=CC ,那么 yaml 就不需要提及 args 或任何命令行 build-arg @ScottStensland 也试过了;没用。 :( 我不使用 docker-compose 来构建图像,只是为了启动或关闭它的容器......构建我发出...... docker build --tag foo --no-cache 。 ... 其次是 ... docker push foo ... 对我来说 docker-compose yaml 文件的内容是运行时设置,它混合并过于复杂,使其还控制构建,特别是当您有许多具有不同重建标准的容器时与发射 我同意最好将所有构建任务保留在 Dockerfile 中,只要它在通过 docker-compose 调用时有效。但我还没有找到可行的解决方案。 【参考方案1】:

你的例子对我有用。

您是否尝试过删除图像并重新构建?如果图像在缓存中,尽管环境变量发生了变化,Docker 也不会重新构建你的图像。

您可以使用以下命令删除它们:

 docker-compose down --rmi all

编辑,我在这里展示它是如何在构建时为我工作的:

$ cat Dockerfile
FROM alpine
ARG BUILD_VERSION
ENV BUILD_VERSION=$BUILD_VERSION
RUN echo Build Time: $BUILD_VERSION

$ cat docker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
      args:
        - BUILD_VERSION

构建:

$ export BUILD_VERSION=122221
$ docker-compose up --build
Creating network "a_default" with the default driver
Building app
Step 1/4 : FROM alpine
latest: Pulling from library/alpine
8e3ba11ec2a2: Pull complete
Digest: sha256:7043076348bf5040220df6ad703798fd8593a0918d06d3ce30c6c93be117e430
Status: Downloaded newer image for alpine:latest
---> 11cd0b38bc3c
Step 2/4 : ARG BUILD_VERSION
---> Running in b0a1a79967a0
Removing intermediate container b0a1a79967a0
---> 9fa331d63f6d
Step 3/4 : ENV BUILD_VERSION=$BUILD_VERSION
---> Running in a602c27689a5
Removing intermediate container a602c27689a5
---> bf2181423c93
Step 4/4 : RUN echo Build Time: $BUILD_VERSION                <<<<<< (*)
---> Running in 9d828cefcfab
Build Time: 122221
Removing intermediate container 9d828cefcfab
---> 2b3afa3d348c
Successfully built 2b3afa3d348c
Successfully tagged a_app:latest
Creating a_app_1 ... done
Attaching to a_app_1
a_app_1 exited with code 0

正如提到的另一个答案,您可以使用docker-compose build --no-cache,如果您有多个服务,则可以避免提及“应用程序”,因此 docker-compose 将构建所有服务。在同一个 docker-compose build 中处理不同构建版本的方法是使用不同的环境变量,例如:

$ cat docker-compose
version: '3'
services:
  app1:
    build:
      context: .
      args:
        - BUILD_VERSION=$APP1_BUILD_VERSION
  app2:
    build:
      context: .
      args:
        - BUILD_VERSION=$APP2_BUILD_VERSION

导出:

$ export APP1_BUILD_VERSION=1.1.1
$ export APP2_BUILD_VERSION=2.2.2

构建:

$ docker-compose build
Building app1
Step 1/4 : FROM alpine
latest: Pulling from library/alpine
8e3ba11ec2a2: Pull complete
Digest: sha256:7043076348bf5040220df6ad703798fd8593a0918d06d3ce30c6c93be117e430
Status: Downloaded newer image for alpine:latest
---> 11cd0b38bc3c
Step 2/4 : ARG BUILD_VERSION
---> Running in 0b66093bc2ef
Removing intermediate container 0b66093bc2ef
---> 906130ee5da8
Step 3/4 : ENV BUILD_VERSION=$BUILD_VERSION
---> Running in 9d89b48c875d
Removing intermediate container 9d89b48c875d
---> ca2480695149
Step 4/4 : RUN echo Build Time: $BUILD_VERSION
---> Running in 52dec27874ec
Build Time: 1.1.1
Removing intermediate container 52dec27874ec
---> 1b3654924297
Successfully built 1b3654924297
Successfully tagged a_app1:latest
Building app2
Step 1/4 : FROM alpine
---> 11cd0b38bc3c
Step 2/4 : ARG BUILD_VERSION
---> Using cache
---> 906130ee5da8
Step 3/4 : ENV BUILD_VERSION=$BUILD_VERSION
---> Running in d29442339459
Removing intermediate container d29442339459
---> 8b26def5ef3a
Step 4/4 : RUN echo Build Time: $BUILD_VERSION
---> Running in 4b3de2d223e5
Build Time: 2.2.2
Removing intermediate container 4b3de2d223e5
---> 89033b10b61e
Successfully built 89033b10b61e
Successfully tagged a_app2:latest

【讨论】:

在运行时,环境变量可用。我需要在构建时拥有它。【参考方案2】:

您需要在 docker-compose.yml 中设置参数,如图所示,然后将其覆盖到传递的 env 变量 -

version: '3'
services:
  app:
    build:
      context: .
      args:
        - BUILD_VERSION

下一个你需要传递的导出环境变量。

$ export BUILD_VERSION=1.0

现在使用命令构建镜像

$ docker-compose build --no-cache --build-arg BUILD_VERSION=$BUILD_VERSION app

【讨论】:

正如我所提到的,即使没有使用docker build 命令的虚拟值,它也可以工作。但我需要它与docker-compose 一起工作。 我已经更新了答案,如果有用你可以试试这个! 成功了!但我希望我可以通过docker-compose up 一步完成。当我在docker-compose.yml 有多个服务时,我必须单独构建图像。【参考方案3】:

你可以传入 args 来构建,从 docker-compose 文件到 docker build。令人惊讶的是,环境变量不用于运行构建。

// docker-compose.yml

version: '3'
services:
app:
  build:
    context: .
environment:
  - BUILD_VERSION
args:
  - BUILD_VERSION=$BUILD_VERSION
volumes:
       ...
// Dockerfile
FROM node
ADD app.js /
ARG BUILD_VERSION
ENV BUILD_VERSION=$BUILD_VERSION
RUN echo Build Time: $BUILD_VERSION
RUN node /app.js
CMD echo Run Time: $BUILD_VERSION

【讨论】:

以上是关于在构建时使用 docker-compose 将环境变量传递给 docker 映像的主要内容,如果未能解决你的问题,请参考以下文章

HyperLedger Fabric 2.x 环境搭建

在运行时将环境变量传递给 Vue 应用程序

为 CTest 测试设置环境变量时遇到问题

将预处理器变量传递给 nmake 构建环境

将环境变量注入图像的构建阶段

ubuntu18.04在线安装dockernvidia-docker2与docker-compos