天天看点

docker系列—Dockerfile详解

介绍

镜像的制作方式有两种

  1. 基于容器制作,但这样的镜像不利于维护,不适合线上使用。
  2. 另一种就是就是要介绍的Dockerfile,Dockerfile就是构建镜像的源代码,当时和我们编写程序的源代码不同,Dockerfile是一些命令的组合。

简要概括Dockerfile的作用:可以让用户个性化定制Docker镜像。因为不同的工作环境需求不同,网络上已存在的镜像不能完全满足自己的需求,此时就需要利用Dockerfile来构建自己可以满足自己需求的镜像。

格式

  1. Dockerfile整体就两类语句组成:
    • 注释信息,以 # 标识的行为注释行
    • 指令参数,一行一个指令。
  2. Dockerfile文件名首字母必须大写。
  3. Dockerfile指令不区分大小写,但是为方便和参数做区分,通常指令使用大写字母。
  4. Dockerfile中指令按顺序从上至下依次执行。
  5. Dockerfile中第一个非注释行必须是FROM指令,用来指定制作当前镜像依据的是哪个基础镜像。
  6. Dockerfile中需要调用的文件必须跟Dockerfile文件在同一目录下,或者在其子目录下,父目录或者其它路径无效。

指令集

FROM

  • FROM

    指令必须为Dockerfile文件开篇的第一个非注释行,用于指定构建镜像所使用的基础镜像,后续的指令运行都要依靠此基础镜像所提供的的环境(简单说就是假如Dockerfile中所引用的基础镜像里面没有mkdir命令,那后续的指令是没法使用mkdir参数的。)
  • 实际使用中,如果没有指定仓库,docker build会先从本机查找是否有此基础镜像,如果没有会默认去Docker Hub Registry上拉取,再找不到就会报错。

语法

FROM [--platform=<platform>] <image> [AS <name>]
or
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
or
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
           

scratch 是最基础的一个空白镜像。 下面是官方的centos的Dockerfile

docker系列—Dockerfile详解

RUN

  • RUN

    指令将在当前镜像的顶部中执行所有命令,并提交结果,生成的镜像将用于下一条指令。
  • RUN

    下一次构建期间,指令缓存不会自动失效。类似指令的缓存 RUN apt-get dist-upgrade -y将在下一个构建中重用。

    RUN

    指令的缓存可以通过使用–no-cache 标志来使无效,例如docker build --no-cache。

语法

shell形式,命令在shell中运行,默认情况下/bin/sh -c在Linux或cmd /S /CWindows 上运行

参数是一个JSON格式的数组,其中

"executable"

为要运行的命令,后面的"paramN"为传递给命令的选项或参数。此格式指定的命令不会以

"/bin/sh-c"

来发起,也就是直接由内核创建,因此不具备shell特性,类似于

RUN [ "echo", "$HOME" ]

,是无法识别 $ 的;如果想要依赖shell特性,可以替换命令为这样的格式

[ "/bin/sh", "-c", "echo $HOME" ]

CMD

  • 指定启动容器的默认要运行的程序,也就是PID为1的进程命令,且其运行结束后容器也会终止。如果不指定,默认是bash。
  • CMD

    指令指定的默认程序会被docker run命令行指定的参数所覆盖。
  • Dockerfile中可以存在多个

    CMD

    指令,但仅最后一个生效。因为一个docker容器只能运行一个PID为1的进程。
  • 类似于

    RUN

    指令,也可以运行任意命令或程序,但是两者的运行时间点不同,RUN指令运行在docker build的过程中,而CMD指令运行在基于新镜像启动容器(docker run)时。

语法

前两种语法格式同RUN指令。第一种用法对于CMD指令基本没有意义,因为它运行的程序PID不为1。

CMD command param1 param2

CMD ["executable","param1","param2"](exec形式,这是首选形式)
           

第三种则需要结合ENTRYPOINT指令使用,CMD指令后面的命令作为ENTRYPOINT指令的默认参 数。如果docker run命令行结尾有参数指定,那CMD后面的参数不生效。

CMD ["param1","param2"](作为ENTRYPOINT的默认参数)
           

LABEL

  • 同docker run -l
  • 用户可以为镜像指定各种元数据(键值对的格式)。

语法

可以在一行或者使用 \ 来拼接,来减少镜像的层,最终减小镜像的大小。

LABEL multi.label1="value1" multi.label2="value2" other="value3"
or
LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"
           

MAINTAINER

已弃用,LABEL要灵活的多。

EXPOSE

  • 通知Docker容器在运行时监听指定的网络端口。可以指定端口是侦听TCP还是UDP,如果未指定协议,则默认值为TCP。
  • docker run --expose

语法

示例

EXPOSE 80/tcp
EXPOSE 80/udp
           

ENV

  • ENV

    指令将环境变量设置为

    <key><value>

    。此值将在构建阶段中所有后续指令的环境中使用。调用格式为

    $variable_name或者${variable_name}

  • docker run -e

语法

