写入正在运行的 docker 容器的标准输入

7 docker docker-exec docker-run

假设我将 docker 容器作为守护进程运行:

docker run -d foo
Run Code Online (Sandbox Code Playgroud)

有没有办法写入该容器的标准输入?就像是:

docker exec -i foo echo 'hi'
Run Code Online (Sandbox Code Playgroud)

上次我检查-i-d标志与docker run命令一起使用时是互斥的。

Dav*_*aze 5

原则上你可以docker attachCTRL+C将停止容器(通过向进程发送 SIGINT);CTRL+ P, CTRL+Q将与它分离并让它继续运行(如果你用 启动了容器docker run -it)。

这里的一个技巧是docker attach期望在某种终端中运行;您可以执行诸如运行之类的操作script来满足此要求。下面是一个例子:

# Create a new empty directory
mkdir x

# Run a container, in the background, that copies its stdin
# to a file in that directory
docker run -itd -v $PWD/x:/x --name cat busybox sh -c 'cat >/x/y'

# Send a string in
echo foo | script -q /dev/null docker attach cat
# Note, EOF here stops the container, probably because /bin/cat
# exits normally

# Clean up
docker rm cat

# See what we got out
cat x/y
Run Code Online (Sandbox Code Playgroud)

在实践中,如果程序通信的主要方式是通过其标准输入和标准输出上的文本,Docker 不是一个很好的打包机制。在 Docker Compose 或 Kubernetes 等更高级别的环境中,以这种方式发送内容变得越来越困难,并且经常假设容器可以完全自主运行。只是调用程序很快就会变得复杂(正如这个问题所暗示的那样)。如果你有类似的东西,比如,create-react-app 设置工具,它会询问一堆交互式问题,然后将内容写入主机文件系统,那么直接在主机上运行它会容易得多,而不是在 Docker 中运行。


Fri*_*itz 5

根据ServerFault上的另一个答案,您可以使用socat管道将输入传输到 docker 容器,如下所示:

echo 'hi' | socat EXEC:"docker attach container0",pty STDIN
Run Code Online (Sandbox Code Playgroud)

请注意,该echo命令在输出的末尾包含一个换行符,因此上面的行实际上发送hi\n. 使用echo -n 如果你不想换行。


让我们看看大卫回答中的示例脚本是怎样

echo 'hi' | socat EXEC:"docker attach container0",pty STDIN
Run Code Online (Sandbox Code Playgroud)

您也可以将其包装在 shell 函数中:

# Create a new empty directory
mkdir x

# Run a container, in the background, that copies its stdin
# to a file in that directory
docker run -itd --rm -v $PWD/x:/x --name cattainer busybox sh -c 'cat >/x/y'

# Send some strings in
echo 'hi' | socat EXEC:"docker attach cattainer",pty STDIN
echo 'still there?' | socat EXEC:"docker attach cattainer",pty STDIN

# Stop container (cleans up itself because of --rm)
docker stop cattainer

# See what we got out
cat x/y

# should output:
# hi
# still there?
Run Code Online (Sandbox Code Playgroud)

花絮:实际上,我使用这种方法来控制泊坞窗容器中运行见方的陆族的服务器,因为TerrariaServer.exe只接受服务器指令(像saveexit上)stdin