How to escape a $-sign in a dockerfile? - docker

I am trying to write a dockerfile in which I add a few java-options to a script called envvars.
To achieve that I want to append a few text-lines to said file like so:
RUN echo "JAVA_OPTS=$JAVA_OPTS -Djavax.net.ssl.trustStore=${CERT_DIR}/${HOSTNAME}_truststore.jks" >> ${BIN_DIR}/envvars
RUN echo "JAVA_OPTS=$JAVA_OPTS -Djavax.net.ssl.trustStorePassword=${PWD_TRUSTSTORE}" >> ${BIN_DIR}/envvars
RUN echo "export JAVA_OPTS" >> ${BIN_DIR}/envvars
The issue here is, that I want the misc. placeholders ${varname} (those with curly braces) to be replaced during execution of the docker build command while the substring '$JAVA_OPTS' (i.e. those without braces) should be echoed and thus added to the envvars file verbatim, i.e. in the end the result in the /usr/local/apache2/bin/envvars file should read:
...
JAVA_OPTS=$JAVA_OPTS -Djavax.net.ssl.trustStore=/usr/local/apache2/cert/myserver_truststore.jks
JAVA_OPTS=$JAVA_OPTS -Djavax.net.ssl.trustStorePassword=my_secret
export JAVA_OPTS
How can one escape a $-sign from variable substitution in dockerfiles?
I found hints to use \$ or $$ but neither worked for me.
In case that matters (which I hope/expect not to): I am building the image using "Docker Desktop" on Windows 10 but I would expect the dockerfile to be agnostic of that.

first you need to add this # escape=` to your Dockerfile since \ is an escape charachter in the Dockerfile . then you can use \$ to escape the dollar sign in the RUN section
Example:
# escape=`
RUN echo "JAVA_OPTS=\$JAVA_OPTS -Djavax.net.ssl.trustStore=${CERT_DIR}/${HOSTNAME}_truststore.jks" >> ${BIN_DIR}/envvars
that will be JAVA_OPTS=$JAVA_OPTS in your env file

Related

How to setup completion of environment variable names in zsh?

In bash when I try to use autocompletion in double-quoted strings it works:
E.g.
echo "My home directory is $HO<t>"
# expands to
echo "My home directory is $HOME"
But when I try the same thing in zsh it just does nothing.
At the same time it works outside strings:
echo My\ home\ directory\ is\ $HO<t>
# expands to
echo My\ home\ directory\ is\ $HOME
Is it possible to make it work the same as bash?
Zsh completion has a bug where completion of parameter names fails if a partial parameter name is followed by a ".
As a workaround, just remove the final " from your string before pressing Tab. Then, Zsh's completion will work correctly and it will automatically add the final " for you.

How to pass environment variables to docker container app user [duplicate]

