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

Write to stdin of running docker container

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

docker run -d foo

有没有办法写入该容器的标准输入?类似于:

docker exec -i foo echo 'hi'

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

原则上可以docker attachCTRL+C 将停止容器(通过向进程发送 SIGINT); CTRL+P,CTRL+Q会脱离它并保留它 运行ning(如果您使用 docker run -it 启动容器)。

这里的一个技巧是 docker attach 期望在某种终端中 运行ning;你可以做类似 run it under 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

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

根据 another answer on ServerFault,您可以使用 socat 将输入通过管道传输到 docker 容器,如下所示:

echo 'hi' | socat EXEC:"docker attach container0",pty STDIN

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


让我们看看 :

中的示例脚本是什么样子的
# 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?

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

docker_send() {
    container=""; shift
    echo "$@" | socat EXEC:"docker attach $container",pty STDIN
}

docker_send cattainer "Hello cat!"
docker_send cattainer -n "No newline here:"    # flag -n is passed to echo

琐事:我实际上使用这种方法在 docker 容器中控制 Terraria 服务器 运行,因为 TerrariaServer.exe 只接受服务器命令(如 saveexit) 在 stdin.