Docker通过dockerfile
创建镜像时,RUN
和CMD
是相当重要的命令,本文对这CMD
指令进行解析。
CMD 语法
# exec形式,这是首选形式.
CMD ["executable","param1","param2"]
# 提供给ENTRYPOINT的默认参数.
CMD ["param1","param2"]
# shell形式.
CMD command param1 param2
CMD 语义
· dockerfile
中只能包含一个CMD
指令,如果存在多个,只有最后一个CMD
生效。
· CMD
的主要用途是为执行容器提供默认值。这些默认值可以包括可执行文件,或者也可以省略可执行文件,但在这种情况下,必须指定一个ENTRYPOINT
。
· 如果CMD
被用来为ENTRYPOINT
指令提供默认参数,那么CMD
和ENTRYPOINT
指令必须使用JSON Array格式。
· exec
形式是按照JSON Array格式解析,意味着必须是使用双引号(")包含参数,而不能使用单引号(’)。
· 与shell
形式不同,exec
形式不会调用shell
命令行,意味着不会进行shell
处理。例如:运行RUN [ "echo", "$HOME" ]
不会对$HOME
进行变量替换。如果需要shell
处理,那么可以使用shell
形式或直接执行shell
,例如:RUN["sh","-c","echo $HOME"]
。当使用exec
形式直接执行shell
时,与shell
形式类似,应用的shell
是宿主机而非Docker。
· 当使用shell
或exec
形式时,通过CMD
设置的指令在镜像运行时执行。
· 如果使用CMD
的shell
形式,那么使用/bin/bash -c
执行:
FROM ubuntu
CMD echo "This is a test." | wc -
· 如果不想使用shell
执行命令,那么必须以JSON Array
格式指定命令表达式,同时指定可执行文件的完整路径。这里的JSON Array
格式即是CMD
的首选格式。任何附加参数都必须被定义为数组中的字符串。
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
· 如果希望容器每次都执行相同的可执行文件,可以考虑使用ENTRYPOINT
和CMD
结合使用。
· docker run
指定的参数会覆盖CMD
指定的值。
· 不要混淆RUN
和CMD
。RUN
用来运行一个命令并提交结果,目的是进行镜像构建;CMD
在构建时不执行任何操作,而是在容器运行时运行指定的命令。
CMD 示例
1) 进入/securitit/dockerfile/目录(根据个人选择,这是本文使用的目录),创建dockerfile
文件。
FROM nginx
MAINTAINER Securitit
CMD echo "The container is running, You can use it now!"
2) 执行如下的构建命令,基于dockerfile
构建镜像。
docker build -f /securitit/dockerfile/dockerfile -t securitit-nginx-cmd:1.0.0.1 .
3) 查看镜像信息。
docker images
4) 指定通过dockerfile
生成的镜像启动容器。
docker run --name securitit-nginx-cmd -it -p 10180:80 securitit-nginx-cmd:1.0.0.1
5) 可以看到,dockerfile
中定义的CMD
指令内容会在docker run
运行容器时执行。
CMD 与 RUN
CMD
与RUN
都是用来在dockerfile
中配置命令的,它们之间有所不同:
· 应用阶段
RUN
是镜像构建步骤,RUN
命令后将容器的状态提交到容器镜像。
CMD
是启动构建镜像时,默认情况下,容器执行的命令。
· 执行次数
一个dockerfile
可以具有很多RUN
步骤,这些步骤相互叠加最后生成镜像。
dockerfile
将使用最后一个CMD
指令,使用CMD
启动容器时可以覆盖docker run $image $other_command
。
总结
RUN
和CMD
指令在基于dockerfile
构建镜像时,起到了非常大的作用,各位可以按照文中示例,手动操作一遍。
docker build
系列指令会在今后的博客中更新。
若文中存在错误和不足,欢迎指正!