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 <docker@keji.com>"
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 命令行中替换此默认命令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值