我正在尝试实现相当于:
docker exec -it <some_container> /bin/bash
即。在容器中运行命令,并将程序的
stdin
和 stdout
连接到命令的 stdin
和 stdout
。
我对文档的阅读似乎暗示以下内容应该可以完成这项工作:
import docker
client = docker.from_env()
container, = client.containers.list()
container.exec_run(['/usr/local/bin/bash'], stdin=True, tty=True)
(有一个容器正在运行
bash:latest
)
但是程序的
stdin
似乎并没有与 exec
'd 命令的连接起来。
命令行只是坐在那里,回显我的输入,但不会以任何方式对其做出反应。
我还尝试与原始套接字交互:
_, s = container.exec_run(['/usr/local/bin/bash'], stdin=True, tty=True, socket=True)
s.write('echo hello world')
但我越来越
UnsupportedOperation: File or stream is not writable.
问题:我需要做什么才能允许我的代码的用户与使用 docker-py 在容器中执行的命令的 std IO 进行交互?
exec_run的结果是一个socket.SocketIO对象。使用其套接字的recv()、sendall()。
例如
import docker
import threading
import queue
client = docker.from_env()
container = client.containers.get('YOUR CONTAINER NAME')
_, sock = container.exec_run(cmd='bash', stdin=True, socket=True)
ch = queue.Queue()
def read():
while res := sock._sock.recv(4096):
print(res[8:].decode())
def write():
while item := ch.get():
item = item + '\n'
item = bytes(item, 'utf-8')
sock._sock.sendall(item)
writer = threading.Thread(target=write)
writer.start()
reader = threading.Thread(target=read)
reader.start()
while cmd := input():
ch.put(cmd)
if cmd == 'exit':
break
sock._sock.close()
ch.put(None)
writer.join()
reader.join()