docker(3、镜像3)1、Dockerfile 常用指令,2、RUN、CMD 和 ENTRYPOINT的区别。

1、Dockerfile 常用指令

下面列出了 Dockerfile 中最常用的指令,完整列表和说明可参看官方文档。
FROM

指定 base 镜像。
支持三种格式:
       FROM <image>
       FROM <image>:<tag>
       FROM <image>@<digest>

FROM指令必须指定,且需要在Dockerfile其他指令的前面。指定的基础指令可以是官方远程仓库中的,也可以是位于本地仓库。后续的指令都依赖于该指令指定的image。 在同一个Dockerfile中建立多个镜像时,可以使用多个FROM指令。

MAINTAINER
设置镜像的作者,可以是任意字符串。

格式: 
MAINTAINER <name> 
示例: 
MAINTAINER Jasper Xu​​​​​​​


COPY
格式为:
        COPY <src>...<dest>
        COPY ["<src>", ..."<dest>"], shell中执行

复制本地的src到容器的dest, 和ADD指令相似,但是COPY不支持URL和压缩包。
将文件从 build context 复制到镜像。
COPY 支持两种形式:
      COPY src dest
      COPY ["src", "dest"]
注意:src 只能指定 build context 中的文件或目录。
ADD
与 COPY 类似,从 build context 复制文件到镜像。不同的是,如果 src 是归档文件(tar, zip, tgz, xz 等),文件会被自动解压到 dest。
格式:ADD <src>...<dest>
           ADD ["<src>", ..."<dest>"]

从src目录复制文件到容器的dest目录,src可以是Dockerfile所在目录的相对路径,也可以是一个url,还可以是一个压缩包
注意事项:
1. src必须在构建的上下⽂内,不能使⽤例如: ADD ../some/something ,因为 docker build 命令⾸先会将上下⽂路径和其⼦⽬录发送到docker daemon
2. 如果src是⼀个URL,同时dest不以斜杠结尾,dest将会被视为⽂件,src对应内容⽂件将会被下载到dest
3. 如果src是⼀个URL,同时dest以斜杠结尾,dest将被视为⽬录,src对应内容将会被下载到dest⽬录
4. 如果src是⼀个⽬录,那么整个⽬录其下的内容将会被拷⻉,包括⽂件系统元数据
5. 如果⽂件是可识别的压缩包格式,则docker会⾃动解压

ENV设置环境变量,环境变量可被后面的指令使用
格式:ENV <key> <value>
           ENV <key>=<value>

指定环境变量,会被后续的RUN指令使用,并在容器使用后可以通过docker inspect查看这个环境变量,也可以通过使用docker run --env <key>=<value>来修改环境变量
例如:
...
ENV MY_VERSION 1.3
RUN apt-get install -y mypackage=$MY_VERSION
...
EXPOSE

指定容器中的进程会监听某个端口,Docker 可以将该端口暴露出来。
格式:
EXPOSE <port> [<port>...] 为Docker容器设置对外的端口号,使用时可以-p选项或者-P选项。

映射⼀个端⼝的例子:
EXPOSE port1
相应的运⾏容器使⽤的命令docker run -p port1 image
也可以使⽤-P选项启动docker run -P image
映射多个端⼝示例EXPOSE port1 port2 port3
相应的运⾏容器使⽤的命令docker run -p port1 -p port2 -p port3 image
还可以指定需要映射到宿主机器上的某个端⼝号docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
注意:
     #EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口
    #默认是TCP


VOLUME

将文件或目录声明为 volume。
格式为: VOLUME ["/data"]

格式:
    VOLUME ["/path/to/dir"]
示例:
    VOLUME ["/data"]
    VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"
注:
  一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
卷可以容器间共享和重用
容器并不一定要和其它容器共享卷
修改卷后会立即生效
对卷的修改不会对镜像产生影响
卷会一直存在,直到没有任何容器在使用它

[root@localhost imgl]# vi Dockerfile 

# Description: test image
FROM busybox:latest
LABEL maintainer "NAME <[email protected]>"
COPY yum.repos.d /etc/yum.repos.d/
# ADD http://nginx.org/download/nginx-1.17.3.tar.gz /usr/local/src/
ADD nginx-1.17.3.tar.gz /usr/local/src/
VOLUME /data/mysql

注意:

容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失,所以当数据需要持久化时用这个命令。
一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统
卷可以容器间共享和重用 可以关注参数 --volumes-from
容器并不一定要和其它容器共享卷
修改卷后会立即生效
对卷的修改不会对镜像产生影响卷会一直存在,直到没有任何容器在使用它
使容器中的⼀个⽬录具有持久化存储数据的功能,该⽬录可以被容器本身使⽤,也可以共享给其他容器

