Захват вывода 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 при выполнении этого.
Ответы
Ответ 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)
Ваш вывод кажется пустым, потому что ничего еще не зарегистрировано.