12

I have a Dockerised application which I would like to run in both proxy and non-proxy host environments. I'm trying to resolve this problem by copying the normal environment variables, such as http_proxy, into the containers if and only if they exist in the host.

I can get 90% of the way there by running

set | grep -i _proxy=>proxies.env

in a top-level script, and then having, in my docker-compose.yml:

myserver:
  build: ./myserver
  env_file:
   - proxies.env

This copies the host's environmental proxy variables, if any, into the server container, and it works in the sense that these variables are available at container run time, in other words by the stage that the Dockerfile CMD or ENTRYPOINT executes.

However I have one container which needs to run npm as a build step, ie from a RUN command in the Dockerfile, and these variables appear not to be present at this stage, so npm can't find the proxy and hangs. In other works, if I have

RUN set

in my Dockerfile, I can't see any variables from proxies.env, but if I do

docker exec -it myserver /bin/bash

and then run set, I can see everything from proxies.env.

Can anyone recommend a way to make these variables visible at container build time, without having to hard-code them, so that my docker-compose.yml and Dockerfile will still work both for hosts with proxies and hosts without proxies?

(Running with centos 7, docker-compose 1.3.1 and docker 1.7.0)

Francis Norton
  • 674
  • 1
  • 8
  • 16
  • Generating your docker file with the env variables predefined seems like the easiest way to me. – Abdullah Jibaly Jul 05 '15 at 08:27
  • You may well be right. In the absence of a better suggestion, I'll put together a shell script that will use sed to either populate or comment out the hard-coded NPM sed settings, so I can use the same Dockerfile for both cloud and corporate hosts. – Francis Norton Jul 06 '15 at 09:37
  • 2
    Update: with `docker-compose.yml` version 2 (docker 1.10+), you now have a better option: `build:/args:`. See [my answer below](http://stackoverflow.com/a/36084324/6309) – VonC Mar 18 '16 at 12:25

5 Answers5

32

Update 2016, docker-compose 1.6.2, docker 1.10+, with a docker-compose.yml version 2:

You now have the args: sub-section of the build: section, which includes that very interesting possibility:

Build arguments with only a key are resolved to their environment value on the machine Compose is running on.

See PR 2653 (January 2016)

As a result, a way to introduce the proxy variables without hard-coding them in the docker-compose.yml file itself is with that precise syntax:

version: '2'
services:
  myservice:
    build:
      context: .
      args:
        - http_proxy
        - https_proxy
        - no_proxy

Before calling docker-compose up, you need to make sure your proxy environment variables are set:

export http_proxy=http://username:password@proxy.com:port
export https_proxy=http://username:password@proxy.com:port
export no_proxy=localhost,127.0.0.1,company.com

docker-compose up

Then your Dockerfile built by the docker-compose process will pick up automatically the proxy variable values, even though the docker-compose.yml does not include any hard-coded specific values.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    What happens if the host env cannot supply the build arguments and aren't supplied via cli? – Meki Feb 17 '17 at 15:08
6

May be you the "environment" option solves your problem. In your docker compose file would looks like:

myserver:
   build: ./myserver
   environment:
   - HTTP_PROXY=192.168.1.8
   - VARIABLE=value
   - ...
3

Maybe you can try this:

Before you call RUN, ADD the .env file into the image

ADD proxies.env proxies.env

then prefix your RUN statement:

RUN export `cat proxies.env` && echo "FOO is $FOO and BAR is $BAR"

This produces the following output:

root@armenubuntudev:~/Dockers/set-env# docker build -t ashimoon/envtest .
Sending build context to Docker daemon 3.584 kB
Sending build context to Docker daemon 
Step 0 : FROM ubuntu
 ---> 91e54dfb1179
Step 1 : ADD proxies.env proxies.env
 ---> Using cache
 ---> 181d0e082e65
Step 2 : RUN export `cat proxies.env` && echo "FOO is $FOO and BAR is $BAR"
 ---> Running in 30426910a450
FOO is 1 and BAR is 2
 ---> 5d88fcac522c
Removing intermediate container 30426910a450
Successfully built 5d88fcac522c
armen.shimoon
  • 6,303
  • 24
  • 32
  • can't we do ENV ENV JAVA_HOME $(alternatives --list | grep javac | awk '{print $3}' | sed -e "s/\/bin\/javac//g") ???? – Marcello DeSales Nov 11 '15 at 02:11
  • This solves the problem for me — it makes the env variables available at build time for the container – FeifanZ Feb 05 '16 at 05:46
  • 1
    This answer solves the problem, just note that this breaks the philosophy of creating `docker images` ... – nanounanue Feb 26 '16 at 00:31
  • I had to do the export at each separate 'RUN' that needed the env file values. Hopefully we figure out a better solution in the future, but for now, making it work is good enough for me. – Jared Chmielecki Mar 07 '16 at 13:29
2

docker-compose.yml

...
server:
  build: .
  args:
    env: $ENV
...

Dockerfile

ARG env

ENV NODE_ENV $env
Roman Rhrn Nesterov
  • 3,538
  • 1
  • 28
  • 16
0

This example fixes YUM.

version: '2'
services:  
  example-service:
    build:
      context: .
      args:
        http_proxy: proxy.example.com:80
Moriarty
  • 3,957
  • 1
  • 31
  • 27