WORKDIR
为后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY 指令设置镜像中的当前工作目录。

格式为: WORKDIR /path/to/workdir

切换⽬录指令,类似于cd命令,对RUN、CMD、ENTRYPOINT⽣效。
注意:
通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。

RUN
在容器中运行指定的命令。

支持两种格式:

RUN <command> 在shell终端中运行命令,在Linux中默认是/bin/sh -c 

RUN["executable", "param1", "param2"],使用exec执行,指定其他终端,例如:RUN["/bin/bash", "-c", "echo hello"],该方式会被转成json数组。

RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell执行
格式:
    RUN <command>
exec执行
格式:
    RUN ["executable", "param1", "param2"]
示例:
    RUN ["executable", "param1", "param2"]
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]
注:
  RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
  基于基础镜像执行,在操作时评估好基础镜像的能力
  注意:json数组中,要使用双引号

CMD

容器启动时运行指定的命令。
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。CMD 可以被 docker run 之后的参数替换。
CMD ["executable", "param1", "param2"], 推荐使用该方式
CMD ["param1", "param2"],为ENTRYPOINT指令提供预设参数
CMD command param1 param2 在SHELL中执行

CMD指令的主要目的是为执行容器提供默认值,每个Dockerfile只有一个CMD命令,如果指定了多个CMD命令,也只会有一条执行,如果启动容器的时候指定了运行的命令,则会覆盖掉CMD指定的命令。

格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
示例:
    CMD echo "This is a test." | wc -
    CMD ["/usr/bin/wc","--help"]
注:
   CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

ENTRYPOINT
设置容器启动时运行的命令。

格式为: ENTRYPOINT ["executable", "param1", "param2"]

               ENTRYPOINT command param1 param2

指定Docker容器启动时执⾏的命令,Dockerfile 中可以有多个 ENTRYPOINT 指令,但只有最后一个生效。
CMD 或 docker run 之后的参数会被当做参数传递给 ENTRYPOINT

LABEL

格式为:LABEL <key>=<value> <key>=<value> <key>=<value> 为镜像添加元数据。

注意:

  • 使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。
  • LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖

USER

格式为: USER ⽤户名

设置启动容器的⽤户,默认是root⽤户

注:

  • 使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

ARG

格式为: ARG <name>[=<default value>]

ARG指令定义⼀个变量。

注意:

如果用户在build镜像时指定了一个参数没有定义在Dockerfile中,那么将有一个Warning:[Warning] One or more build-args [foo] were not consumed
ARG定义的参数默认值,当build镜像时没有指定参数值,将会使用这个默认值
 

ONBUILD

格式为:ONBUILD [INSTRUCTION]

指定当前建⽴的镜像作为其他镜像的基础时,所执⾏的命令。
注意:
当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发只对当前镜像的子镜像生效。
比如当前镜像为A,在Dockerfile种添加:ONBUILD RUN ls -al 这个 ls -al 命令不会在A镜像构建或启动的时候执行,此时有一个镜像B是基于A镜像构建的,那么这个ls -al 命令会在B镜像构建的时候被执行。

STOPSIGNAL
该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。此信号可以是与内核的系统调用表中的位置匹配的有效无符号数,例如9,或SIGNAME格式的信号名,例如SIGKILL

 
HEALTHCHECK
HEALTHCHECK指令告诉Docker如何测试容器以检查它是否仍在工作。即使服务器进程仍在运行,这也可以检测到陷入无限循环且无法处理新连接的Web服务器等情况。
当容器指定了运行状况检查时,除了正常状态外,它还具有运行状况。这个状态最初是starting。每当健康检查通过时,它就会变成healthy(以前的状态)。经过一定数量的连续失败后,它就变成了unhealthy


HEALTHCHECKDockerfile中只能有一条指令。如果列出多个,则只有最后一个HEALTHCHECK生效
SHELL
SHELL指令允许覆盖用于shell形式的命令的默认shell 。Linux上的默认shell是["/bin/sh", “-c”],而在Windows上[“cmd”, “/S”, “/C”]。


SHELL指令必须以JSON格式写入Dockerfile
SHELL指令可以多次出现。每条SHELL指令都会覆盖所有先前的SHELL指令,并影响所有后续指令

2、RUN、CMD 和 ENTRYPOINT的区别

区别:

  1.  RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包。
  2. CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换。
  3. ENTRYPOINT 配置容器启动时运行的命令。

Shell 和 Exec 格式
我们可用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式,二者在使用上有细微的区别。

Shell 格式
<instruction> <command>

