dockerenvironment-variablesapache-commonsapache-commons-config

Passing Variable "aaa.bbb" into a Docker Container Process


Update: the question initially assumed this issue was related to Apache Commons Config behavior. I have updated the question and title to narrow the focus of the question.

I am working with the following Apache commons config setup. This setup allows system properties and/or environment variables to override config file properties. I have a number of config file properties with values like "dspace.url".

When testing this application in Docker, it would be very convenient to override these values by passing an environment variable to the container.

Note that the period in the environment variable name is difficult to set from the command line. The following command fails.

export dspace.url=/some/path

However, the variable can be set with docker run.

docker run -e dspace.url=/some/path ...

If I connect to my Docker instance, I see that the environment variable is present.

docker exec myapp /bin/bash

From that shell the following command shows that the variable is set.

env |grep "dspace.url"

Here is the issue that I am encountering. When I attempt to override such a value in my larger application, the configuration loads most of my environment variables but it is not loading the environment variables that contain a period in their names.

I have attempted to isolate the problem by writing the following program. When I run this program as a standalone application, I am able to access environment variables such as "dspace.url". Most notably, System.getenv() returns those values.

public static void main(String[] args) {
    //builder.setFile(new File("config.xml"));
    try {
        DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder("config-definition.xml");
        Configuration config = builder.getConfiguration(true);
        for(Iterator<String> keys = config.getKeys(); keys.hasNext(); ) {
            System.out.println("TBTB1 "+keys.next());
        }

        System.out.println("");

        for(Iterator<String> keys=new EnvironmentConfiguration().getKeys(); keys.hasNext();) {
            System.out.println("TBTB2 "+keys.next());
        }

        System.out.println("");

        for(String s: System.getenv().keySet()) {
            System.out.println("TBTB3"+s);
        }

        System.out.println(config.getString("dspace.foo"));
        System.out.println(config.getString("dspace.name"));
    } catch (ConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

If I run this same code compiled within my larger application, I do not see the environment variables containing periods.

Can you think of any other differences to examine?


Solution

  • The default shell for an OS/Docker image determines if these variables can be exported into child processes.

    passing variables to the current shell

    When passing an environment variable with docker run, it is possible to pass an environment variable containing a period to the current shell.

    ubuntu

    winpty docker run --rm -it -e dspace.foo=ZZZZZ ubuntu env
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=0f34eac98005
    TERM=xterm
    dspace.foo=ZZZZZ
    HOME=/root
    

    alpine

    docker run --rm -it -e dspace.foo=ZZZZZ alpine env
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=2887c4ed82ce
    TERM=xterm
    dspace.foo=ZZZZZ
    HOME=/root
    

    accessing variable from a subprocess

    ubuntu - notice that the variable is not present

    Dockerfile
    FROM ubuntu
    CMD echo `env`
    
    Output
    docker run --rm -it -e dspace.foo=ZZZZZ myshell
    HOSTNAME=143368c4bdde HOME=/root TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/
    

    alpine - notice that the variable is present

    Dockerfile
    FROM alpine
    CMD echo `env`
    
    Output
    docker run --rm -it -e dspace.foo=ZZZZZ myshell
    HOSTNAME=323a8540cefa SHLVL=1 HOME=/root TERM=xterm dspace.foo=ZZZZZ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/