使用Shell脚本在Docker容器中运行脚本


85

我正在尝试创建用于设置Docker容器的Shell脚本。我的脚本文件如下所示:

#!bin/bash

docker run -t -i -p 5902:5902 --name "mycontainer" --privileged myImage:new /bin/bash

运行此脚本文件将在新调用的bash中运行容器。

现在,我需要运行一个脚本文件(test.sh),该文件已经位于上述给定的shell脚本的容器中(例如:cd /path/to/test.sh && ./test.sh)。


1
为什么不使用WORKDIRCMD
Dharmit

1
您可能不想在这里使用--privileged。参见:stackoverflow.com/questions/36425230/…–
CMP

Answers:


121

您可以使用以下命令在正在运行的容器中运行命令docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

docker exec mycontainer /path/to/test.sh

并从bash会话运行:

docker exec -it mycontainer /bin/bash

从那里您可以运行脚本。


6
如果我需要先进入/ bin / bash然后在该bash中运行命令怎么办?
zappy

44
您也可以直接从主机运行本地脚本。docker exec -i mycontainer bash < mylocal.sh 这将读取本地主机脚本并在容器内运行它。您可以使用其他方法(例如,将.tgz文件通过管道输送到tar中)进行操作-只需使用“ -i”将其输送到容器进程的std输入中即可。
Marvin

@Marvin在PowerShell中等效于什么?无法识别“ <”字符。
Nicekiwi

1
我不是一个超级强大的专家,但我四处徘徊,发现stackoverflow.com/a/11788475/500902。因此,也许Get-Content mylocal.sh | docker exec -i mycontainer bash。我不知道这是否可行。
马文

97

假设您的Docker容器已启动并正在运行,则可以运行以下命令:

docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"

2
我喜欢这个答案;您不必登录docker容器即可执行一个命令或一组命令。谢谢!
Hatem Jaber

您是否知道进一步操作并将整个命令(/bin/sh -c "cmd1; cmd2; ...; cmdn")作为shell变量的值传递?我问是因为“ docker run”似乎期望一个命令和单个未加引号的参数,而不是带引号的字符串。
davidA

@meowsqueak:此答案告诉您如何在已创建并正在运行的容器中运行多个命令而无需登录该容器,这对自动化很有帮助。但是,如果要在创建容器时运行多个命令(PS:docker run命令创建并启动容器),则可以通过在同一线程中遵循以下答案来实现这一点stackoverflow.com/a/41363989/777617
Cyclops

代替cmd1,我需要传递整个for循环-但它期望;loop语句和do语句之后。如何将整个for循环作为单个命令运行cmd1?可能吗?
Nicholas K

18

我正在寻找相同问题的答案,并在Dockerfile解决方案中为我找到ENTRYPOINT

Docker文件

...
ENTRYPOINT /my-script.sh ; /my-script2.sh ; /bin/bash

现在,当我启动容器时便会执行脚本,并且在执行脚本后会收到bash提示。


6

您还可以将本地目录挂载到docker映像中,并在中获取脚本.bashrc。除非您希望脚本在每个新的Shell上执行,否则不要忘记脚本必须由函数组成。(这已过时,请参阅更新通知。)

我正在使用此解决方案,以便能够在docker实例之外更新脚本。这样,如果发生更改,我不必重新运行映像,只需打开一个新的shell。(摆脱了重新打开外壳程序的问题-请参阅更新通知)

这是绑定当前目录的方式:

docker run -it -v $PWD:/scripts $my_docker_build /bin/bash

现在,您的当前目录已绑定到/scripts您的Docker实例。

(已过时)要保存.bashrc更改,请使用以下命令提交工作映像:

docker commit $container_id $my_docker_build

更新资料

为了解决此问题以为每个更改打开新的外壳,我现在执行以下操作:

在dockerfile本身中添加RUN echo "/scripts/bashrc" > /root/.bashrc"。在内部,zshrc我将脚本目录导出到路径。脚本目录现在包含多个文件,而不是一个。现在,我可以直接调用所有脚本,而不必每次更改都打开一个子外壳。

顺便说一句,您也可以在容器外部定义历史文件。这样,就不必再进行bash更改了。


太晚了..!@javier已经显示了直接的解决方案!我觉得一个还是更好。
zappy

2
@zappy javier的解决方案无法为我方便地解决此问题-但我的解决方案可以解决我的问题,对于那些有类似问题且不想重启docker镜像来更新a的人,我认为这将很有趣查看他们需要的功能。例如,如果您一次使用多个docker镜像启动一个dev集群,则您不想一直重启它们。
Devpool '18

3

如果您不想(或没有)一个正在运行的容器,则可以使用run命令直接调用脚本。

删除迭代的tty-i -t参数,并使用此参数:

    $ docker run ubuntu:bionic /bin/bash /path/to/script.sh

这((未测试)也可以用于其他脚本:

    $ docker run ubuntu:bionic /usr/bin/python /path/to/script.py


0

如果要在多个实例上运行相同的命令,可以执行以下操作:

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.