07、Dockerfile语法详解

07、Dockerfile语法详解

1. 什么是Dockerfile

简单来说,Dockerfile 就是用来自定义镜像的

​ Dockerfile 是一个用于定义和构建 Docker 镜像的文本文件。Dockerfile 中包含一系列指令和参数,用于描述镜像的构建过程,包括基础镜像的选择、软件包的安装、文件的复制、环境变量的设置等

2. Dockerfile的基本结构

图片

2. Dockerfile的构建过程

Dockerfile 构建过程:

  1. 从基础镜像运行一个容器
  2. 执行一条指令,对容器做出修改
  3. 执行类似 docker commit 的操作,提交一个新的镜像层
  4. 再基于刚提交的镜像运行一个新的容器
  5. 执行 dockerfile 中的下一条指令,直至所有指令执行完毕

3. Dockerfile的参数详解

参数简单描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1FROM # 拉取镜像
2MAINTAINER # 指定镜像的作者信息
3RUN # 指定在当前镜像构建过程中要运行的命令 ,格式:RUN echo hello
4EXPOSE # 暴露端口, 格式:EXPOSE <端口 1> [<端口 2>...]
5CMD # 用于启动镜像,最后执行,格式: CMD[“executable”,“param1”,“param2”]
6)ENTERYPOINT # 和CMD类似,最后一个执行,格式:ENTERYPOINT [“executable”,“param1”,“param2”]
7COPY # 复制文件到容器,COPY [--chown=<user>:<group>] <源路径 1>... <目标路径>
8ADD # 将文件拷贝到容器,进行解压,单纯复制用copy命令。格式:ADD <src> <dest>
9VOLUME # 指定数据卷,格式:VOLUME ["<路径 1>", "<路径 2>"...] || VOLUME <路径>
10WORKDIR # 指定进入容器后的位置,格式:WORKDIR <工作目录路径>
(11) ENV # 设置环境变量,格式: ENV <key> <value> ||ENV <key>=<value>...
12USER # 指定进入容器的用户,必须存在,格式:USER <用户名>[:<用户组>]
13ONBUILD # 如果其他容器用该容器做基础镜像执行。
14LABEL # 容器打标签,LABEL authors="jiang" images="jiang"(多个空格隔开)
15HEALTHCHECK # 容器健康检查,判断容器是否启动,屏蔽检查 HEALTHCHECK NONE,最后一个执行
16ARG # 环境变量,仅对dockerfile文件生效

参数详细说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
1FROM 基础镜像
必须是可以下载下来的,定制的镜像都是基于 FROM 的镜像,这里的 centos 就是定制需要的基础镜像。后续的操作都是基于 centos 镜像。
示例:FROM centos

2MAINTAINER :指定镜像的作者信息
示例:LABEL maintainer="yourname@example.com"

3RUN:指定在当前镜像构建过程中要运行的命令
包含两种模式 :
1Shell
RUN <command> (shell 模式,这个是最常用的,需要记住)
RUN echo hello

2、exec 模式
RUN [“executable”,“param1”,“param2”](exec 模式)
RUN [“/bin/bash”,”-c”,”echo hello”]
等价于/bin/bash -c echo hello

4EXPOSE 指令 仅仅只是声明端口。
作用:
1、帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
2、在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
3、可以是一个或者多个端口,也可以指定多个 EXPOSE

格式:EXPOSE <端口 1> [<端口 2>...]

5CMD
类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
1CMD 在 docker run 时运行。
2RUN 是在 docker build 构建镜像时运行的

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被
docker run 命令行参数中指定要运行的程序所覆盖。

CMD[“executable”,“param1”,“param2”](exec 模式)
CMD command (shell 模式)
CMD [“param1”,”param2”](作为 ENTRYPOINT 指令的默认参数)

6)ENTERYPOINT
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被 当作参数送给 ENTRYPOINT 指令指定的程序。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 entrypoint 指令指定的程序。
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

格式:
ENTERYPOINT [“executable”,“param1”,“param2”](exec 模式)
ENTERYPOINT command (shell 模式)

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。
示例:
# 假设已通过 Dockerfile 构建了 nginx:test 镜像:
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参

1、不传参运行
$ docker run nginx:test

容器内会默认运行以下命令,启动主进程。
nginx -c /etc/nginx/nginx.conf

