AFAIK: вы не можете отправлять сигналы из контейнера процессу, запущенному на хосте, но есть и другие способы узнать, когда импорт завершен. Я думаю, что проще всего запустить контейнер в отдельном режиме и дождаться, пока определенная строка не войдет в систему . Следующий скрипт, например, ожидает, пока не будет зарегистрирована строка done
:
import os
import docker
client = docker.from_env()
container = client.containers.run('ubuntu:latest', 'bash -c "for i in {1..10}; do sleep 1; echo working; done; echo done"', detach=True)
print('container started')
for line in container.logs(stream=True):
print line.strip()
if line.strip() == 'done':
break
print('continue....')
Если вывод скрипта импорта переходит к stdout
, он может содержать простую печать в конце:
select 'The import has finished' AS '';
Дождитесь этой строки в скрипте Python.
Другой подход заключается в использовании некоторой другой формы межпроцессного взаимодействия . Пример использования именованных каналов:
import os
import docker
import errno
client = docker.from_env()
FIFO = '/tmp/apipe'
# create the pipe
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
# start the container sharing the pipe
container = client.containers.run('ubuntu:latest', 'bash -c "sleep 5; echo done > /tmp/apipe"', volumes={FIFO: {'bind': FIFO, 'mode': 'rw'}}, detach=True)
print("container started")
with open(FIFO) as fifo:
print("FIFO opened")
while True:
data = fifo.read()
if len(data) == 0:
print("Writer closed")
break
print('Read: "{0}"'.format(data))
print("continue...")
Хост совместно использует именованный канал с контейнером. В скрипте python вызов read для FIFO блокируется до тех пор, пока некоторые данные не будут доступны в конвейере. В контейнере скрипт импорта пишет в канал, уведомляя программу о загрузке данных. Системная команда mysql , \! команда для выполнения внешней команды может пригодиться в этой ситуации. Вы можете просто добавить в конец сценария:
\! echo done > /tmp/apipe
Аналогичным образом вы можете использовать сокеты IPC (так называемые сокеты Unix) или разделяемую память, но все становится немного сложнее.
Еще одно решение - добавить проверку здоровья в контейнер. Состояние работоспособности может быть опрошено на хосте путем проверки контейнера. См. Как дождаться окончания docker start
?
Отредактировано: Приведенные выше подходы предполагают, что контейнер инициализирован и принимает соединения. Если сценарий выполняется как часть процесса инициализации ( Инициализация свежего экземпляра ), что, как кажется, имеет место здесь, база данных не готова и принимает подключения после завершения импорта. Для инициализации сервер временно запускается с --skip_networking
(разрешены только локальные клиенты) и только после завершения инициализации он перезапускается и становится доступным удаленно.