简体   繁体   English

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

[英]How do i send a signal FROM container TO host on some event?

I have a mariadb running in a container.我有一个 mariadb 在容器中运行。 On 'docker run', an import script (from a db dump) is run by mariadb, which creates users, builds schema, etc.在“docker run”上,导入脚本(来自 db 转储)由 mariadb 运行,它创建用户、构建模式等。

As the size of that dump script grows, the time to do the import increases.随着该转储脚本的大小增加,执行导入的时间也会增加。 At this point it's about 8-10 seconds, but i expect amount of data to increase substantially, and the import time will be more difficult to predict.此时大约需要 8-10 秒,但我预计数据量会大幅增加,并且导入时间将更难以预测。

I'd like to be able to send a signal from the container to the host, to let it know that the data has been loaded, and that db is ready to be used.我希望能够从容器向主机发送信号,让它知道数据已加载,并且数据库已准备好使用。 So far i have found info on how to send signal from one container to another container, but there's no information on how to send signal from container to the host.到目前为止,我已经找到了有关如何将信号从一个容器发送到另一个容器的信息,但是没有关于如何将信号从容器发送到主机的信息。 Also, i need to be able to do this programmatically, as creating container is part part of a larger pipeline.此外,我需要能够以编程方式执行此操作,因为创建容器是更大管道的一部分。

Ideally, i'd like to be able to do something like this:理想情况下,我希望能够做这样的事情:

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

# check for signal from db_c container
# do other things

Thank you!谢谢!

you can add this code to check if the db is ready to accept the connections:您可以添加此代码以检查数据库是否已准备好接受连接:

import MySQLdb
import time


db = MySQLdb.connect(host='MYHost', user='MYNAME', passwd='PASS', db='MYDB')

if not db:
    while True:
        db = MySQLdb.connect(host='MYHost', user='MYNAME', passwd='PASS', db='MYDB')
        if db:
            break
        print("Still waiting for the DB")
        time.sleep(10)

AFAIK you cannot send signals from the container to a process running on the host but there are other ways to know when the import has finished. AFAIK 您不能将信号从容器发送到主机上运行的进程,但是还有其他方法可以知道导入何时完成。 I think the easiest is to start the container in detached mode and wait until a specific line gets logged .我认为最简单的方法是以分离模式启动容器并等待特定行被记录 The following script for example waits until the line done is logged:例如,以下脚本会等待,直到记录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....')

If the output of the import script goes to stdout it could contain a simple print at the end:如果导入脚本的 output 进入stdout ,它可能在末尾包含一个简单的打印:

select 'The import has finished' AS '';

Wait for this string in the python script.在 python 脚本中等待此字符串。

Another approach is to use some other form of inter-process communication .另一种方法是使用其他形式的进程间通信 An example using named pipes:使用命名管道的示例:

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...")

The host shares the named pipe with the container.主机与容器共享名为 pipe。 In the python script the read call to the FIFO is blocked until some data is available in the pipe.在 python 脚本中,对 FIFO 的读取调用被阻塞,直到 pipe 中有一些数据可用。 In the container the import script writes to the pipe notifying the program that the data has been loaded.在容器中,导入脚本写入 pipe 通知程序数据已加载。 The mysql system command, \! mysql系统命令,\! command to execute an external command might come in handy in this situation.在这种情况下,执行外部命令的命令可能会派上用场。 You could simply add to the end of the script:您可以简单地添加到脚本的末尾:

\! echo done > /tmp/apipe

In a similar way you could use IPC sockets (aka Unix sockets) or shared memory but things get a bit more complicated.以类似的方式,您可以使用 IPC sockets(又名 Unix 套接字)或共享 memory,但事情会变得更复杂一些。

Yet another solution is to add a health-check to the container.另一个解决方案是向容器添加健康检查 The health status can be polled on the host by inspecting the container.可以通过检查容器在主机上轮询健康状态。 See How to wait until docker start is finished?请参阅如何等到docker start完成?

Edited: The above approaches assume the container is initialized and accepting connections.编辑:上述方法假设容器已初始化并接受连接。 If the script is executed as part of the initialization process ( Initializing a fresh instance ), which seems to be the case here, the database is not ready and accepting connections when the import completes.如果脚本作为初始化过程的一部分执行(初始化一个新实例),这似乎是这里的情况,导入完成时数据库还没有准备好并接受连接。 For the initialization the server is temporarily started with the --skip_networking (allowing only local clients) and only after the initialization completes it is restarted and becomes available remotely.对于初始化,服务器使用--skip_networking临时启动(仅允许本地客户端),只有在初始化完成后它才会重新启动并远程可用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM