docker 运行 <IMAGE> <MULTIPLE COMMANDS>

docker run <IMAGE> <MULTIPLE COMMANDS>

我正在尝试 运行 多个这样的命令。

docker run image cd /path/to/somewhere && python a.py

但这给了我 "No such file or directory" 错误,因为它被解释为...

"docker run image cd /path/to/somewhere" && "python a.py"

好像需要一些ESCAPE字符,比如""或者()。

所以我也试了

docker run image "cd /path/to/somewhere && python a.py"
docker run image (cd /path/to/somewhere && python a.py)

但是这些都不起作用。

我搜索了 Docker Run Reference 但没有找到任何关于 ESCAPE 字符的提示。

To 运行 docker中的多个命令,使用/bin/bash -c和分号;

docker run image_name /bin/bash -c "cd /path/to/somewhere; python a.py"

如果我们需要当且仅当 command1 (cd) 返回零(无错误)退出状态时执行 command2 (python),请使用 && 而不是 ;

docker run image_name /bin/bash -c "cd /path/to/somewhere && python a.py"

您可以通过以下几种方式执行此操作:

  1. 使用-w选项更改工作目录:

    -w, --workdir="" Working directory inside the container

    https://docs.docker.com/engine/reference/commandline/run/#set-working-directory--w

  2. 将整个参数传递给 /bin/bash:

    docker run image /bin/bash -c "cd /path/to/somewhere; python a.py"
    

您还可以在 Docker 容器内通过管道传输命令,bash -c "<command1> | <command2>" 例如:

docker run img /bin/bash -c "ls -1 | wc -l"

但是,如果不在远程中调用 shell,输出将被重定向到本地终端。

如果你想将结果存储在容器外的一个文件中,在你的本地机器上,你可以这样做。

RES_FILE=$(readlink -f /tmp/result.txt)

docker run --rm -v ${RES_FILE}:/result.txt img bash -c "cat /etc/passwd | grep root > /result.txt"

您的命令的结果将在您本地计算机的 /tmp/result.txt 中可用。

对于来到这里并希望对 docker-compose 执行相同操作的任何其他人,您只需在前面添加 bash -c 并将多个命令用引号引起来,并与 && 连接在一起。

因此在 OP 示例中 docker-compose run image bash -c "cd /path/to/somewhere && python a.py"

只是为了从@Eddy Hernandez 的评论中做出正确的回答,这是非常正确的,因为 Alpine 附带的是 ash 而不是 bash。

现在的问题是指 ,这意味着使用 shash/bin/sh/bin/ash/

根据 OP 的问题:

docker run image sh -c "cd /path/to/somewhere && python a.py"

bash -c 如果您使用的命令 运行 相对简单,则效果很好。但是,如果您尝试 运行 一长串充满控制字符的命令,它可能会变得复杂。

我通过从外部将我的命令传送到进程中成功地解决了这个问题,即

cat script.sh | docker run -i <image> /bin/bash

如果不明显,如果 a.py 总是需要在特定目录中 运行,请创建一个简单的包装脚本来执行 cd 然后 运行是脚本。

在你的Dockerfile中,替换

CMD [ 'python', 'a.py' ]

或任何

CMD [ '/wrapper' ]

并在您的根目录(或您方便的任何地方)创建一个脚本 wrapper,内容如下

#!/bin/sh
set -e
cd /path/to/somewhere
python a.py

在许多情况下,也许还可以考虑重写 a.py 以便它不需要包装器。要么让它 os.chdir() 在它需要的地方,要么让它在你在它的环境或类似环境中配置的目录中查找它的数据文件。

如果您不介意子 shell 中的命令 运行ning,只需在 运行:

的多个命令周围放置一组外括号
docker run image (cd /path/to/somewhere && python a.py)