如何通过Python脚本向Docker容器内应用传递输入并接收输出
需求结论
这个需求完全可实现,你现有代码存在配置错误、API使用方式不当的问题,调整后即可完成宿主机Python脚本和容器内应用的stdin/stdout双向转发。
现有代码的问题
- 拼写错误:镜像名参数写为
doxker_image_name,存在拼写错误,会导致镜像拉取/启动失败 - 套接字使用方式错误:
exec_run返回的第二个值已经是可直接读写的封装套接字,不需要访问私有属性_sock收发数据 - TTY配置冗余:你开启了
tty=True分配伪终端,对于纯文本流透传场景,伪终端会额外插入终端控制字符、转义换行符,干扰正常的输入输出内容 - 流程逻辑缺失:发送数据后既没有读取程序的输出,也没有通知程序输入已结束,直接调用
container.wait()会永久阻塞——你的MirrorText程序是持续读取stdin的逻辑,没有收到输入结束的EOF信号会一直驻留运行,不会主动退出。
修正后的可运行代码
import docker client = docker.from_env() container = client.containers.run( image=docker_image_name, detach=True, name=dockername, network_mode='host', remove=True, tty=False ) # 启动容器内目标程序,获取双向交互套接字 _, sock = container.exec_run( cmd='./MirrorText', stdin=True, stdout=True, stderr=True, socket=True, workdir='/usr/src/ctf', tty=False, demux=True ) # 向容器内程序发送输入内容 sock.sendall(b"abc\n") # 关闭套接字写方向,向程序传递EOF信号,通知其输入已完成 sock.shutdown(1) # 参数1对应SHUT_WR,仅关闭写通道,不影响读通道接收输出 # 读取程序返回的全部输出 res = b"" while True: data = sock.recv(4096) if not data: break res += data # 等待容器正常退出 container.wait() # 打印输出结果 print(res.decode("utf-8"))
场景适配说明
- 如果你需要做持续交互式通信(不是发一次内容就结束),不需要调用
sock.shutdown(1),可以根据业务逻辑交替调用sendall()发送指令、recv()读取返回,注意根据自己的协议做好粘包拆分即可 - 如果你运行的程序必须依赖伪终端环境,可以保留
tty=True配置,读取输出时过滤掉终端产生的ANSI控制字符即可 - 不要直接访问套接字的私有属性
_sock,Docker SDK对外暴露的套接字对象已经做了协议适配,直接调用公开的send/recv方法兼容性更好。
内容的提问来源于stack exchange,提问作者DuduArbel
相关产品推荐
相关产品推荐

