Подтвердить что ты не робот

Захват вывода python script выполняется внутри контейнера докеров

Целью здесь является использование контейнера docker в качестве защищенной изолированной программы для запуска ненадежных скриптов python, но сделать это изнутри python с помощью модуля docker-py и иметь возможность фиксировать вывод этого script.

Я запускаю python script foo.py внутри контейнера докеров (он устанавливается как команда ENTRYPOINT в моем файле Docker, поэтому он выполняется, как только выполняется контейнер), и я не могу захватить вывод из этого script. Когда я запускаю контейнер через обычный CLI, используя

docker run -v /host_dirpath:/cont_dirpath my_image

(host_dirpath - каталог, содержащий foo.py) Я получаю ожидаемый вывод foo.py, напечатанный в stdout, который является просто словарем пар ключ-значение. Тем не менее, я пытаюсь сделать это изнутри python с помощью модуля docker-py, и каким-то образом вывод script не выполняется методом logs. Вот код python, который я использую:

from docker import Client

docker = Client(base_url='unix://var/run/docker.sock',
              version='1.10',
              timeout=10)

contid = docker.create_container('my_image', volumes={"/cont_dirpath":""})
docker.start(contid, binds={"/host_dirpath": {"bind": "/cont_dirpath"} })

print "Docker logs: " + str(docker.logs(contid))

Что только приводит к "журналам докеров": ничего не записывается в журналы, ни stdout, ни stderr (я попытался создать исключение внутри foo.py, чтобы проверить это).

Результаты, которые я получил после, вычисляются foo.py и в настоящее время просто печатаются в stdout с помощью инструкции python print. Как я могу заставить это быть включенным в журналы контейнеров докеров, чтобы я мог прочитать его из python? Или захватить этот выход каким-то другим способом извне контейнера?

Любая помощь будет принята с благодарностью. Спасибо заранее!

ИЗМЕНИТЬ:

По-прежнему не повезло с docker-py, но он хорошо работает при запуске контейнера с обычным CLI, используя subprocess.Popen - вывод действительно правильно захвачен stdout при выполнении этого.

4b9b3361

Ответ 1

Вы испытываете такое поведение, потому что python по умолчанию выполняет буферизацию своих выходов.

Возьмем этот пример:

[email protected]:/vagrant/tmp$ cat foo.py
#!/usr/bin/python
from time import sleep

while True:
    print "f00"
    sleep(1)

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

[email protected]:/vagrant/tmp$ docker logs -f $(docker run -d -v $(pwd):/app dockerfile/python python /app/foo.py)

но если вы отключите буферизованный вывод python с параметром командной строки -u, все будет отображаться:

[email protected]:/vagrant/tmp$ docker logs -f $(docker run -d -v $(pwd):/app dockerfile/python python -u /app/foo.py)
f00
f00
f00
f00

Вы также можете ввести переменную среды PYTHONUNBUFFERED:

[email protected]:/vagrant/tmp$ docker logs -f $(docker run -d -v $(pwd):/app -e PYTHONUNBUFFERED=0 dockerfile/python python /app/foo.py)
f00
f00
f00
f00

Обратите внимание, что это поведение влияет только на контейнеры, работающие без параметров -t или --tty.

Ответ 2

У вас может возникнуть условие гонки, так как запущенный контейнер работает параллельно с вашей программой управления. Вам нужно дождаться, когда ваш контейнер начнется и закончен, прежде чем захватить журналы. Добавьте docker.wait в свой код сразу после docker.start.

docker.wait(contid)

Ваш вывод кажется пустым, потому что ничего еще не зарегистрировано.