例如:

RUN apt-get install python3  
CMD echo "Hello world"  
ENTRYPOINT echo "Hello world" 

当指令执行时,shell 格式底层会调用 /bin/sh -c <command>。
例如下面的 Dockerfile 片段:

ENV name Cloud Man  
ENTRYPOINT echo "Hello, $name" 

执行 docker run <image> 将输出:
Hello,  Man
注意环境变量 name 已经被值 Cloud Man 替换。
下面来看 Exec 格式。

Exec 格式
<instruction> ["executable", "param1", "param2", ...]

例如:

RUN ["apt-get", "install", "python3"]  
CMD ["/bin/echo", "Hello world"]  
ENTRYPOINT ["/bin/echo", "Hello world"]

当指令执行时,会直接调用 <command>,不会被 shell 解析。
例如下面的 Dockerfile 片段:

ENV name Man  
ENTRYPOINT ["/bin/echo", "Hello, $name"]

运行容器将输出:
Hello, $name
注意环境变量“name”没有被替换。
如果希望使用环境变量,照如下修改

ENV name Man  
ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]

运行容器将输出:
Hello,  Man
CMD 和 ENTRYPOINT 推荐使用 Exec 格式,因为指令可读性更强,更容易理解。RUN 则两种格式都可以。
RUN
RUN 指令通常用于安装应用和软件包。
RUN 在当前镜像的顶部执行命令,并通过创建新的镜像层。Dockerfile 中常常包含多个 RUN 指令。
RUN 有两种格式:
Shell 格式:RUN
Exec 格式:RUN ["executable", "param1", "param2"]
下面是使用 RUN 安装多个包的例子:

RUN apt-get update && apt-get install -y \  
 bzr \
 cvs \
 git \
 mercurial \
 subversion


注意:apt-get update 和 apt-get install 被放在一个 RUN 指令中执行,这样能够保证每次安装的是最新的包。如果 apt-get install 在单独的 RUN 中执行,则会使用 apt-get update 创建的镜像层,而这一层可能是很久以前缓存的。
CMD
CMD 指令允许用户指定容器的默认执行的命令。
此命令会在容器启动且 docker run 没有指定其他命令时运行。
如果 docker run 指定了其他命令,CMD 指定的默认命令将被忽略。
如果 Dockerfile 中有多个 CMD 指令,只有最后一个 CMD 有效。
CMD 有三种格式:
Exec 格式:CMD ["executable","param1","param2"]
这是 CMD 的推荐格式。
CMD ["param1","param2"] 为 ENTRYPOINT 提供额外的参数,此时 ENTRYPOINT 必须使用 Exec 格式。
Shell 格式:CMD command param1 param2
Exec 和 Shell 格式前面已经介绍过了。
第二种格式 CMD ["param1","param2"] 要与 Exec 格式 的 ENTRYPOINT 指令配合使用,其用途是为 ENTRYPOINT 设置默认的参数。我们将在后面讨论 ENTRYPOINT 时举例说明。
下面看看 CMD 是如何工作的。Dockerfile 片段如下:
CMD echo "Hello world"
运行容器 docker run -it [image] 将输出:
Hello world
但当后面加上一个命令,比如 docker run -it [image] /bin/bash,CMD 会被忽略掉,命令 bash 将被执行:
root@10a32dc7d3d3:/#
ENTRYPOINT
ENTRYPOINT 指令可让容器以应用程序或者服务的形式运行。
ENTRYPOINT 看上去与 CMD 很像,它们都可以指定要执行的命令及其参数。不同的地方在于 ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。
ENTRYPOINT 有两种格式:
Exec 格式:ENTRYPOINT ["executable", "param1", "param2"] 这是 ENTRYPOINT 的推荐格式。
Shell 格式:ENTRYPOINT command param1 param2
在为 ENTRYPOINT 选择格式时必须小心,因为这两种格式的效果差别很大。
Exec 格式
ENTRYPOINT 的 Exec 格式用于设置要执行的命令及其参数,同时可通过 CMD 提供额外的参数。
ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉。
比如下面的 Dockerfile 片段:
ENTRYPOINT ["/bin/echo", "Hello"]  
CMD ["world"]
当容器通过 docker run -it [image] 启动时,输出为:
Hello world
而如果通过 docker run -it [image] Man 启动,则输出为:
Hello Man
Shell 格式
ENTRYPOINT 的 Shell 格式会忽略任何 CMD 或 docker run 提供的参数。
最佳实践
使用 RUN 指令安装应用和软件包,构建镜像。
如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。
如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。

发布了62 篇原创文章 · 获赞 10 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/cojn52/article/details/104371306