Use sh -c command in docker run
Are these two commands same?
docker run python:3.6 cat /etc/*release*
docker run python:3.6 sh -c "cat /etc/*release*"
They are not. When I ran these two commands on a server which runs Alpine Linux v3.18, I got different outputs.
Notice that the first command gives us an error at the top saying “/etc/alpine-release” cannot be found.
However if you try to try to list /etc
in the docker, you can only find one file.
So where does this “/etc/alpine-release” comes from? It’s not hard to guess, isn’t it? It is from the host shell. Here is the proof:
Why does this happen? This is because when we run the first command, the glob
pattern is a part of the whole command and handled by the host shell. Therefore, the host shell interprets *release*
and passes two files to docker. As a result, on Alpine system, the first command is essentially docker run python:3.6 cat /etc/alpine-release /etc/os-release
. That is why cat complains it cannot find /etc/alpine-release
. Conversely, for the second command, the whole cat command together with the glob pattern is passed as a string and handled by sh
inside the container. That makes sure the glob pattern is interpreted inside the container, so it correctly only reads the file that exists in its /etc
directory.
Lesson learnt: consider wrapping the command to be executed inside container with sh -c"
, especially in case that the command relies on some sort of interpolations by shell.