文章目录
Docker 可以通过读取 Dockerfile来构建镜像。本文描述了Dockerfile各个命令意义及如何打包镜像
格式
Dockerfile文件格式为: 指令 参数
# this is a comment-line
RUN echo hello world
#RUN为指令,“echo hello world“为参数
一般来说指令不区分大小写。然而,按照惯例可以写成大写的,以便更容易地与参数区分开来。
Docker 按顺序运行Dockerfile指令。Dockerfile 文件中开始指令一般为FROM
。这可能位于 解析器指令、 注释和全局范围的 ARG之后。该FROM指令指定用那种基础镜像进行构建docker镜像。FROM前面只能有一个或多个ARG指令,这些指令声明FROM在Dockerfile.
Docker 将以#
为开头的均视为注释,除非该行是有效的 解析器指令。否则行中其他任何位置的标记#
都被视为参数。这允许这样的语句:
# Comment
RUN echo 'we are running some # of cool things'
注释行在执行 Dockerfile 指令之前被删除,这意味着执行命令的 shell 不会处理以下示例中的注释echo,并且下面的两个示例是等效的:
RUN echo hello \
# comment
world
RUN echo hello \
world
转义
Dockerfile默认转义字符为\
,可以用解析器指令escape
自定义转义符号
这在windows构建中特别有用,因为\
是windows目录路径分隔符
windows我们可以这样定义Dockerfile
# escape=`
FROM microsoft/nanoserver
COPY testfile.txt c:\
RUN dir c:\
指令
环境变量
环境变量在Dockerfile用 语句ENV声明,可以处理转义以将变量内容按字面意思包含到语句中。
Dockerfile环境变量形式为$variable_name
或${variable_name}
。大括号{}语法用于解决变量名不带空格的问题,例如${foo}_bar.
${variable_name}语法支持一些标准bash 修饰符,如下所示:
${variable:-word}
表示如果variable设置了则结果将是该值。如果variable未设置,则将word是结果。
${variable:+word}
表示如果variable设置了则word结果为,否则结果为空字符串。
在所有情况下,word可以是任何字符串,包括其他环境变量。
可以通过\进行转义,在变量前添加\$foo
或 \${foo}
,将分别转换为$foo
和${foo}
文字。
示例(解析后的表示显示在#后面):
FROM busybox
ENV FOO=/bar
WORKDIR ${FOO} # WORKDIR /bar
ADD . $FOO # ADD . /bar
COPY \$FOO /quux # COPY $FOO /quux
在Dockerfile中以下指令列表支持环境变量:
- ADD
- COPY
- ENV
- EXPOSE
- FROM
- LABEL
- STOPSIGNAL
- USER
- VOLUME
- WORKDIR
- ONBUILD(与上面支持的指令结合使用)
RUN指令
RUN 有 2 种形式:
RUN <command>
(shell形式,在Linux默认为/bin/sh -c)RUN ["executable", "param1", "param2"]
(exec形式)
该RUN指令将在当前镜像之上的新层中执行命令并提交结果。
分层RUN指令和生成提交符合 Docker 的核心概念,其中提交成本低廉,并且可以从映像历史记录中的任何点创建容器,就像源代码控制一样。
exec形式可以避免 shell 字符串修改,并且可以 使用不包含指定 shell 可执行文件的基本映像来执行命令。
在shell形式中,您可以使用\(反斜杠)将单个 RUN 指令继续到下一行。例如,考虑以下两行
RUN /bin/bash -c 'source $HOME/.bashrc && \
echo $HOME'
指令RUN缓存在下次构建期间不会自动失效。类似RUN apt-get dist-upgrade -y
将在下一次构建期间重用。可以使用–no-cache 标志使指令RUN缓存无效,例如docker build --no-cache。
CMD指令
CMD一条指令中只能有一条指令Dockerfile。如果列出多个,CMD 则只有最后一个CMD生效
CMD的主要目的是为执行容器提供默认值。这些默认值可以包含可执行文件,也可以省略,在无CMD情况下,必须指定指令ENTRYPOINT 。
如果CMD用于为ENTRYPOINT指令提供默认参数,则CMD和ENTRYPOINT指令都应使用 JSON 数组格式指定。
例如:
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
CMD 和 ENTRYPOINT
CMD和指令都ENTRYPOINT定义了运行容器时执行的命令。
-
Dockerfile 应至少指定CMD或ENTRYPOINT命令之一。
-
在容器用作可执行文件时应定义ENTRYPOINT 。
-
CMD用作定义命令的默认参数,ENTRYPOINT可以用在容器中执行临时命令。
-
当使用替代参数运行容器时CMD将被覆盖。
EXPOSE
该EXPOSE指令通知 Docker 容器在运行时监听指定的网络端口。可以指定端口是侦听 TCP 还是 UDP,如果不指定协议,则默认为 TCP。
该EXPOSE指令实际上并未发布端口。它充当构建映像的人员和运行容器的人员之间的一种文档,有关要发布哪些端口。要在运行容器时实际发布端口,请使用docker run -p
来发布和映射一个或多个端口,或者使用-P
标志来发布所有公开的端口并将它们映射到主机端口。
EXPOSE 80/tcp
使用-P
Docker 将每个公开的端口绑定到主机上的随机端口。端口范围在系统定义的临时端口范围(/proc/sys/net/ipv4/ip_local_port_range)内。使用-p
标志显式映射单个端口或端口范围。
ADD
ADD 的两种形式:
ADD [--chown=<user>:<group>] [--chmod=<perms>] [--checksum=<checksum>] <src>... <dest>
ADD [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]
#如果路径包含空格需要后一种形式。
ADD指令从路径复制新文件、目录或远程文件 URL<src>
并将它们添加到镜像的文件系统中<dest>
。
可以指定多个<src>
资源,但如果它们是文件或目录,则它们的路径将被解释为相对于构建上下文的源。
每个<src>
资源都可以包含通配符。例如:
添加以“hom”开头的所有文件:
ADD hom* /mydir/
在下面的示例中,?将替换为任何单个字符,例如“home.txt”。
ADD hom?.txt /mydir/
ADD规则:
-
该
<src>
路径必须位于构建的上下文内;不能使用ADD ../something /something
,因为 docker build第一步是将Dockefile上下文目录(和子目录)发送到 docker 守护进程。 -
如果
<src>
是 URL 并且<dest>
不以尾部斜杠结尾,则从该 URL 下载文件并将其复制到<dest>
。 -
如果
<src>
是 URL 并且<dest>
以尾部斜杠结尾,则从 URL 推断文件名并将文件下载到<dest>/<filename>
.例如,ADD http://example.com/foobar /
将创建文件/foobar
. URL 必须有一个路径,以便在这种情况下可以发现适当的文件名(http://example.com 不起作用)。 -
如果
<src>
是目录,则复制该目录的全部内容,包括文件系统元数据。 -
如果
<src>
是可识别的压缩格式(identity、gzip、bzip2 或 xz)的本地tar 存档,则将其解压缩为目录。如果是远程URL 的资源不会解压缩。当复制或解压目录时,它与tar -x相同
WORKDIR
WORKDIR /path/to/workdir
一个Dockerfile中WORKDIR指令为相对路径,它将相对于上一条指令的路径 WORKDIR。例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
pwd最终命令的输出Dockerfile将是/a/b/c。
如果未指定WORKDIR,则默认工作目录为/。实际上,如果不是从头开始构建 Dockerfile ( FROM scratch),则WORKDIR可能是由正在使用的基础映像设置的。
COPY
COPY [--chown=<user>:<group>] [--chmod=<perms>] <src>... <dest>
COPY [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]
以下命令是将当前文件拷贝到容器的工作目录中
COPY . .
HEALTHCHECK
HEALTHCHECK指令有两种形式:
- HEALTHCHECK [OPTIONS] CMD command(通过在容器内运行命令来检查容器运行状况)
- HEALTHCHECK NONE(禁用从基础镜像继承的任何健康检查)
HEALTHCHECK指令告诉 Docker 如何测试容器以检查它是否仍在工作。这可以检测诸如陷入无限循环并且无法处理新连接的 Web 服务器等情况,即使服务器进程仍在运行也是如此。
当容器指定了健康检查时,它除了正常状态之外,还具有健康状态。这种状态最初是starting。每当健康检查通过时,它就会变成healthy(无论它之前处于什么状态)。连续失败一定次数后,就变成了unhealthy。
HEALTHCHECK一个 Dockerfile 中只能有一条指令。如果列出多个,则只有最后一个HEALTHCHECK生效。
关键字后面的命令CMD可以是 shell 命令(例如HEALTHCHECK CMD /bin/check-running)或exec数组。
命令的退出状态指示容器的健康状态。可能的值为:
- 0:成功 - 容器运行状况良好并可供使用
- 1:不健康 - 容器无法正常工作
- 2:保留 - 不使用此退出代码
例如,每隔五分钟左右检查一次网站,超时时间为3s:
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
docker build
如果Dockerfile文件在当前目录,可以执行以下命令构建镜像
docker build .
#如果Dockerfile文件名不是默认的可以这样
docker build -f Dockerfile_name -t registry-vpc.cn-hangzhou.aliyuncs.com/xxxx:v1 .
docker push registry-vpc.cn-hangzhou.aliyuncs.com/xxxx:v1