Error executing command with docker run

Hello!

I am having an issue executing this command docker run alpine cat /etc/*release* on my macOS 10.13.1.

I get a response of zsh: no matches found: /etc/*release*

When I use online playgrounds like katacoda to try the command, it works fine.

What could be wrong on my side please?

any help please? I have done so much googling to no success.

When you run that command, zsh tries to expand /etc/*release* itself instead of passing it to the command to be executed in docker. So it actually tries to look up /etc/*release* in your local MacOS installation and fails to find it, leading to that error message.
What you should actually do is run:

docker run alpine /bin/sh -c "cat /etc/*release*"
1 Like

Thank you Johan.

This explains it, however, alpine uses ash for its bash so the updated command that worked is

docker run alpine /bin/ash -c “cat /etc/*release*”

No, it doesn’t :wink:

% docker run -it --rm alpine
/ # ls -l /bin/sh /bin/ash
lrwxrwxrwx    1 root     root            12 Jan 16 21:52 /bin/ash -> /bin/busybox
lrwxrwxrwx    1 root     root            12 Jan 16 21:52 /bin/sh -> /bin/busybox

Glad I could be of help.

I actually arrived here after googling the issue. Thanks. I’m trying to make sense of this command by checking the documentation. It’s not the easiest to make sense of. Any chance you can explain what the command is actually doing?

Thanks either way!

I’m not sure if it will answer your question but let me share something with you: from the below, I can conclude that even if the cat command is executed in a contained the local presence of the same filename and path is required. It probably is a MacOS-only issue.

sh-3.2# docker run ubuntu cat /etc/*release* 
cat: '/etc/*release*': No such file or directory
sh-3.2# echo "Fake release" > /etc/os-release 
sh-3.2# docker run ubuntu cat /etc/*release* 
PRETTY_NAME="Ubuntu 22.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.1 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

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.