需求背景
如果要在docker容器中执行一个shell脚本,往往需要
docker cp ./test.sh container_name:/
docker exec container_name /test.sh
这样,先将脚本copy到容器中,然后运行
较为繁琐
优化方案
docker exec -i container_name sh -s -arg1 -arg2 <test.sh
如上表示在容器中执行宿主机当前路径下的test.sh脚本,并将-arg1 -arg2两个命令行参数传给test.sh
注意事项
-
注意执行docker exec时一定要有参数
-i
,否则脚本内容将不会被执行,原理见下 -
注意执行docker exec时不能有参数
-t
, 否则会报错the input device is not a TTY
-
如果脚本不需要入参,去掉
-s
即可
原理解释
平时我们‘进入容器’需要执行如下命令
docker exec -it container_name sh
这表示进入容器的命名空间,并执行sh命令
其中-i
表示打开标准输入(即0号文件描述符),并将将宿主机当前bash的标准输入继承到容器的sh进程
-t
表示为容器中的sh进程打开一个tty设备,让进程有终端
接下来我们在命令行输入的所有命令都会被脚本解释器sh进行解释并执行
那么,再看看我们的命令
docker exec -i container_name sh <test.sh
它同样是在容器中执行sh程序,但进程的标准输入被重定向到了宿主机的test.sh文件
sh会一行一行将test.sh中的命令解释并执行,文件读取完成后程序退出
其实就相当于我们‘进入容器’,把test.sh的内容一行一行敲进去,然后exit退出
原理理解了,python等其他脚本语言也可通过一样的方式进行执行脚本透传
测试
docker run busybox --name busybox
echo 'ls $1' >test.sh
docker exec -i busybox sh -s /usr/bin < test.sh