Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing environment variable to docker image at build time with docker-compose

Everything I tried following Dockerfile and docker compose references to pass an environment variable to the Docker image did not work.

I want to make this env var available during docker build when using docker-compose.

On the Docker host I have:

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

If I build the image directly, the env var is passed fine:

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

and is also available at run-time:

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

but not with 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:

It's only available at run-time:

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

I also tried using environment in docker-compose.yml like below which again only makes it available at run-time but not build-time:

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

Please advise, how can I make it work in the least convoluted way?

like image 873
orad Avatar asked Jul 10 '18 21:07

orad


People also ask

Does docker compose pass environment variables?

Docker Compose allows us to pass environment variables in via command line or to define them in our shell. However, it's best to keep these values inside the actual Compose file and out of the command line.

What is the correct way to pass an argument with a value during docker build phase?

If you want to pass multiple build arguments with docker build command you have to pass each argument with separate — build-arg. docker build -t <image-name>:<tag> --build-arg <key1>=<value1> --build-arg <key2>=<value2> .

Does docker build use docker compose?

The three primary differences between the Dockerfile and docker-compose are: The Dockerfile is used to build images while the docker-compose. yaml file is used to run images. The Dockerfile uses the docker build command, while the docker-compose.


2 Answers

Your example is working for me.

Have you tried deleting the images and building again? Docker won't re-build your image despite environment variables changed if the image is in cache.

You can delete them with:

 docker-compose down --rmi all

Edit, I show here how it is working for me at build time:

$ 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

Build:

$ 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

As the other answer mentioned, you can use docker-compose build --no-cache, and you can avoid mentioning "app" if you have multiple services, so docker-compose will build all the services. What you can do to handle different build versions in the same docker-compose build is to use different env vars, like:

$ 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:

$ export APP1_BUILD_VERSION=1.1.1
$ export APP2_BUILD_VERSION=2.2.2

Build:

$ 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
like image 82
Robert Avatar answered Sep 20 '22 05:09

Robert


You need to set argument in docker-compose.yml as shown which will then be overriden to passed env variable -

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

Next export environment variable you need to pass.

$ export BUILD_VERSION=1.0

Now build the image using command

$ docker-compose build --no-cache --build-arg BUILD_VERSION=$BUILD_VERSION app
like image 34
Mishi.Srivastava Avatar answered Sep 19 '22 05:09

Mishi.Srivastava