Docker 运行 bash --init-file

mpe*_*pen 2 bash docker

我正在尝试创建一个别名来帮助调试我的 docker 容器。

我发现 bash接受一个--init-file选项,该选项应该让我们在进入交互模式之前运行一些命令。

所以我想我可以做

docker-bash() {
  docker run --rm -it "$1" bash --init-file <(echo "ls; pwd")
}
Run Code Online (Sandbox Code Playgroud)

但这些命令似乎没有运行:

 % docker-bash c7460dfcab50
root@9c6f64a9db8c:/#
Run Code Online (Sandbox Code Playgroud)

这是一个逃避问题还是......发生了什么事?

bash --init-file <(echo "ls; pwd")
Run Code Online (Sandbox Code Playgroud)

单独在我的主机上的终端中按预期工作(运行命令启动一个新的 bash 实例)。

Kam*_*Cuk 5

分:

  • <(...)是 bash 扩展进程的替代
  • 从上面的手册:Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files.
  • 进程替换的工作原理如下:
    • bash 在 中创建一个 fifo/tmp或在 中创建一个新的文件描述符/dev/fd
    • 执行命令时,文件名将被/tmp/.something/dev/fd/<number>替换。<(...)
    • 例如echo <(echo 1)输出/dev/fd/63
  • Docker 的工作原理是创建一个与主机分离的新环境。这意味着:
    • docker 内部的进程不会从主机进程继承文件描述符:
      • 所以/dev/fd/*文件不会被继承。
    • docker 内的进程正在访问隔离的文件系统树。
      • 因此进程无法/tmp/*从主机访问文件。
  • 所以总结docker run -ti --rm alpine cat <(echo 1)是行不通的,因为 所替换的文件名<(...)在 docker 环境中不可用。

一个简单的解决方法就是:

docker run -ti --rm alpine sh -c 'ls; pwd; exec sh'
Run Code Online (Sandbox Code Playgroud)

或者使用临时文件:

echo "ls; pwd" > /tmp/tempfile
docker run -v /tmp/tempfile:/tmp/tempfile bash bash --init-file /tmp/tempfile
Run Code Online (Sandbox Code Playgroud)