写入 运行 docker 容器的标准输入
Write to stdin of running docker container
假设我 运行 一个 docker 容器作为守护进程:
docker run -d foo
有没有办法写入该容器的标准输入?类似于:
docker exec -i foo echo 'hi'
我上次检查 -i
和 -d
标志在与 docker run
命令一起使用时是互斥的。
原则上可以docker attach
。 CTRL+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
只接受服务器命令(如 save
或 exit
) 在 stdin
.
假设我 运行 一个 docker 容器作为守护进程:
docker run -d foo
有没有办法写入该容器的标准输入?类似于:
docker exec -i foo echo 'hi'
我上次检查 -i
和 -d
标志在与 docker run
命令一起使用时是互斥的。
原则上可以docker attach
。 CTRL+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
只接受服务器命令(如 save
或 exit
) 在 stdin
.