Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Literal "\n" in Dockerfile ENV instruction: is this literally impossible to achieve?

Tags:

docker

My ENV variable in the Dockerfile requires a newline sequence (\n). Using the ENV instruction, it seems impossible to achieve this.

I've tried all possible combinations, I think:

# Dockerfile

ENV FOO @static {\n path_regexp \\n}  # @static {n path_regexp \\n}
ENV BAR='@static {\n path_regexp \n}' # @static {\\n path_regexp \\n}
ENV BAZ="@static {\n path_regexp \n}" # @static {\\n path_regexp \\n}

\n is always prepended with a backslash. Is this a "feature"? How can I make my ENV respect the newline sequence?

Putting the variabile directly in Compose file will output the variabile correctly.

like image 807
gremo Avatar asked Dec 02 '25 19:12

gremo


2 Answers

Docker doesn't replace escaped characters in the ENV statement.

You can replace them at runtime by echoing them into new variables as this shows

FROM debian
ENV foo="Hello\nWorld!"
CMD bar=$(echo ${foo}) && echo ${#foo} && echo ${#bar}

It prints 13 and 12 showing that foo is 13 characters long and bar is 12 long, so \n has been replaced with a newline.

like image 64
Hans Kilian Avatar answered Dec 04 '25 08:12

Hans Kilian


I don't believe you can do this with only a Dockerfile. The parsing on the ENV step is very minimal. However, you can define the variable outside of the build, and pass it in as a build arg:

$ cat df.env
from alpine

arg hello
env hello=${hello}
cmd env

$ hello="hello
> world"

$ docker build -t test-env -f df.env --build-arg "hello=$hello" .
[+] Building 0.2s (5/5) FINISHED                                                          docker:default
 => [internal] load build definition from df.env                                                   0.0s
 => => transferring dockerfile: 84B                                                                 0.0s
 => WARN: JSONArgsRecommended: JSON arguments recommended for cmd to prevent unintended behavior r  0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                    0.0s
 => [internal] load .dockerignore                                                                   0.0s
 => => transferring context: 49B                                                                    0.0s
 => CACHED [1/1] FROM docker.io/library/alpine:latest                                               0.0s
 => exporting to image                                                                              0.0s
 => => exporting layers                                                                             0.0s
 => => writing image sha256:11ff645049d1b266b68f2b0fe1da19ef0daccaf103bbafc2030b10d58eb0d6b6        0.0s
 => => naming to docker.io/library/test-env                                                         0.0s

 1 warning found (use docker --debug to expand):
 - JSONArgsRecommended: JSON arguments recommended for cmd to prevent unintended behavior related to OS signals (line 5)

$ docker run --rm test-env
HOSTNAME=af8f8744374d
SHLVL=1
HOME=/root
hello=hello
world
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

Another option to do this is to expand the variable inside of an entrypoint script, in this case using printf. This will only apply to child processes of the entrypoint, so a docker exec would see the unexpanded variable:

from alpine

env hello=hello\\nworld

copy --chmod=755 <<-"EOT" /entrypoint.sh
#!/bin/sh
export hello="$(printf "$hello")"
if [ $# = 0 ]; then
  set -- /bin/sh
fi
exec "$@"
EOT

entrypoint [ "/entrypoint.sh" ]
cmd env
like image 25
BMitch Avatar answered Dec 04 '25 09:12

BMitch