When I use any command with sudo the environment variables are not there. For example after setting HTTP_PROXY the command wget works fine without sudo. However if I type sudo wget it says it can't bypass the proxy setting.
First you need to export HTTP_PROXY. Second, you need to read man sudo, and look at the -E flag. This works:
$ export HTTP_PROXY=foof
$ sudo -E bash -c 'echo $HTTP_PROXY'
Here is the quote from the man page:
-E, --preserve-env
Indicates to the security policy that the user wishes to preserve their
existing environment variables. The security policy may return an error
if the user does not have permission to preserve the environment.
The trick is to add environment variables to sudoers file via sudo visudo command and add these lines:
Defaults env_keep += "ftp_proxy http_proxy https_proxy no_proxy"
taken from ArchLinux wiki.
For Ubuntu 14, you need to specify in separate lines as it returns the errors for multi-variable lines:
Defaults env_keep += "http_proxy"
Defaults env_keep += "https_proxy"
Defaults env_keep += "HTTP_PROXY"
Defaults env_keep += "HTTPS_PROXY"
For individual variables you want to make available on a one off basis you can make it part of the command.
sudo http_proxy=$http_proxy wget "http://stackoverflow.com"
You can also combine the two env_keep statements in Ahmed Aswani's answer into a single statement like this:
Defaults env_keep += "http_proxy https_proxy"
You should also consider specifying env_keep for only a single command like this:
Defaults!/bin/[your_command] env_keep += "http_proxy https_proxy"
A simple wrapper function (or in-line for loop)
I came up with a unique solution because:
sudo -E "$#" was leaking variables that was causing problems for my command
sudo VAR1="$VAR1" ... VAR42="$VAR42" "$#" was long and ugly in my case
demo.sh
#!/bin/bash
function sudo_exports(){
eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) "$#"
}
# create a test script to call as sudo
echo 'echo Forty-Two is $VAR42' > sudo_test.sh
chmod +x sudo_test.sh
export VAR42="The Answer to the Ultimate Question of Life, The Universe, and Everything."
export _EXPORTS="_EXPORTS VAR1 VAR2 VAR3 VAR4 VAR5 VAR6 VAR7 VAR8 VAR9 VAR10 VAR11 VAR12 VAR13 VAR14 VAR15 VAR16 VAR17 VAR18 VAR19 VAR20 VAR21 VAR22 VAR23 VAR24 VAR25 VAR26 VAR27 VAR28 VAR29 VAR30 VAR31 VAR32 VAR33 VAR34 VAR35 VAR36 VAR37 VAR38 VAR39 VAR40 VAR41 VAR42"
# clean function style
sudo_exports ./sudo_test.sh
# or just use the content of the function
eval sudo $(for x in $_EXPORTS; do printf '%q=%q ' "$x" "${!x}"; done;) ./sudo_test.sh
Result
$ ./demo.sh
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.
Forty-Two is The Answer to the Ultimate Question of Life, The Universe, and Everything.
How?
This is made possible by a feature of the bash builtin printf. The %q produces a shell quoted string. Unlike the parameter expansion in bash 4.4, this works in bash versions < 4.0
Add code snippets to /etc/sudoers.d
Don't know if this is available in all distros, but in Debian-based distros, there is a line at or near the tail of the /etc/sudoers file that includes the folder /etc/sudoers.d. Herein, one may add code "snippets" that modify sudo's configuration. Specifically, they allow control over all environment variables used in sudo.
As with /etc/sudoers, these "code snippets" should be edited using visudo. You can start by reading the README file, which is also a handy place for keeping any notes you care to make:
$ sudo visudo -f /etc/sudoers.d/README
# files for your snippets may be created/edited like so:
$ sudo visudo -f /etc/sudoers.d/20_mysnippets
Read the "Command Environment" section of 'man 5 sudoers'
Perhaps the most informative documentation on environment configuration in sudo is found in the Command environment section of man 5 sudoers. Here, we learn that a sudoers environment variables that are blocked by default may be "whitelisted" using the env_check or env_keep options; e.g.
Defaults env_keep += "http_proxy HTTP_PROXY"
Defaults env_keep += "https_proxy HTTPS_PROXY"
Defaults env_keep += "ftp_proxy FTP_PROXY"
And so, in the OP's case, we may "pass" the sudoer's environment variables as follows:
$ sudo visudo -f /etc/sudoers.d/10_myenvwlist
# opens the default editor for entry of the following lines:
Defaults env_keep += "http_proxy HTTP_PROXY"
Defaults env_keep += "https_proxy HTTPS_PROXY"
# and any others deemed useful/necessary
# Save the file, close the editor, and you are done!
Get your bearings from '# sudo -V'
The OP presumably discovered the missing environment variable in sudo by trial-and-error. However, it is possible to be proactive: A listing of all environment variables, and their allowed or denied status is available (and unique to each host) from the root prompt as follows:
# sudo -V
...
Environment variables to check for safety:
...
Environment variables to remove:
...
Environment variables to preserve:
...
Note that once an environment variable is "whitelisted" as above, it will appear in subsequent listings of sudo -V under the "preserve" listing.
If you have the need to keep the environment variables in a script you can put your command in a here document like this. Especially if you have lots of variables to set things look tidy this way.
# prepare a script e.g. for running maven
runmaven=/tmp/runmaven$$
# create the script with a here document
cat << EOF > $runmaven
#!/bin/bash
# run the maven clean with environment variables set
export ANT_HOME=/usr/share/ant
export MAKEFLAGS=-j4
mvn clean install
EOF
# make the script executable
chmod +x $runmaven
# run it
sudo $runmaven
# remove it or comment out to keep
rm $runmaven

Clean composer output from non readable characters in Jenkins' console output page

