It is not just a macOS issue. You replied to an old question so I donât think @abdulwahabadi is still waiting for the answer, but for anyone else, everything after the name of the image in a docker run
command is an argument of the entrypoint defined for that image. ENTRYPOINT + aguments will be the final command. The ENTRYPOINT is optional and the base alpine image doesnât have it, so letâs forget about that for a moment.
The terminal where you execute a command on your host machine will be the first to interpret the command. Any special character that is not escaped (backslash) or surrounded by quotation marks or sometimes apostrophes will be interpreted by your host shell, not the container.
docker run --rm -it alpine echo $HOME
for example will echo the home of the user on the host machine, because the host shell interprets the variable and executes:
docker run --rm -it alpine echo /Users/username
The dollar sign is not the only special character. The *
character can be used as a wildcard character, and this is what happened here. If you run the following commands:
docke run --name wildcardtest alpine cat /etc/*release*
docker ps -a --no-trunc --filter name=funny_sinoussi --format '{{ .Command }}'
you will see that the container is failing on macOS with this command:
cat /etc/*release*
This is the entire command because the wildcard character was not interpreted by the host shell and there is no shell involved in the execution of cat in the container to understand *
.
Now what about Linux? On Linux /etc/os-release usually exists and on many systems ther eis even
/etc/lsb-release`. In that case the cat command would be interpreted on the host and the container actualyl runs
cat /etc/lsb-release /etc/os-release
Now lsb-release
is not something that you would find in most of the containers, so this command would partially fail. It would show warn about the missing lsb-release and show the content of the os-release file. Even os-release is not guaranteed to be in a container. So what if you are runing the following command on Linux:
docker run -it busybox cat /etc/*release*
It would fail, since busybox doesnât have any release file, but the host had one or two so you could get this:
cat: can't open '/etc/lsb-release': No such file or directory
cat: can't open '/etc/os-release': No such file or directory
So the right solution is exactly what @johanmulder suggested. And what happens is that by starting the command with /bin/sh
you are executing a shell. You could just pass the path of the shell and run the rest of the command interactively, but you can also use the -c
option of the shell which expects a string which will be executed by the shell itself, which understands the wildcard characters. This is why the following command with quoating only the argument of cat is not enough
docker run --rm -it alpine cat "/etc/*release*"
In this case the host shell could not interpret the wildcard character since it is quoated, but you still donât have a shell in the container.