moby: ENV directive that sets PATH for a USER other than the final user does not properly set other user's PATH
I have a container which starts as root, but one of the applications that’s running (under the supervisor) runs as a different user. I want to specify that user’s PATH in the Dockerfile. I tried to do this with ENV, but it only affects the user the container is run as (root).
Switching back to root at the end and exporting galaxy user’s environment:
# start as root
USER galaxy
# set PATH to include linuxbrew and also WINEPREFIX and WINEARCH
ENV PATH=$PATH:/home/galaxy/.linuxbrew/bin WINEPREFIX=$HOME/.wine32 WINEARCH=win32
USER root
CMD su galaxy -c export | egrep " PATH=|WINEPREFIX="
produces:
export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/galaxy/.linuxbrew/bin'
export WINEPREFIX='/home/galaxy/.wine32'
Switching back to root at the end and exporting galaxy user’s environment (using login shell):
# start as root
USER galaxy
# set PATH to include linuxbrew and also WINEPREFIX and WINEARCH
ENV PATH=$PATH:/home/galaxy/.linuxbrew/bin WINEPREFIX=$HOME/.wine32 WINEARCH=win32
USER root
CMD su - galaxy -c export | egrep " PATH=|WINEPREFIX="
produces:
export PATH='/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games'
Not switching back to root at the end exporting the environment:
# start as root
USER galaxy
# set PATH to include linuxbrew and also WINEPREFIX and WINEARCH
ENV PATH=$PATH:/home/galaxy/.linuxbrew/bin WINEPREFIX=$HOME/.wine32 WINEARCH=win32
# stay as user galaxy
CMD export | egrep " PATH=|WINEPREFIX="
produces:
export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games'
export WINEPREFIX='/home/galaxy/.wine32'
Not only is linuxbrew missing from PATH, but where do the games come from?!
vagrant@vagrant-ubuntu-trusty-64:~$ docker version
Client version: 1.7.1
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 786b29d
OS/Arch (client): linux/amd64
Server version: 1.7.1
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 786b29d
OS/Arch (server): linux/amd64
vagrant@vagrant-ubuntu-trusty-64:~$ docker info
Containers: 4
Images: 117
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 125
Dirperm1 Supported: false
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 3.13.0-55-generic
Operating System: Ubuntu 14.04.2 LTS
CPUs: 4
Total Memory: 3.86 GiB
Name: vagrant-ubuntu-trusty-64
ID: SXPR:67AC:PQZ2:OCEN:OUXM:SGX5:7NG3:XB2Z:QCTJ:IBMB:6TIZ:7QOL
WARNING: No swap limit support
vagrant@vagrant-ubuntu-trusty-64:~$ uname -a
Linux vagrant-ubuntu-trusty-64 3.13.0-55-generic #92-Ubuntu SMP Sun Jun 14 18:32:20 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 16 (9 by maintainers)
Thats not quite how
USER
andENV
work in Dockerfiles. UsingUSER
does not switch into a another scoped context but just specifies that next time a process is ran inside a container it runs as this user.The difference in your example comes from using the
su -
option that simulates user login and clears environment variables. If you want to make changes to the env list that is loaded on login try updating/home/username/.profile
.RUN echo “PATH="${PATH}"” >> /etc/environment
It has to do with how Dockerfiles treat the USER and ENV directives. It is not abundantly clear from reading the docs that ENV’s only effect is to change the export section of the example you just gave, and USER’s only effect is to change the someuser (without the ‘-’) for that section of the Dockerfile. A reasonable intuition of how the USER directive ought to work is that ENV directives made while that user is set apply to that USER and persist when logging into that user no matter what the context. So changing to that user in a running container and not seeing those variables (even when resetting the environment to the user’s default) could be surprising and confusing, as it was to me.
This has nothing to do with docker though. This is how the
su
utility works (when provided with-
,-l
, or--login
).If you were on a non docker system, and you performed the following:
The
FOO
variable would be lost when switching to the new user.OK, so something like this should be in the docs, if I understand correctly:
At build time, the ENV directive sets environment variables for whatever user a command is run under. At run time, the ENV directive sets the environment for the user that the container is run as. Changing user once the container is running may not preserve the environment (e.g. 'su - <user>').