介绍
镜像的制作方式有两种
- 基于容器制作,但这样的镜像不利于维护,不适合线上使用。
- 另一种就是就是要介绍的Dockerfile,Dockerfile就是构建镜像的源代码,当时和我们编写程序的源代码不同,Dockerfile是一些命令的组合。
简要概括Dockerfile的作用:可以让用户个性化定制Docker镜像。因为不同的工作环境需求不同,网络上已存在的镜像不能完全满足自己的需求,此时就需要利用Dockerfile来构建自己可以满足自己需求的镜像。
格式
- Dockerfile整体就两类语句组成:
- 注释信息,以 # 标识的行为注释行
- 指令参数,一行一个指令。
- Dockerfile文件名首字母必须大写。
- Dockerfile指令不区分大小写,但是为方便和参数做区分,通常指令使用大写字母。
- Dockerfile中指令按顺序从上至下依次执行。
- Dockerfile中第一个非注释行必须是FROM指令,用来指定制作当前镜像依据的是哪个基础镜像。
- Dockerfile中需要调用的文件必须跟Dockerfile文件在同一目录下,或者在其子目录下,父目录或者其它路径无效。
指令集
FROM
-
指令必须为Dockerfile文件开篇的第一个非注释行,用于指定构建镜像所使用的基础镜像,后续的指令运行都要依靠此基础镜像所提供的的环境(简单说就是假如Dockerfile中所引用的基础镜像里面没有mkdir命令,那后续的指令是没法使用mkdir参数的。)FROM
- 实际使用中,如果没有指定仓库,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
RUN
-
指令将在当前镜像的顶部中执行所有命令,并提交结果,生成的镜像将用于下一条指令。RUN
-
下一次构建期间,指令缓存不会自动失效。类似指令的缓存 RUN apt-get dist-upgrade -y将在下一个构建中重用。RUN
指令的缓存可以通过使用–no-cache 标志来使无效,例如docker build --no-cache。RUN
语法
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。
-
指令指定的默认程序会被docker run命令行指定的参数所覆盖。CMD
- Dockerfile中可以存在多个
指令,但仅最后一个生效。因为一个docker容器只能运行一个PID为1的进程。CMD
- 类似于
指令,也可以运行任意命令或程序,但是两者的运行时间点不同,RUN指令运行在docker build的过程中,而CMD指令运行在基于新镜像启动容器(docker run)时。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> ...
- 第一种形式,ENV
会将一个变量设置为一个值。第一个空格之后的整个字符串将被视为-包括空格字符。该值将为其他环境变量解释,因此如果不对引号字符进行转义,则将其删除。<key> <value>
- 第二种形式ENV
允许一次设置多个变量。请注意,第二种形式在语法中使用等号(=),而第一种形式则不使用等号(=)。像命令行解析一样,引号和反斜杠可用于在值中包含空格。<key>=<value> ...
- 定义多个变量时,建议使用第二种方式,因为Dockerfile中每一行都是一个镜像层,构建起来比较吃资源。
ADD
-
指令跟ADD
类似,不过它还支持使用tar文件和URL路径。COPY
- 当拷贝的源文件是tar文件时,会自动展开为一个目录并拷贝进新的镜像中;然而通过URL获取到的tar文件不会自动展开。复制或解压缩目录时,其行为与相同tar -x。
语法
ADD [--chown=<user>:<group>] <src>... <dest>
or
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] (此格式对于包含空格的路径是必需的)
规则
- 该路径必须是内部语境的构建; 不能这样做ADD …/something /something,因为第一步 docker build是将上下文目录(和子目录)发送到docker守护程序。
- 如果是URL,并且不以斜杠结尾,则从URL下载文件并将其复制到。
- 如果是URL并以斜杠结尾,则从URL推断文件名,然后将文件下载到 /。例如,ADD http://example.com/foobar /将创建文件/foobar。该URL必须具有非平凡的路径,以便在这种情况下可以发现适当的文件名(http://example.com 将不起作用)。
- 如果是目录,则将复制目录的整个内容,包括文件系统元数据。
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的容器时,容器内的卷的目的地必须是以下之一:
- 不存在或空目录
- 除以下以外的驱动器 C:
- 从Dockerfile内更改卷:如果在声明了卷后有任何构建步骤更改了卷内的数据,则这些更改将被丢弃。
- JSON格式:列表被解析为JSON数组。必须用双引号(")而不是单引号(’)括住单词。
- 主机目录是在容器运行时声明的:主机目录(挂载点)从本质上说是依赖于主机的。这是为了保留图像的可移植性,因为不能保证给定的主机目录在所有主机上都可用。因此,无法从Dockerfile内挂载主机目录。该VOLUME指令不支持指定host-dir 参数。创建或运行容器时,必须指定安装点。
WORKDIR
- 同
docker run -w
- 指定工作目录,可以指多个,每个
只影响他下面的指令,直到遇见下一个WORKDIR
为止。WORKDIR
-
也可以调用由ENV指令定义的变量。WORKDIR
语法
WORKDIR /path/to/workdir
- 该WORKDIR指令可以在Dockerfile中多次使用。如果提供了相对路径,则它将相对于上一条WORKDIR指令的路径
例如
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
则最终路径为/a/b/c
ARG
-
G命令同AR
类似,也是指定一个变量,但不同的是,EVN
指令配合ENV
参数可以在-e
过程中传参,而使用docker run
指令配合ARG
参数可以在--build-arg
过程中传参,这方便了我们为不同场景构建不同镜像。docker build
语法
ONBUILD
- 用于在Dockerfile中定义一个触发器。
-
后面指定的指令在ONBUILD
时是不会执行,构建完的镜像在被另一个Dockerfile文件中FROM指令所引用的时才会触发执行。docker build
语法
STOPSIGNAL
- 指定发送使容器退出的系统调用信号。
之所以能停止容器,就是发送了15的信号给容器内PID为1的进程。docker stop
语法
STOPSIGNAL signal