I have a Jenkins job to tweak, but no administration right on Jenkins itself.
I'd like to clean composer output from non readable characters, e.g:
the command is composer update --no-progress --ansi which outputs
in Jenkins'console.
I didn't exactly get the the reason why Jenkins cannot output some characters correctly.
As per https://medium.com/pacroy/how-to-fix-jenkins-console-log-encoding-issue-on-windows-a1f4b26e0db4, I perhaps could have tried to specify -Dfile.encoding=UTF8 for java, but as I said I don't have rights for Jenkins administration.
How could I get rid of these 'squares' characters ?
By pasting output lines into Notepad++, i noticed that these characters were backspaces. Hereafter how I've managed to embellish the output for Jenkins console :
# run the command, redirect the output into composer.out file
bin/composer.sh update --no-progress --ansi >composer.out 2>&1
# getting rid of backspaces
composer_out=$(cat composer.out | tr -d '\b')
# adding line feeds instead of numerous spaces
composer_out=$(echo "$composer_out" | sed -r 's/\)\s*(\w+)/\)\n\1/g')
echo "$composer_out"

Error when trying to use variables in the post build event with delphi 10.2

I use windows 7 pro service pack 1.
I have the following code in the post build event :
SET VAR1=BLABLA
ECHO %VAR1% > Test.txt
It wont work. In the file, i get «command echo activated» (translated from french).
Embarcadero documentation says that i can use any valid dos command in those events.
If i just use :
ECHO BLABLA > Test.txt
It works, no problem. Is this a bug or there is a problem with % character ? % is an ascii char so i dont even know what could be the problem.
ty for your help.
% is used in cmd to delimit variablenames when the value of the variable is required, hence echo %var1% > test.txt will write the current value of the environment variable var1 to the file.
If var1 is not defined at the time, it will report the echo status (Echo is on/off`.
This can be circumvented by using echo(%var1% - the ( modifies echo's behaviour to not report the echo status if the arguments are resolved to nothing.
If you want to echo a literal % then you need to escape the % with another %. cmd normally uses ^ to escape symbols with a special meaning - % is the exception; %% to echo a literal %.
BTW - the space between the string to be echoed and the redirector will be output to the file. To prevent this, use > test.txt echo %var1% Note that > creates a file anew. >> will create or append if the file already exists. The space between the redirector and the filename is optional.
However, it's important when using batch to post exactly the code that's in use.
SET VAR1=BLABLA
ECHO %VAR1% > Test.txt
will work happily.
SET VAR1 = BLABLA
ECHO %VAR1% > Test.txt
will not because this latter code sets a variable named "var1Space"
On my 10.2.1 system, I've tried the code as published.
The actual code that's executed is
SET VAR1=BLABLA&ECHO %VAR1% > Test.txt
not
SET VAR1=BLABLA
ECHO %VAR1% > Test.txt
as shown in the "Build events commands" window.
This will not work because the entire line is executed as published on the "build events" page - SET VAR1=BLABLA&ECHO %VAR1% > Test.txt which will be interpreted by cmd after cmd performs its standard parsing routine.
cmd replaces any %var% with the actual value at parse time, not at run time hence as var1 has no value when the line SET VAR1=BLABLA&ECHO %VAR1% > Test.txt is parsed, the code is executed as SET VAR1=BLABLA&ECHO > Test.txt hence the problem encountered.
To cure this, you need to use
SET VAR1=BLABLA&call ECHO %%VAR1%% > Test.txt
where cmd will execute the parsed-ECHO command in a subshell. % is the escape character for % so the subshell executes ECHO %VAR1% > Test.txt after var1 has been set.
I'd suggest you raise this as a problem with EMBT. Batch commands cannot be strung together with & without side-effects. The code entered into the "Build events commands" window should be executed without reformatting - just written to a (temporary) batch file and the batch file then executed.
No doubt the eager downvoters will support the resolution of this problem.

Capturing Dockerfile variable in file

in a Dockerfile I'm trying to capture a build arg variable inside a file with no luck.
Now I'm doing something such as:
RUN echo '\n\
enableSemantics( "$DOMAIN_NAME" );\n\
include_once "$IP/LocalSettings.local.php"; ' >> /var/www/w/LocalSettings.php
and I would like to replace $DOMAIN_NAME with DOMAIN_NAME build ARG (but not $IP, which is not...)
What should I change?
Try inverting the quotes :
ARG DOMAIN_NAME
RUN echo "\n\
enableSemantics( '$DOMAIN_NAME' );\n\
include_once '$IP/LocalSettings.local.php'; " >> /var/www/w/LocalSettings.php
I don't know the exact reason , why this works , but most probably , its how Docker resolves the variables , i.e it ignores variables between double quotes.
Also you can skip the $ in this way : \$

Resources