Search code examples
dockerubuntu-16.04systemd

issues in accessing docker environment variables in systemd service files


1) I am running a docker container with following cmd (passing few env variables with -e option)

$ docker run --name=xyz -d -e CONTAINER_NAME=xyz -e SSH_PORT=22 -e NWMODE=HOST -e XDG_RUNTIME_DIR=/run/user/0 --net=host -v /mnt:/mnt -v /dev:/dev -v /etc/sysconfig/network-scripts:/etc/sysconfig/network-scripts -v /:/hostroot/ -v /etc/hostname:/etc/host_hostname -v /etc/localtime:/etc/localtime -v /var/run/docker.sock:/var/run/docker.sock --privileged=true cf3681e04bfb

2) After running the container as above, i check the env variable NWMODE inside the container, and it shows correctly as shown below :

$ docker exec -it xyz bash $ env | grep NWMODE NWMODE=HOST

3) Now, i created a sample service 'b' shown below which executes a script b.sh (where i try to access NWMODE) :

root@ubuntu16:/etc/systemd/system# cat b.service
[Unit]
Description=testing service b

[Service]
ExecStart=/bin/bash /etc/systemd/system/b.sh

root@ubuntu16:/etc/systemd/system# cat b.sh
#!/bin/bash`
systemctl import-environment
echo "NWMODE:" $NWMODE`

4) Now if i start service 'b' and see its logs, it shows that it is not able to access NWMODE env variable

$ systemctl start b
$ journalctl -fu b
...
systemd[1]: Started testing service b.
bash[641]: NWMODE:      //blank for $NWMODE here`

5) Now rather than having 'systemctl import-environment' in b.sh, if i do following then the b.service logs show the correct value of NWMODE env variable: $ systemctl import-environment $ systemctl start b

Though the step 5 above works i can't go for it, as all the services in my system will be started automatically by systemd. In that case, can anyone please let me know how can i access the environment variables (passed using 'docker run...' cmd above) in a service file (say for e.g. in b.sh above). Can this be achieved somehow with systemctl import-environment or there is some other way ?


Solution

  • systemd unsets all environment variables to provide a clean environment. Afaik that is intended to be a security feature.

    Workaround: Create a file /etc/systemd/system.conf.d/myenvironment.conf:

    [Manager]
    DefaultEnvironment=CONTAINER_NAME=xyz NWMODE=HOST XDG_RUNTIME_DIR=/run/user/0
    

    systemd will set the environment variables declared in this file.

    You can set up an ENTRYPOINT script that automatically creates this file before running systemd. Example:

    RUN echo '#! /bin/bash \n\
    echo "[Manager] \n\
    DefaultEnvironment=$(while read -r Line; do echo -n "$Line" ; done < <(env)) \n\
    " >/etc/systemd/system.conf.d/myenvironment.conf \n\
    exec /lib/systemd/systemd \n\
    ' >/usr/bin/setmyenv && chmod +x /usr/bin/setmyenv
    
    ENTRYPOINT /usr/bin/setmyenv
    

    Instead of creating the script within Dockerfile you can store it outside and add it with COPY:

    #! /bin/bash
    echo "[Manager]
    DefaultEnvironment=$(while read -r Line; do echo -n "$Line" ; done < <(env))
    " >/etc/systemd/system.conf.d/myenvironment.conf
    exec /lib/systemd/systemd