CMD bash echo ENV interpretered and enclosed in double quotes?

After 3 days I’m still stuck with this ENV echoing problem.


As shown in the image, I tested it twice by build and run then re-build and re-run.
What I wanted: ENV variable interpretered and enclosed in double quotes, like:

abc
"abc"

Could anybody please give me a hand?

You need to fix this problem first: “/bin/sh: [/bin/bash, : not found”? Just because the image has -bash in the name, doesn’t mean bash will be available as /bin/bash.

You might want to inspect your build image and check wether the variable was not substituted while building the image:
docker image inspect ${image} --format '{{.Config.Cmd}}'

Something worth trying: In compose files a $ character can be escaped with another $ character, so ${MYVAR} would become $${MYVAR}. You could try if it applies to variables declared in a Dockerfile as well.

Update: I realize I hadn’t finished the first sentence. Completed now.

1 Like

Thank you so much for taking time.
“/bin/sh: [/bin/bash, : not found”… this is where I did not understand, my first test and second test used the same base image, so the first test has proved bash is good? and I used bash but how sh popped up?
Anyway, now I change base image to ubuntu and test again following your instruction:

FROM ubuntu
CMD ["/bin/bash", "-c", "   echo ${MYVAR} && echo \"${MYVAR}\"   "]
docker image inspect testenv --format '{{.Config.Cmd}}'
[/bin/bash -c    echo ${MYVAR} && echo "${MYVAR}"   ]

which proved ok with bin/bash part (but double quote did not print out ). Then:

FROM ubuntu
CMD ["/bin/bash", "-c", "   echo '"'   "]
docker image inspect testenv --format '{{.Config.Cmd}}'
[/bin/sh -c ["/bin/bash", "-c", "   echo '"'   "]]

So, my problem is about single quote or double quote causing shell mal-function? I probably used wrong title for this topic.
I tried some methods like \x22, nothing worked till now.
And, in Linux echo \""abc\"" will print out "abc", but put that inside CMD bin/bash, I will see /bin/sh: 1: [/bin/bash,: not found…so weird.

If you use the non-array syntax, docker will prefix the string in CMD with /bin/sh -c as you can see below the Dockerfile:

FROM ubuntu
CMD echo ${MYVAR} && echo "${MYVAR}"

Resulting .Config.Cmd:

            "Cmd": [
                "/bin/sh",
                "-c",
                "echo ${MYVAR} && echo \"${MYVAR}\""
            ],

If you modily the .Config.Cmd created by the Dockerfile above to use /bin/bash instead of /bin/sh, your Dockerfile will look like this:

FROM ubuntu
CMD ["/bin/bash","-c", "echo ${MYVAR} && echo \"${MYVAR}\""]

I am not sure what you try to archive, but may I suggest to take a look at ENTRYPOINT and make yourself acquainted with the idea of writting an entrypoint script instead? Typicaly entrypoint scripts do the required preparation work, like rendering config files based on the env values, and then start the main process.

1 Like

I read some articles then tried my first entrypoint.sh, it didn’t work out, too much errors.
However, I finally find my solution (and this example is kind of what I want to achieve - I can input all variables in --ENV, then a config file will be created inside container):

FROM ubuntu
CMD ["/bin/bash", "-c", "   dq='\"' && echo { >> /etc/example.conf && echo ${dq}listen${dq}:${dq}:${MV} ${dq},>> /etc/example.conf && echo }>> /etc/example.conf && cat /etc/example.conf   "]
root@606672145hax:~/testenv# docker run --rm -it -e MV='1080' testenv
{
"listen":":1080 ",
}

After reading so much stackoverflow Q&A, I still don’t know exactly what is causing those problems, I just avoid using single quote when double quote needs to be printed out within echo.

Many thanks! Appreciate it.

Single quotes in bash/sh will prevent variable interpolation and result in variables beeing printed literaly.

Your last Dockerfile indeed looks like something that should be done in an entrypoint script, which can be a bash script itself. You can use variables passed-in with -e directly in the entrypoint script.

1 Like
FROM ubuntu
CMD ["/bin/bash", "-c", "   echo { >> /etc/example.conf && echo '\"'listen'\"':'\"':${MV} '\"',>> /etc/example.conf && echo }>> /etc/example.conf && cat /etc/example.conf   "]

This works, too.

Oh, that’s why the variable does not expand. But other times they cause errors…

Please take a look:

#!/bin/bash
set -e
cat <<-EOF > /config.json
{
  "listen": ":$MV", 
}
EOF
exec "$@"
FROM ubuntu
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
root@606672145hax:~/testenv# docker run --rm -it -e MV='1080' testenv
standard_init_linux.go:228: exec user process caused: no such file or directory

looks good to me, except a chmod +x /entrypoint.sh is missing. If +x is set in the host folder, it will be retained, but I would still advice to explicitly set chmod +x /entrypoint.sh in a RUN block of the Dockerfile.

1 Like

Thanks. I still got this error with RUN chmod added.

Well that’s odd.

if I create the entrypoint.sh with the content you provided and use this Dockerfile it works as it should:

FROM ubuntu
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

Build it: docker build -t test:1.0 .
run it:

me@node:~/test$ docker run -ti --rm -e MV=random-value test:1.0 cat config.json
{
  "listen": ":random-value",
}

It also works if the command is defined in the Dockerfile, instead of beeing passed als container argument:

FROM ubuntu
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD [ "cat", "/config.json" ]

docker run -ti --rm -e MV=random-value test:1.0

Note: CMD will become the argument for ENTRYPOINT. Since your declared exec "$@" at the end of your entrypoint script, it will be responsible to execute whatever is declared as CMD.

Thus said, I have no idea why it’s not working for you.

1 Like

I figured it out!
This error I saw is: standard_init_linux.go:228: exec user process caused: no such file or directory
I’m testing all this docker thing in VPS. And I’m using a SSH terminal to control, which is powerful and allows me to edit file with my assigned “default editor” in Windows - my editor choice is Emeditor.
So, in Emeditor, after I changed from “CR+LF” to “LF ONLY” when saving entrypoint.sh, bug is gone!
I don’t know if this is related to entire entrypoint.sh file or just the cat <<-EOF > /config.json ....... part.

One last question please: I don’t know why “COPY entrypoint.sh /entrypoint.sh” is necessary, I see error without it. ---- is not that dot at the end of “docker build” command saying: copy all files (entrypoint.sh in my example) inside Dockerfiles’s folder into root folder in the image?

The . means the current folder is the build context. The build context != image.

Depending wether you use buildkit or not, the behavior changes. With buildkit only files declared as COPY/ADD will be copied into the build context, without buildkit everything will be copied (except files listed in .dockerignore file). You still need to COPY/ADD files from the build context to the image.

1 Like

Thank you so much, I appreciate all your help.