Использование трубок с docker-py - PullRequest
0 голосов
/ 29 октября 2019

В примере на https://github.com/docker/docker-py, они возвращают результаты команды в образ докера следующим образом:

>>> client.containers.run("ubuntu:latest", "echo hello world")
'hello world\n'

Я хочу использовать канал - например, он будетбыло бы здорово, если бы я мог сделать это:

>>> client.containers.run("ubuntu:latest", "echo hello world | wc")
'       1       2      12\n'

Однако вместо этого я получаю это:

 >>> client.containers.run("ubuntu:latest", "echo hello world | wc")
    b'hello world | wc\n'

Какой самый простой способ выполнить две команды, вторая по конвейеру от первой,в докере?

Ответы [ 2 ]

1 голос
/ 30 октября 2019

Это просто:

client.containers.run("ubuntu:latest", "sh -c 'echo hello world | wc'")
1 голос
/ 30 октября 2019

Всякий раз, когда вы используете такую ​​конструкцию оболочки, как $ENV_VAR, | и т. Д., Убедитесь, что у вас действительно есть оболочка для их интерпретации, иначе у них будут свои буквальные значения! Чтобы понять, почему в вашем вызове отсутствует оболочка, вы должны понимать докер ENTRYPOINT и CMD.

Если вы посмотрите на файл Docker для ubuntu: последняя , вы увидите, что это

FROM scratch

И файл не устанавливает ENTRYPOINT, только CMD. Прочитайте В чем разница между CMD и ENTRYPOINT в Dockerfile? , чтобы получить отличную информацию о разнице. Достаточно сказать, что в вашем случае все после имени изображения заменяет cmd.

Документ для containers.run() говорит, что command может быть str или list. Исходя из этого и из наблюдаемого поведения, мы можем сделать вывод, что командная строка будет разбита на пробелы, чтобы создать список аргументов для исполняющего устройства Docker.

Итак, ответ, короче говоря, заключается в том, что |конструкция оболочки, но вы не выполняете оболочку. Есть несколько способов добавить оболочку в уравнение. Наиболее очевидным является прямой запуск оболочки:

>>> client.containers.run("ubuntu:latest", "bash -c 'echo hello world | wc'",)
'      1       2      12\n'

Но вы также можете установить точку входа в оболочку, что обычно делается в контейнерах общего назначения (хотя обратите внимание, что вы все равно должны убедиться, что -c, и вся команда оболочки должна быть заключена в кавычки, как и раньше. Точка входа предоставляет только исполняемый файл, а не аргументы).

>>> client.containers.run("ubuntu:latest", "-c 'echo hello world | wc'", entrypoint="bash")
'      1       2      12\n'

Командная строка делает то же самое со стандартным разделителем полей ввода:

$ docker run --rm -it ubuntu:latest echo hello world \| wc
hello world | wc

Если мы заключаем в кавычки все это, мы побеждаем автоматическое разделение вокруг разделителя полей ввода:

$ 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.

Эквивалент Python:

>>> 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")
...