Repository: deis/deis

Issue:
Cannot retrieve environment variables set in Dockerfile from the application
I'm not sure if it is an issue. But it's kind weird to me: the deis application cannot get the environment variables set in the Dockerfile.

My Dockerfile:

```
FROM ubuntu:trusty
MAINTAINER quyennt "quyen@agencyrevolution.com"
# Set environment variables
ENV NODE_ENV development
ADD test.sh /test.sh
EXPOSE 80
ENTRYPOINT ["/bin/bash", "/test.sh"]
```

My `test.sh`:

```
#!/bin/bash
echo "print environment..."
echo $NODE_ENV
```

It's just simple as that, but I cannot get the `$NODE_ENV` printed out in the logs:

```
fleetctl status test-env-vars_v4.cmd.1.service
● test-env-vars_v4.cmd.1.service - test-env-vars_v4.cmd.1
   Loaded: loaded (/run/fleet/units/test-env-vars_v4.cmd.1.service; linked-runtime)
   Active: inactive (dead)

Jul 15 11:21:56 deis-1 systemd[1]: Starting test-env-vars_v4.cmd.1...
Jul 15 11:21:58 deis-1 docker[2365]: Pulling repository 172.17.8.100:5000/test-env-vars
Jul 15 11:22:02 deis-1 systemd[1]: Started test-env-vars_v4.cmd.1.
Jul 15 11:22:02 deis-1 sh[2754]: print environment...
Jul 15 11:22:02 deis-1 docker[2805]: test-env-vars_v4.cmd.1
```

The behavior is different from using docker alone. Can anyone explain the reason? Thanks! 



Discussion:
@ntquyen what happens if you run a `deis run env`? does the environment variable show up?

It prints the first line, and an empty line:

```
$ deis run env
print environment...

$
```

Oh right, because you set it as an entrypoint you cannot run arbitrary commands in the image any more. Could you try changing the ENTRYPOINT to a CMD, re-push the app and try running `deis run env` again? I just want to confirm what the environment shows. Could you also please run the following so we can see the raw JSON metadata of the app image...

```
$ fleetctl ssh deis-registry
$ curl localhost:5000/v1/repositories/test-env-vars/tags/latest
```

Then copy/paste the image ID from the last command:

```
$ curl localhost:5000/v1/images/<image_id>/json
```

That should tell us if NODE_ENV ever got into the container's environment during the build.

After change ENTRYPOINT to a CMD, here what it looks like:

```
$ deis run env
HOME=/
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=d2c81c6e7090
```

And the NODE_ENV does appear in `$ curl localhost:5000/v1/images/<image_id>/json`

Anyway, what I'm trying to do is retrieve the environment variables from within my application at runtime. So I have to set a ENTRYPOINT, rather than a CMD, right? 

We've seen this issue happen before... This is not the intended behaviour. I'll look further into this.

However, when I use ENTRYPOINT, running `docker inspect <image id>` and I found my environment variables in the container, the same when I change to CMD.

@bacongobbler I found a weird behavior with docker that might be related to this issue:
When I first entered the container and run `env`, I can find my environment variables:

```
$ docker run -p 6002:6002 -p 8181:8181 -i -t develop/tokenauthentication /bin/bash
root@08d8c45bb283:/# env
HOSTNAME=08d8c45bb283
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
NODE_ENV=development
```

But in another terminal window, I enter the same container using `nse`, my environment vars disappear: 

```
$ nse 08d8c45bb283
groups: cannot find name for group ID 11
root@08d8c45bb283:/# env
COREOS_PRIVATE_IPV4=172.17.8.100
SHELL=/bin/bash
TERM=xterm
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
SUDO_USER=core
SUDO_UID=500
USERNAME=root
MAIL=/var/mail/root
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin:/mnt/host/source/chromite/bin
PWD=/
COREOS_PUBLIC_IPV4=172.17.8.100
NODE_PATH=/usr/lib/nodejs:/usr/lib/node_modules:/usr/share/javascript
SHLVL=1
SUDO_COMMAND=/bin/nsenter --pid --uts --mount --ipc --net --target 3863
HOME=/root
LOGNAME=root
LESSOPEN=| /bin/lesspipe %s
SUDO_GID=500
LESSCLOSE=/bin/lesspipe %s %s
_=/usr/bin/env
```