2、传参运行
$ docker run nginx:test -c /etc/nginx/new.conf
容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
nginx -c /etc/nginx/new.conf

7COPY
COPY<src>..<dest>
COPY[“<src>”...“<dest>”]
复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

格式:
COPY [--chown=<user>:<group>] <源路径 1>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径 1>",... "<目标路径>"]
[--chown=<user>:<group>]:可选参数,用户改变复制到容器内文件的拥有者和属组。
规则。例如:
COPY hom* /mydir/
COPY hom?.txt /mydir/

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

8ADD
ADD <src>...<dest>
ADD [“<src>”...“<dest>”]

ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,
会自动复制并解压到 <目标路径>。

ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像
构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

ADD vs COPY
ADD 包含类似 tar 的解压功能
如果单纯复制文件,dockerfile 推荐使用 COPY

例;替换/usr/share/nginx 下的 index.html
cd /root/dockerfile/test1
cat dockerfile
FROM centos
MAINTAINER xianchao
RUN yum install wget -y
RUN yum install nginx -y
COPY index.html /usr/share/nginx/html/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]

vim index.html
<html>
<head>

9VOLUME 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:
1、避免重要的数据,因容器重启而丢失,这是非常致命的。
2、避免容器不断变大。

格式:
VOLUME ["<路径 1>", "<路径 2>"...]
VOLUME <路径>
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

VOLUME [“/data”]

10WORKDIR
指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
格式:
WORKDIR <工作目录路径>

WORKDIR /path/to/workdir
(填写绝对路径)

(11 )ENV 设置环境变量
ENV <key> <value>
ENV <key>=<value>...

以下示例设置 NODE_VERSION =6.6.6, 在后续的指令中可以通过 $NODE_VERSION 引用:
ENV NODE_VERSION 6.6.6

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

12USER
用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
格式:
USER <用户名>[:<用户组>]

USER daemon
USER nginx
USER user
USER uid
USER user:group
USER uid:gid
USER user:gid
USER uid:group

13ONBUILD
用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的
ONBUILD 指定的命令。
格式:
ONBUILD <其它指令>

为镜像添加触发器当一个镜像被其他镜像作为基础镜像时需要写上 OBNBUILD 会在构建时插入触发器指令

14LABEL
LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
比如我们可以添加镜像的作者:
LABEL org.opencontainers.image.authors="xianchao"

15HEALTHCHECK 用于指定某个程序或者指令来监控 docker 容器服务的运行状态。
格式:
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

选项
--interval=<间隔> :两次健康检查的间隔,默认为 30 秒;
--timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
--retries=<次数> :当连续失败指定次数后,则将容器状态视为 unhealthy ,默认 3

举例:
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
# 如果返回 1 则退出

# 执行 docker build
$ docker build -f HEALTHCHEK.dockerifle -t myweb .

16ARG
构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。
格式:
ARG <参数名>[=<默认值>]

4. Dockerfile的构建java镜像

	在工程打好包后,我们就需要将部署包构建为docker镜像文件。那在构建镜像的时候,我们就需要一个Dockerfile文件来告诉docker怎么进行一个镜像的生成,比如说一些环境配置啊,部署包的路径啊,暴露的一些端口配置啊,启动命令啥的。

​ 那我们这里就需要告诉docker,我们部署的Java应用是需要一个jdk的运行环境,端口的话需要暴露8080,设置一个应用的工作目录/opt/app,服务启动命令java -jar /opt/app.jar。

查看目录结构:

1
2
3
4
[root@test docker]# tree ./
./
├── app.jar
└── Dockerfile

构建docker镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 编辑dockerfile文件
[root@test docker]# vim dockerfile

# 配置jdk基础镜像
FROM openjdk:8-jdk-alpine

# 暴露服务端口,暴露应用的端口,确保容器外部可以访问应用。
EXPOSE 8080

# 设置工作目录
WORKDIR /opt

# 拷贝本地文件到容器中 copy是相对于dockerfile的路径
COPY app.jar /opt/app.jar

#启动命令,设置容器启动时运行的命令,这里是启动 JAR 文件。
ENTRYPOINT ["java","-jar","/opt/app.jar"]

通过docker build命令来执行构建镜像:

1
docker build -f Dockerfile -t app:1.0 .


07、Dockerfile语法详解
http://blog.kjiang.vip/posts/1950070036.html
作者
发布于
2025年7月25日
许可协议