python - 如何在某些事件中从容器向主机发送信号?

标签 python docker mariadb

我有一个 mariadb 在容器中运行。在“docker run”上,mariadb 运行导入脚本(来自数据库转储),它创建用户、构建架构等。

随着转储脚本大小的增加,执行导入的时间也会增加。此时大约需要 8-10 秒,但我预计数据量会大幅增加,并且导入时间将更难以预测。

我希望能够从容器向主机发送信号,让它知道数据已加载,并且数据库已准备好使用。到目前为止,我已经找到了有关如何将信号从一个容器发送到另一个容器的信息,但没有有关如何将信号从容器发送到主机的信息。另外,我需要能够以编程方式执行此操作,因为创建容器是更大管道的一部分。

理想情况下,我希望能够做这样的事情:

client = docker.from_env()
db_c = client.containers.run('my_db_image', ....)

# check for signal from db_c container
# do other things

谢谢!

最佳答案

据我所知,您无法将信号从容器发送到主机上运行的进程,但还有其他方法可以知道导入何时完成。我认为最简单的是以分离模式启动容器并等待特定行被记录。例如,以下脚本将等待直到记录 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 脚本中,对 FIFO 的读取调用会被阻止,直到管道中出现一些数据为止。 在容器中,导入脚本写入管道,通知程序数据已加载。 mysql 系统命令,\!在这种情况下,执行外部命令的命令可能会派上用场。您可以简单地添加到脚本末尾:

\! echo done > /tmp/apipe

以类似的方式,您可以使用 IPC 套接字(又名 Unix 套接字)或共享内存,但事情会变得更复杂一些。

另一种解决方案是向容器添加运行状况检查。可以通过检查容器来轮询主机上的健康状态。请参阅How to wait until docker start is finished?

编辑: 上述方法假设容器已初始化并接受连接。如果脚本作为初始化过程的一部分执行 ( Initializing a fresh instance )(此处似乎是这种情况),则导入完成时数据库尚未准备好并接受连接。为了初始化,服务器暂时启动 --skip_networking (仅允许本地客户端)并且只有在初始化完成后才会重新启动并可远程使用。

关于python - 如何在某些事件中从容器向主机发送信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58617288/

相关文章:

windows - Docker- 为什么 docker 更新主机文件?

debian 9 + odbc + mariadb : [01000] Can't open lib , 文件未找到

php - MySQL 无法选择在不同 session 中插入的行

python - 为什么对本地主机的 python 请求很慢?

python - Python 中的 OpenCV。获取网络摄像头流有效,但会打印错误消息

docker -/bin/sh :/root/start-docker. sh:在 docker 中执行命令时权限被拒绝

docker - 关于 Mesos Linux 容器和 Docker 的问题

php - 使用 canvasjs 的“实时”图表

python - pytransitions/transitions : Is there any better way to store the history of visited state?

python - 'print'在Python中的实现