Hope that will help you to help me to resolve the issue!!

Odd, environment variables set with ADD do not work, but with `deis config:set`, it does...

Example Dockerfile to reproduce this issue:

```
FROM ubuntu:14.04
ENV NODE_ENV development
RUN apt-get update && apt-get install -yq python
EXPOSE 80
CMD python -m SimpleHTTPServer 80
```

Note that after pushing to Deis, this is the image metadata:

```
core@deis-1 ~ $ curl localhost:5000/v1/repositories/zaftig-moonrise/tags/v2
"62cde782340a41b69a0ed2d3ce0853f362cde782340a41b69a0ed2d3ce0853f3"
core@deis-1 ~ $ curl localhost:5000/v1/images/62cde782340a41b69a0ed2d3ce0853f362cde782340a41b69a0ed2d3ce0853f3/json
{"container": "7b821f8255cced20ef1c17af3fcffeef8342c4fc5c3be68fa4c0102a666bdb26", "parent": "2351b180f607d0f8253797c50829df9a4485421b0059432dc38b2a34e4fbfc1c", "created": "2014-07-16T15:44:28.431741554Z", "os": "linux", "container_config": {"Env": ["HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NODE_ENV=development"], "Hostname": "0e6756a12879", "Entrypoint": null, "PortSpecs": null, "Memory": 0, "OnBuild": [], "OpenStdin": false, "Cpuset": "", "User": "", "AttachStderr": false, "AttachStdout": false, "NetworkDisabled": false, "StdinOnce": false, "Cmd": ["/bin/sh", "-c", "#(nop) CMD [/bin/sh -c python -m SimpleHTTPServer 80]"], "WorkingDir": "", "AttachStdin": false, "Volumes": null, "MemorySwap": 0, "Tty": false, "CpuShares": 0, "Domainname": "", "Image": "befe1dfec828e8ff2c3c903c560b92a6a64658fbb7ab6bfc32af4b7cb2de1791", "ExposedPorts": {"80/tcp": {}}}, "architecture": "amd64", "docker_version": "1.0.0", "config": {"Env": [], "Hostname": "0e6756a12879", "Entrypoint": null, "PortSpecs": null, "Memory": 0, "OnBuild": [], "OpenStdin": false, "Cpuset": "", "User": "", "AttachStderr": false, "AttachStdout": false, "NetworkDisabled": false, "StdinOnce": false, "Cmd": ["/bin/sh", "-c", "python -m SimpleHTTPServer 80"], "WorkingDir": "", "AttachStdin": false, "Volumes": null, "MemorySwap": 0, "Tty": false, "CpuShares": 0, "Domainname": "", "Image": "befe1dfec828e8ff2c3c903c560b92a6a64658fbb7ab6bfc32af4b7cb2de1791", "ExposedPorts": {"80/tcp": {}}}, "id": "62cde782340a41b69a0ed2d3ce0853f362cde782340a41b69a0ed2d3ce0853f3", "Size": 0}
```

Note that there's 2 definitions in the image metadata: `config/Env` and `container_config/Env`. Internally, we use `config/Env` for `config:set`: https://github.com/deis/deis/blob/master/controller/registry/private.py#L40

I'm testing a small fix to see if updating it to container_config/Env drops the issue.


Resolving patch:
diff --git a/controller/registry/private.py b/controller/registry/private.py
--- a/controller/registry/private.py
+++ b/controller/registry/private.py
@@ -151,7 +151,7 @@ def _construct_env(env, config):
         if k in config:
             # update values defined by config
             v = config.pop(k)
-            new_env.append("{}={}".format(k, v))
+        new_env.append("{}={}".format(k, v))
     # add other config ENV items
     for k, v in config.items():
         new_env.append("{}={}".format(k, v))


Test patch: