【问题标题】:Write to stdin of running docker container写入正在运行的 docker 容器的标准输入
【发布时间】:2020-01-21 02:08:01
【问题描述】:

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

docker run -d foo

有没有办法写入该容器的标准输入?比如:

docker exec -i foo echo 'hi'

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

【问题讨论】:

  • 规范的答案是使用socat。详细请看下面关于serverfault的问题:serverfault.com/questions/885765
  • 你能在这里添加答案吗?我会投票给我加个标签,谢谢

标签: docker docker-run docker-exec


【解决方案1】:

根据another answer on ServerFault,您可以像这样使用socat 将输入通过管道传输到docker 容器:

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

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


让我们看看David's answer的示例脚本是什么样子的:

# 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="$1"; 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 仅在 stdin 上接受服务器命令(如 saveexit)。

【讨论】:

  • 这个方法是在继续下一行之前等待 docker 容器完成它的工作,还是只是异步执行这些步骤?
  • @Logan:它只是将文本发送到容器的标准输入。只要echo | socat 管道终止,函数docker_send 就会返回。为了等待,您首先必须准确地指定容器“做它的事情”的意思。例如,等待正在运行的进程的标准输出上的一些输出。
【解决方案2】:

原则上你可以docker attach给它。 CTRL+C 将停止容器(通过向进程发送 SIGINT); CTRL+P, CTRL+Q 将与它分离并保持运行(如果你用docker run -it)。

这里的一个技巧是docker attach 期望在某种终端中运行;您可以执行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 中运行它会容易得多。

【讨论】:

  • echo 'david left this part out' | docker attach c 还是?我说的更多是脚本,而不是交互式 shell。
  • 我以前见过有人使用echo foo | docker run --rm -it ... | grep ... 的例子,我有点期待... | docker attach 会起作用,但我手头没有例子。
  • 如果你能找到一个 docker attach 示例,我会给你一个大的绿色复选标记和 20 美元,我已经投票了
猜你喜欢
  • 2015-09-19
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多