35
votes

Having the following docker-compose file:

db:
    build: .
    environment:
        - MYSQL_ROOT_PASSWORD=password
        - ENV=test
    env_file: .env

Is there any way to use the env variables declared in docker-compose.yml (either as environment or declared in the env_file) as part of Dockerfile without declaring them in the Dockerfile? Something like this:

FROM java:7
ADD ${ENV}/data.xml /data/
CMD ["run.sh"]
3
that would be really useful.Greg
No, this is not possible. It would be very similar to this question on using environment variables from the host: stackoverflow.com/questions/27925006/…Hans Kristian
Actually, there's work in progress to facilitate this; github.com/docker/docker/pull/9176 this won't be part of Docker 1.6, but possibly 1.7thaJeztah
Anyone got answer for this please?? it's 1.8.2 already. I need to get something from docker-compose in Dockerfile!holms
As of Docker 1.9, build-time arguments are now available. However, Compose does not support it yet.yjwong

3 Answers

33
votes

Although this question was asked long ago, there is an answer to a similar question here: Pass environment variables from docker-compose to container at build stage

Basically, to use variables at the container's build time one has to define the variable in docker-compose.yml:

build:
  context: .
  args:
    MYSQL_ROOT_PASSWORD: password
    ENV: test

and then reference it in the Dockerfile using ARG:

ARG MYSQL_ROOT_PASSWORD
ARG ENV
ADD ${ENV}/data.xml /data/

Concerning environment variables defined in an *.env file, I believe that they can't be passed to the container at build time.

18
votes

It works ok this way:

docker-compose.yml

version: '3.5'

services:
    container:
        build:
            context: .
            args:
                ENV: ${ENV} # from .env file
        env_file:
            - .env

Dockerfile

# from compose args
ARG ENV 
ADD ${ENV}/data.xml /data/

.env

ENV=myenv

Thus all the values are taken from .env file

11
votes

This approach goes against the 'build once, run anywhere' theory behind Docker and most DevOps approaches. With this approach you'll need to build a container for every environment you expect to use. By doing so you can't safely say if a container works in the dev environment it will work in staging and production since you aren't using the same container.

You'd be better off adding all config files you need on to the container and writing an entrypoint script that selects/copies the data for that environment to the correct location when the container starts. You can also apply this approach to other config on the container, like templated Apache config using jinja2 templates etc.