Shell格式和Exec格式运行命令
我们可用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式:
Shell格式:。例如:apt-get install python3
Exec格式: ["executable", "param1", "param2", ...]。例如: ["apt-get", "install", "python3"]
CMD 和 ENTRYPOINT 推荐使用 Exec 格式,因为指令可读性更强,更容易理解。RUN 则两种格式都可以。
docker CMD 有三种形式
CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。
如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。
shell 格式的话如下
CMD echo "hello"
exec 格式的话如下
CMD ["echo","hello"]
exec 格式必须用双引号,中间用逗号隔开,执行命令 和命令后参数都是用双引号引起来,每个都要用逗号隔开。
shell 格式和 exec 格式主要区别在于
shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行执行。比如:
CMD echo $HOME
在实际执行中,会将其变更为:
CMD [ "sh", "-c", "echo $HOME" ]
这就是为什么我们可以使用环境变量的原因,因为这些环境变量会被 shell 进行解析处理,CMD会使用容器内的shell变量,自定义ENV
如果使用exec 格式的话,CMD 不会使用容器内的变量和自定义ENV
比如我们自定义了ENV name=lisa
使用shell模式的话,可以输出$name 为lisa
但是exec 模式的话是不能正常输出$namd的
如果想用exec 模式获取ENV变量的话,可以用折中方法,就是编写脚本,然后使用脚本去获取变量输出,CMD指令执行脚本,脚本一定加可执行权限比如 CMD["/root/test.sh"]
test.sh内容为
#!/bin/bash
echo $name
chmo 755 test.sh
这样打包进镜像后,就可以正常输出变量了,因为脚本使用的也是容器的shell,会被shell进行解析处理
最后一种运行模式
CMD ["参数1","参数2"] 是配合 ENTRYPOINT 使用的
CMD 和 ENTRYPOINT 最大区别在于,CMD 指定在容器启动时候指定了指令就会覆盖CMD
但是 ENTRYPOINT 不会被覆盖,只能追加参数,CMD可以配合ENTRYPOINT 使用,可以给ENTRYPOINT追加参数,另外两者结合使用的时候 CMD 指令是可以被覆盖的。