ENV <key> <value>
ENV <key>=<value> ...
           
  1. 第一种形式,ENV

    <key> <value>

    会将一个变量设置为一个值。第一个空格之后的整个字符串将被视为-包括空格字符。该值将为其他环境变量解释,因此如果不对引号字符进行转义,则将其删除。
  2. 第二种形式ENV

    <key>=<value> ...

    允许一次设置多个变量。请注意,第二种形式在语法中使用等号(=),而第一种形式则不使用等号(=)。像命令行解析一样,引号和反斜杠可用于在值中包含空格。
  3. 定义多个变量时,建议使用第二种方式,因为Dockerfile中每一行都是一个镜像层,构建起来比较吃资源。

ADD

  • ADD

    指令跟

    COPY

    类似,不过它还支持使用tar文件和URL路径。
  • 当拷贝的源文件是tar文件时,会自动展开为一个目录并拷贝进新的镜像中;然而通过URL获取到的tar文件不会自动展开。复制或解压缩目录时,其行为与相同tar -x。

语法

ADD [--chown=<user>:<group>] <src>... <dest>
or
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] (此格式对于包含空格的路径是必需的)
           

规则

  1. 该路径必须是内部语境的构建; 不能这样做ADD …/something /something,因为第一步 docker build是将上下文目录(和子目录)发送到docker守护程序。
  2. 如果是URL,并且不以斜杠结尾,则从URL下载文件并将其复制到。
  3. 如果是URL并以斜杠结尾,则从URL推断文件名,然后将文件下载到 /。例如,ADD http://example.com/foobar /将创建文件/foobar。该URL必须具有非平凡的路径,以便在这种情况下可以发现适当的文件名(http://example.com 将不起作用)。
  4. 如果是目录,则将复制目录的整个内容,包括文件系统元数据。

COPY

  • 复制宿主机上的文件到目标镜像中

语法

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] (此格式对于包含空格的路径是必需的)
           

规则

同 ADD

ENTRYPOINT

  • 类似

    CMD

    指令的功能,用于为容器指定默认运行程序。
  • Dockerfile中可以存在多个

    ENTRYPOINT

    指令,但仅最后一个生效
  • CMD

    区别在于,由

    ENTRYPOINT

    启动的程序不会被

    docker run

    命令行指定的参数所覆盖,而且这些命令行参数会被当做参数传递给

    ENTRYPOINT

    指令指定的程序。不过,

    docker run

    的-

    -entrypoint

    选项的参数可覆盖

    ENTRYPOINT

    指定的默认程序

语法

ENTRYPOINT ["executable", "param1", "param2"] (执行表格,首选)
ENTRYPOINT command param1 param2 
           

VOLUME

  • 等同于

    docker run -v

  • 用于在镜像中创建一个挂载点目录。在dockerfile中只支持docker管理的卷,也就是说只能指定容器内的路径,不能指定宿主机的路径。宿主机可以通过

    docker inspect container

    查看。

语法

注意事项

  • 基于Windows的容器上的卷:使用基于Windows的容器时,容器内的卷的目的地必须是以下之一:
    1. 不存在或空目录
    2. 除以下以外的驱动器 C:
  • 从Dockerfile内更改卷:如果在声明了卷后有任何构建步骤更改了卷内的数据,则这些更改将被丢弃。
  • JSON格式:列表被解析为JSON数组。必须用双引号(")而不是单引号(’)括住单词。
  • 主机目录是在容器运行时声明的:主机目录(挂载点)从本质上说是依赖于主机的。这是为了保留图像的可移植性,因为不能保证给定的主机目录在所有主机上都可用。因此,无法从Dockerfile内挂载主机目录。该VOLUME指令不支持指定host-dir 参数。创建或运行容器时,必须指定安装点。

WORKDIR

  • docker run -w

  • 指定工作目录,可以指多个,每个

    WORKDIR

    只影响他下面的指令,直到遇见下一个

    WORKDIR

    为止。
  • WORKDIR

    也可以调用由ENV指令定义的变量。

语法

WORKDIR /path/to/workdir
           
  1. 该WORKDIR指令可以在Dockerfile中多次使用。如果提供了相对路径,则它将相对于上一条WORKDIR指令的路径

例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
则最终路径为/a/b/c
           

ARG

  • AR

    G命令同

    EVN

    类似,也是指定一个变量,但不同的是,

    ENV

    指令配合

    -e

    参数可以在

    docker run

    过程中传参,而使用

    ARG

    指令配合

    --build-arg

    参数可以在

    docker build

    过程中传参,这方便了我们为不同场景构建不同镜像。

语法

ONBUILD

  • 用于在Dockerfile中定义一个触发器。
  • ONBUILD

    后面指定的指令在

    docker build

    时是不会执行,构建完的镜像在被另一个Dockerfile文件中FROM指令所引用的时才会触发执行。

语法

STOPSIGNAL

  • 指定发送使容器退出的系统调用信号。

    docker stop

    之所以能停止容器,就是发送了15的信号给容器内PID为1的进程。

语法

STOPSIGNAL signal