Захват вывода скрипта Python, запускаемого внутри контейнера Docker
Цель здесь состоит в том, чтобы использовать контейнер Docker в качестве безопасной изолированной программной среды для запуска ненадежных сценариев Python, но делать это изнутри Python с помощью модуля docker-py и иметь возможность захватывать выходные данные этого сценария.
Я запускаю скрипт python foo.py внутри контейнера докера (он установлен как ENTRYPOINT
в моем Dockerfile, поэтому она выполняется сразу после запуска контейнера), и я не могу зафиксировать вывод этого скрипта. Когда я запускаю контейнер через обычный интерфейс командной строки, используя
docker run -v /host_dirpath:/cont_dirpath my_image
(host_dirpath
это каталог, содержащий foo.py) Я получаю ожидаемый вывод foo.py, распечатанный в stdout, который является просто словарем пар ключ-значение. Тем не менее, я пытаюсь сделать это из Python с помощью модуля docker-py, и каким-то образом вывод сценария не фиксируется 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))
Что просто приводит к "Docker logs: " - в логах ничего не записывается, ни stdout, ни stderr (я попытался вызвать исключение внутри foo.py, чтобы проверить это).
Результаты, которые я получаю, рассчитываются с помощью foo.py и в настоящее время просто выводятся на стандартный вывод с питоном. print
заявление. Как я могу включить это в журналы Docker-контейнеров, чтобы я мог читать это из Python? Или захватить этот вывод каким-то другим способом извне контейнера?
Любая помощь будет принята с благодарностью. Заранее спасибо!
РЕДАКТИРОВАТЬ:
Все еще не повезло с docker-py, но он работает хорошо при запуске контейнера с обычным CLI с использованием subprocess.Popen - вывод действительно правильно захватывается stdout при этом.
2 ответа
Вы испытываете это поведение, потому что Python буферизует свои выходные данные по умолчанию.
Возьмите этот пример:
vagrant@docker:/vagrant/tmp$ cat foo.py
#!/usr/bin/python
from time import sleep
while True:
print "f00"
sleep(1)
тогда просмотр журналов контейнера, работающего как демон, ничего не показывает:
vagrant@docker:/vagrant/tmp$ docker logs -f $(docker run -d -v $(pwd):/app dockerfile/python python /app/foo.py)
но если вы отключите буферизованный вывод Python с помощью -u
параметр командной строки, все отображается:
vagrant@docker:/vagrant/tmp$ docker logs -f $(docker run -d -v $(pwd):/app dockerfile/python python -u /app/foo.py)
f00
f00
f00
f00
Вы также можете ввести PYTHONUNBUFFERED
переменная окружения:
vagrant@docker:/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
параметр.
Вы можете испытать состояние гонки, поскольку запущенный контейнер работает параллельно с вашей управляющей программой. Вам нужно подождать, пока ваш контейнер запустится и закончится, прежде чем захватывать логи. Добавьте docker.wait к вашему коду сразу после docker.start.
docker.wait(contid)
Ваш вывод кажется пустым, потому что ничего еще не было зарегистрировано.