Whenever you use a shell construct such as $ENV_VAR
, |
, etc, make sure you actually have a shell to interpret them or they'll have their literal values! To see why your invocation lacks a shell, you have to understand docker ENTRYPOINT
and CMD
.
If you look at the dockerfile for ubuntu:latest,you'll see that it is
FROM scratch
And the file doesn't set an ENTRYPOINT
, only a CMD
. Read What is the difference between CMD and ENTRYPOINT in a Dockerfile? for some good looking info about the difference. Suffice it to say that in your case everything after the image name replaces the cmd
.
The doc for containers.run()
says command
can be a str
or list
. From that, and from observed behavior, we can infer the command string will be split on whitespace to create a list of arguments for the docker exec.
So, the answer, in short, is because |
is a shell construct but you're executing no shell. There's a few ways to add a shell into the equation. The most obvious is to run the shell directly:
>>> client.containers.run("ubuntu:latest", "bash -c 'echo hello world | wc'",)
' 1 2 12\n'
But you could also set the entrypoint to a shell, which is commonly done in general purpose containers (though notice you still have to make sure that -c
is provided, and the entire shell command must be enquoted as before. The entrypoint only provides the executable, not any arguments).
>>> client.containers.run("ubuntu:latest", "-c 'echo hello world | wc'", entrypoint="bash")
' 1 2 12\n'
The command line does the same thing with the standard input field separator:
$ docker run --rm -it ubuntu:latest echo hello world \| wc
hello world | wc
If we enquote the whole thing we defeat the automatic splitting around the input field separator:
$ docker run --rm -it ubuntu:latest "echo hello world \| wc"
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"echo hello world \\\\| wc\": executable file not found in $PATH": unknown.
The python equivalent is:
>>> client.containers.run("ubuntu:latest",["echo hello world \\|"])
Traceback (most recent call last):
[... traceback omitted for brevity ...]
docker.errors.APIError: 500 Server Error: Internal Server Error ("OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"echo hello world \\\\|\": executable file not found in $PATH": unknown")