Parameterized config files are a must to create customizable and flexible docker images. There are many tools available for doing the same. To name a few, consul-template, confd
But in this article I want to discuss about few of the basic approaches. So why basic ones? Well, when you can do the job with a knife, why use a gun!
Approach 1 - Using Bash Substituion
This uses shell parameter and file redirection. Consider we have a templated file
conf.txt
My name is $NAME or ${NAME} ?
Now we write a bash function to parse and output the parsed text to a destination file
$ parse_template_file(){
local FILE=$1
local OUT=$2
eval "cat <<EOF
$(cat $FILE)
EOF" > $OUT
}
$ NAME=TARUN parse_template_file conf.txt /dev/stdout
My name is TARUN or TARUN ?
$ NAME=TARUN parse_template_file conf.txt conf2.txt
$ cat conf2.txt
My name is TARUN or TARUN ?
This works in all environments as just uses the shell’s functionality. The two type of parameter you can use is the form of $NAME
or ${NAME}
Note: If you need to have a literal $NAME in your output then use \$NAME
Approach 2 - Using envsubst
envsubst
command can be used to parse environment variables passed in standard input and output the parsed values on standard output
So our new commands from previous example would now look like
$ NAME=TARUN envsubst < conf.txt
My name is TARUN or TARUN ?
$ NAME=TARUN envsubst < conf.txt > conf3.txt
$ cat conf3.txt
My name is TARUN or TARUN ?
envsubst
is not a shell command. It is provided by a gettext package
$ dpkg -S /usr/bin/envsubst
gettext-base: /usr/bin/envsubst
So this may not be available on all the docker images, you may need to install it
Approach 3 - Using perl
Approach #1 and #2 works great for most simpler use cases. But recently while templating our PHP project config, we had to rethink this. Earlier we used to escape each $
symbol by writing it as \$
.
Doing that in a PHP file of 500 odd lines is not a feasible approach. So we though of using an approach which only parses the 2nd format of the shell parameters which is ${NAME}
. And any $NAME
parameter is left as it is.
Most of the distributions have perl
by default, so we thought of using perl for this approach
Our parse_template_file
function would change as below
parse_template_file(){
local FILE=$1
local OUT=$2
cat $FILE | perl 2>/dev/null -pe 's/\$\{([_A-Z]+)\}/ $ENV{$1} /eg' > $OUT
}
The usage is similar to Approach #1
$ NAME=TARUN parse_template_file conf.txt /dev/stdout
My name is $NAME or TARUN ?
As you can see this would avoid parsing any variable in the PHP config.