【docker】CMD ENTRYPOINT 区别 终极解读!_绝世好阿狸的博客-CSDN博客
0、上下文路径
$ docker build -t nginx:v3 . # . 是上下文路径,那么什么是上下文路径呢?
上下文路径:指docker在构建镜像时想使用本机的文件,docker build命令得知这个路径后,会将路径下的所有内容打包。
解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。
如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。
注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。
1、COPY
复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
格式:
COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
[--chown=<user>:<group>]:可选参数,用户改变复制到容器内文件的拥有者和属组。
<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。
一般而言,虽然ADD并且COPY在功能上类似,但是
首选CO
P
Y。
那是因为它比ADD更易懂。
COPY仅支持将本地文件复制到容器中,而ADD具有一些功能(如仅限本地的tar提取和远程URL支持
)
,这些功能并不是很明显。因此,
ADD的最佳用途是将本地tar文件自动提取到镜像中
,如ADD rootfs.tar.xz /。
2、ADD
ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
-
ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
-
ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
3、RUN
RUN 指令:用于指定 docker build 过程中要运行的命令。:
格式:
RUN <command>
RUN ["<executeable>","<param1>","param2",...]
RUN ["/bin/bash","-c","<executeable>","param1","param2",...]
例如:
RUN yum install iproute nginx && yum clean all
4、CMD
类似于RUN命令,用于运行程序,但二者运行的时间点不同:
-
CMD在docker run时运行
-
RUN在docker build时运行
作用:为启动的容器指定默认运行的程序,程序运行结束,容器随之结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效
格式:推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行。
CMD <command> param1 param2 #(shell form) 默认可执行文件是 sh
CMD ["<executeable>","<param1>","<param2>",...] # (exec form, this is the preferred form 官方建议 )
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数;
例如:
CMD ["/usr/sbin/httpd","-c","/etc/httpd/conf/httpd.conf"]
#用法1:CMD <command> param1 param2 # (shell form)
即没有中括号的形式。那么命令<command>默认是在“/bin/sh -c”下执行的。
FROM centos
CMD echo "hello cmd!"
#用法2:CMD ["<executeable>","<param1>","<param2>",...] # (exec form, 官方建议)
带有中括号的形式。这时,命令没有在任何shell终端环境下,如果我们要执行shell,必须把shell加入到中括号的参数中。这种用法就像一个c语言的exec函数,意思是我们要执行一个进程。如果采用非shell的方法,那么上面的例子要修改为:
FROM centos
CMD ["/bin/bash", "-c", "echo 'hello cmd!'"]
当然,以上都是体现了cmd的“默认”行为。如果我们在run时指定了命令或者有entrypoint,那么cmd就会被覆盖。仍然是上面的image。run命令变了:
可以看到,最终容器里面执行的是run命令后面的命令,而不是cmd里面定义的。
5、ENTRYPOINT
ENTRYPOINT 指令:类似于CMD指令,但其不会被docker run的命令行参数指定的指令覆盖,且这些命令行参数会被当做参数送给ENTRYPOINT指令指定的程序。但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序。
entrypoint才是正统地用于定义容器启动以后的执行体的,这个是容器的“入口”
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
格式:
ENTRYPOINT <command> param1 param2 # (shell form)
ENTRYPOINT ["<executeable>","<param1>","<param2>",...] # (exec form, preferred 建议)
例如:输出top -b -c
CMD ["-c"]
ENTRYPOINT ["top","-b"]
可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参
,以下示例会提到。
示例:假设已通过 Dockerfile 构建了 nginx:test 镜像:
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
#用法2:ENTRYPOINT ["<executeable>","<param1>","<param2>",...] # (exec form, preferred 建议)
带中括号的,在shell环境下运行,跟CMD有所区别。若run命令后有东西,那么后面的全部作为entrypoint的参数,如果run后面没有而CMD有,那么CMD的全部内容作为entrypoint的参数。
Dockerfile为:
FROM centos
CMD ["p in cmd"]
ENTRYPOINT ["echo"]
若run不带参数:
若run带参数:
#用法1:ENTRYPOINT <command> param1 param2 # (shell form)
不带中括号,任何run和CMD的参数都无法传入到ENTRYPOINT里
FROM centos
CMD ["p in cmd"]
ENTRYPOINT echo
CMD的参数没有被打印。
5.1、ENTRYPOINT 与 CMD 区别
CMD是默认的容器启动执行命令,ENTRYPOINT才是真正的容器启动以后要执行命令。
如:
FROM ubuntu:14.10
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
把可能需要变动的参数写到 CMD 里面。然后你可以在 docker run 里指定参数,这样 CMD 里的参数(这里是-c) 就会被覆盖掉而 ENTRYPOINT 里的不被覆盖。
总结下一般该怎么使用:一般还是会用entrypoint的中括号形式作为docker 容器启动以后的默认执行命令,里面放的是不变的部分,可变部分比如命令参数可以使用cmd的形式提供默认版本,也就是run里面没有任何参数时使用的默认参数。如果我们想用默认参数,就直接run,否则想用其他参数,就run 里面加参数。
6、ENV
设置环境变量,定义了环境变量,后续指令就可以使用这个环境变量。
格式:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
7、ARG
构建参数,与ENV作用一样,但作用域不一样。ARG设置的环境变量仅对Dockerfile内有效,即只在docker build的过程中有效,构造好的镜像内不存在此环境变量。
构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。
格式:
ARG <参数名>[=<默认值>]
8、VOLUMN
定义匿名数据卷,在启动容器时忘记挂载数据卷,会自动挂载匿名卷。
作用:
1、避免重要的数据,因容器重启而丢失,这是非常致命的。
2、避免容器不断变大。
格式:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
9、EXPOSE
仅仅是声明端口
作用:
1、帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
2、在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
格式:
EXPOSE <端口1> [<端口2>...]
设置docker容器端口映射四种方式:
docker run -p 80 -i -t centos /bin/bash 【该方式指定容器端口-宿主机端口随机】
docker run -p 8080:80 -i -t centos /bin/bash【该方式指定宿主机端口:容器端口】
docker run -p 0.0.0.0:80 -i -t centos /bin/bash 【该方式指定宿主机IP:容器端口】
docker run -p 0.0.0.0:8888:80 -i -t centos /bin/bash 【该方式指定宿主机IP:端口:容器端口】常用这种方式
10、WORKDIR
指定工作目录。用WORKDIR指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
格式:
WORKDIR <工作目录路径>
11、HEALTHCHECK
用于指定某个程序或者指令来监控docker容器服务的运行状态
格式:
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
12、ONBUILD
用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
格式:
ONBUILD <其它指令>