In the example at https://github.com/docker/docker-py , they return the results of a command to a docker image as so:
>>> client.containers.run("ubuntu:latest", "echo hello world")
'hello world\n'
What I want is to use a pipe - for instance, it would be great if I could do this:
>>> client.containers.run("ubuntu:latest", "echo hello world | wc")
' 1 2 12\n'
However, instead I get this:
>>> client.containers.run("ubuntu:latest", "echo hello world | wc")
b'hello world | wc\n'
What is the easiest way to run two commands, the second piped from the first, in docker?
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")
It is simply:
client.containers.run("ubuntu:latest", "sh -c 'echo hello world | wc'")
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.