如何用Python编写程序启动Docker并执行命令返回输出?
我明白你想实现的功能——用Python调用Docker容器,执行指定命令并获取输出。先看看你现有代码里的几个小问题,然后给你两种可行的实现方案:
问题分析
-it参数的问题:-t会让Docker分配一个伪终端,但在subprocess这种非交互式环境下,这会导致不必要的错误,只需要保留-i来保持标准输入打开即可。communicate的用法:你传递给communicate的字符串是发送给容器的标准输入,但如果容器默认启动的不是shell,这条命令不会被执行。更稳妥的方式是直接在docker run命令里指定要执行的容器内命令。
方案一:直接在Docker命令中指定容器内的管道命令(推荐,更安全)
这种方式不需要通过stdin传递命令,直接把所有要在容器内执行的逻辑放在docker run的命令参数里,避免shell注入风险,也更清晰:
import subprocess def get_docker_output(image_name, input_text): # 构造容器内要执行的命令:把输入文本echo后传给demo.sh container_cmd = f'echo "{input_text}" | work/demo.sh' # Docker命令:--rm用完即删,无需-i(因为输入直接包含在命令里) docker_cmd = [ "sudo", "docker", "run", "--rm", image_name, "/bin/sh", "-c", container_cmd ] try: # 执行命令,捕获stdout和stderr result = subprocess.run( docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True # 命令执行失败时直接抛出异常 ) return result.stdout.strip() except subprocess.CalledProcessError as e: print(f"命令执行出错:{e.stderr}") return None # 使用示例 sentence = "Input for programm" output = get_docker_output("syntaxnet", sentence) if output: print("容器返回的脚本输出:") print(output)
方案二:通过stdin向容器传递输入(适合动态输入场景)
如果你的输入文本是动态生成的,或者不想把输入放在命令行参数里,可以通过stdin把输入直接传给容器内的demo.sh:
import subprocess def run_docker_with_input(image_name, input_text): # Docker命令:--rm用完即删,-i保持stdin打开,让demo.sh可以读取输入 docker_cmd = [ "sudo", "docker", "run", "--rm", "-i", image_name, "work/demo.sh" # 直接启动demo.sh,它会从stdin读取输入 ] try: # 启动进程,传递输入并获取输出 result = subprocess.run( docker_cmd, input=input_text, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True ) return result.stdout.strip() except subprocess.CalledProcessError as e: print(f"执行失败:{e.stderr}") return None # 使用示例 sentence = "Input for programm" output = run_docker_with_input("syntaxnet", sentence) if output: print("脚本输出:") print(output)
为什么这两个方案能解决问题?
- 移除了
-t参数,避免了非交互式环境下的终端分配错误; - 使用
subprocess.run(比Popen更简洁,适合一次性执行的命令),并通过text=True直接处理字符串,不需要手动解码字节流; - 方案一直接在容器内完成管道逻辑,方案二则让
demo.sh直接读取stdin输入,两种方式都能正确获取脚本的输出。
内容的提问来源于stack exchange,提问作者Rodrigo Serna Pérez
相关产品推荐
相关产品推荐

