目录
1. FROM 基于基础镜像构建
1.1 FROM 指令开头
1.2 ARG和FROM使用
1.3 FROM可以多个
1.4 AS name
1.5 tag和digest
2. RUN 执行任何命令
2.1 shell和exec两种使用方式
2.2 [OPTIONS]参数
3. CMD 指定默认执行命令
3.1 使用格式shell和exec两种使用方式
3.2 只能有一个CMD指令
3.3 CMD可以在外部启动容器时替换CMD中的命令
4. ENTRYPOINT 指定默认执行命令
5. CMD和ENTRYPOINT区别
6. LABEL 将元数据添加到镜像中
7. MAINTAINER 指定生成的镜像作者信息
8. EXPOSE docker运行时要监听的端口号
9. ENV设置环境变量
10. ADD 添加本地和远程文件目录
11. COPY复制文件和目录
12. ADD和COPY指令在功能上是相似的,但目的略有不同。
13. VOLUME创建卷挂载
14. USER设定用户名和群组ID
14.1 使用示例
第 1 步:创建 Dockerfile
第 2 步:构建 Docker 镜像
第 3 步:运行 Docker 容器
第 4 步:验证输出
15. WORKDIR 设置工作目录
16. ARG 构建镜像时设置变量
16.1 ARG指令可以包含一个默认值
16.2 ARG变量有效范围
16.3 ARG使用方式
16.14 docker预定义的ARG参数
17. ONBUILD 当前镜像被其他镜像使用的时候的触发指令
18. STOPSIGNAL 指定在容器停止时发送给容器的信号
19. HEALTHCHECK 启动时检查容器的健康状况
20. SHELL Set the default shell of an image.
1. FROM 基于基础镜像构建
FROM [--platform=<platform>] <image> [AS <name>]FROM [--platform=<platform>] <image>[:<tag>] [AS <name>FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
1.1 FROM 指令开头
FROM 指令用于初始化一个新的构建阶段,并为后续指令设置基础镜像。因此,有效的 Dockerfile 必须以 FROM 指令开头。该镜像可以是任何有效的镜像。
1.2 ARG和FROM使用
在Dockerfile中,ARG是唯一可能位于FROM之前的指令。参见理解ARG和FROM是如何互动的。
dockerFile文件中,不论一个FROM还是多个FROM,如果from指令中要使用ARG定义的变量,只能使用第一个FROM指令前ARG定义的变量参数
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-appFROM extras:${CODE_VERSION}
CMD /code/run-extras
但如果我们想在FROM之后的命令中也想使用ARG定义的参数,就必须在FROM之后,再次用ARG指令引用参数名,只能引用参数名,而不能携带参数默认值
ARG VERSION=latest
FROM busybox:$VERSION
# 通过ARG 参数名 的方式 引用第一个from之前定义arg参数
ARG VERSION
RUN echo $VERSION > image_version
1.3 FROM可以多个
FROM可以在单个Dockerfile中出现多次,以创建多个镜像
或者将一个构建阶段用作另一个构建阶段的引用依赖。只需在每个新的FROM指令之前记录提交操作输出的最后一个镜像ID。
每个FROM指令清除由前一个指令创建的任何状态。
1.4 AS name
FROM指令添加AS name为新的构建阶段指定一个名称,该名称可以在后续的FROM构建阶段中引用。引用方式如下:
FROM <name>COPY --from=<name>RUN --mount=type=bind,from=<name> # 例如# 第一阶段:构建应用程序
FROM golang:1.16 AS builderWORKDIR /app# 拷贝应用程序的源代码到容器中
COPY . .# 构建应用程序
RUN go build -o myapp# 第二阶段:创建最终镜像
FROM alpine:latestWORKDIR /app# 从第一阶段复制构建好的应用程序到最终镜像中
COPY --from=builder /app/myapp .# 设置应用程序的入口命令
CMD ["./myapp"]
在上面的示例中,Dockerfile分为两个阶段。第一阶段使用golang:1.16作为基础镜像,将应用程序的源代码复制到容器中,并在容器中构建应用程序。第二阶段使用alpine:latest作为基础镜像,从第一阶段复制构建好的应用程序到最终镜像中,并设置应用程序的入口命令。
使用多阶段构建可以减小最终镜像的大小,因为第一阶段只包含构建所需的依赖和工具,而不包含运行时所需的额外组件。最终镜像只包含运行应用程序所需的最小组件,从而减小了镜像的体积。
另外一个方式:
COPY --from=0 /app/ /app
编号是从0开始,排第几就from几
1.5 tag和digest
<image>[:<tag>]和<image>[@<digest>] 以上两个参数可选,如果不使用这两个值时,会使用latest版本的基础镜像
2. RUN 执行任何命令
RUN 后面可以添加任何指令,相当于在当前镜像之上创建一个新层。添加的层在Dockerfile的下一步中使用。RUN有两种形式:
# Shell form:
RUN [OPTIONS] <command> ...
# Exec form:
RUN [OPTIONS] [ "<command>", ... ]
2.1 shell和exec两种使用方式
见之前介绍
(七)Dockerfile文件命令大全详解_dockerfile命令详解-CSDN博客文章浏览阅读784次,点赞16次,收藏25次。dockerFile命令时史上全面详细讲解_dockerfile命令详解https://blog.csdn.net/yilvqingtai/article/details/148692900
2.2 [OPTIONS]参数
使用见官方文档:
Dockerfile reference | Docker DocsFind all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.https://docs.docker.com/reference/dockerfile/#run
3. CMD 指定默认执行命令
通过镜像运行容器的时候,会执行CMD后面的命令
3.1 使用格式shell和exec两种使用方式
CMD command param1 param2CMD ["executable","param1","param2"]
3.2 只能有一个CMD指令
一个Dockerfile中只能有一个CMD指令。如果您列出了多个CMD命令,则只有最后一个生效。
3.3 CMD可以在外部启动容器时替换CMD中的命令
# dockerfile文件内容如下
FROM ubuntu:trusty
ENTRYPOINT ["ping"]
CMD ["-c", "20", "localhost"]
启动容器的时候
docker run kaidemo6 -c 30 127.0.0.1
其中 -c 30 127.0.0.1 就替换了dockerfile中CMD后面的 ["-c", "20", "localhost"]
4. ENTRYPOINT 指定默认执行命令
用法基本上和CMD一样,实际使用中二者结合使用,具体区别如下
5. CMD和ENTRYPOINT区别
(1)ENTRYPOINT 和 CMD 都可以单独使用,指定启动容器时所运行的命令以及参数。
(2)更常见的用法是把 ENTRYPOINT 和 CMD 组合使用:
- ENTRYPOINT 指定启动容器时所运行的命令和不变的参数。在启动容器时可以显式覆盖,但一般不这么做。
- CMD 指定运行参数。在启动容器时可以显式覆盖。
(3)ENTRYPOINT 和 CMD 都强烈推荐使用“exec形式”。
具体参考博客
Dockerfile里的ENTRYPOINT和CMD_dockerfile entrypoint和cmd-CSDN博客文章浏览阅读7k次,点赞40次,收藏44次。Dockerfile里的ENTRYPOINT和CMD_dockerfile entrypoint和cmdhttps://blog.csdn.net/duke_ding2/article/details/135418179
6. LABEL 将元数据添加到镜像中
LABEL指令将元数据添加到镜像中。LABEL是一个键值对。要在LABEL值中包含空格,请像在命令行解析中那样使用引号和反斜杠。下面是一些用法示例:
LABEL <key>=<value> [<key>=<value>...]
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
一个镜像可以添加多个标签LABEL,以下两种方式:
LABEL multi.label1="value1" multi.label2="value2" other="value3"LABEL multi.label1="value1" \multi.label2="value2" \other="value3"
7. MAINTAINER 指定生成的镜像作者信息
维护者信息:作者啥的,可以多个
格式:MAINTAINER <name>
示例:MAINTAINER Juhe cnMAINTAINER juhecn@163.comMAINTAINER Juhe cn <juhecn@163.com>
建议使用LABEL指令进行设置, 更方便灵活,同时可以通过 docker inspect 查看镜像的元数据。
8. EXPOSE docker运行时要监听的端口号
EXPOSE <port> [<port>/<protocol>...]
EXPOSE指令通知Docker容器在运行时监听指定的网络端口。您可以指定监听的端口TCP还是UDP,如果不指定协议,则默认为TCP。
EXPOSE 80/tcp
EXPOSE 80/udp
EXPOSE指令实际上并不发布端口。它的作用是作为构建映像的人员和运行容器的人员之间的一种文档,说明打算发布哪些端口。要在运行容器时发布端口,请在docker运行上使用-p标志来发布和映射一个或多个端口,或者使用-p标志来发布所有公开的端口并将其映射到高阶端口。
docker run -p 80:80/tcp -p 80:80/udp ...
docker network命令支持在容器之间创建通信网络,而不需要公开或发布特定的端口,因为连接到网络的容器可以通过任何端口相互通信。
9. ENV设置环境变量
ENV <key>=<value> [<key>=<value>...]
使用方式:
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
ENV指令允许多个<key>=<value>…变量一次设置:
ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \MY_CAT=fluffy
通过生成的镜像运行容器时,可以使用使用docker run——env <key>=<value>来更改它们。
10. ADD 添加本地和远程文件目录
ADD指令从<src>复制新的文件或目录,并将它们添加到镜像文件系统中<dest>路径下。
其中文件和目录可以从构建上下文、远程URL或Git存储库中复制。
两种使用方式:其中如果路径中带有空格,使用第二种方式
ADD [OPTIONS] <src> ... <dest>
ADD [OPTIONS] ["<src>", ... "<dest>"]
- 可以指定多个源文件或目录,但最后一个必须复制的目的地参数
ADD file1.txt file2.txt /usr/src/things/
如果指定了多个源文件,无论是直接指定还是使用通配符指定,那么目标文件必须是一个目录(必须以斜杠/结尾)。
- 远程地址或者git仓库地址复制
ADD https://example.com/archive.zip /usr/src/things/
ADD git@github.com:user/repo.git /usr/src/things/
- 从构建的上下文中复制文件
任何不以http://、https://或git@协议前缀开头的相对路径或本地路径都被认为是本地文件路径。
本地文件路径是相对于构建上下文的。
例如,如果构建上下文是当前目录,ADD file.txt / 将位于 ./file.txt 的文件添加到构建容器中文件系统的根目录。
- 指定带有斜杠的源路径,或者在构建上下文之外导航的源路径,
例如 ADD ../something /something,自动删除所有父目录导航(../)。源路径中的尾斜杠也会被忽略,使 ADD something/ /something 等同于 ADD something/ something
- 模式匹配
要在构建上下文的根目录中添加所有以.png结尾的文件和目录:
ADD *.png /dest/
在下面的例子中,?是一个单字符通配符,匹配例如index.js和index.ts
ADD index.?s /dest/
在添加包含特殊字符(如[和])的文件或目录时,需要按照Golang规则转义这些路径,以防止它们被视为匹配模式。例如,要添加一个名为arr[0].txt的文件,使用以下命令;
ADD arr[[]0].txt /dest/
更多见官方文档
Dockerfile reference | Docker DocsFind all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.https://docs.docker.com/reference/dockerfile/#add
11. COPY复制文件和目录
COPY有两种形式。后一种形式是包含空格的路径所必需的。
COPY [OPTIONS] <src> ... <dest>
COPY [OPTIONS] ["<src>", ... "<dest>"]
[OPTIONS]参数:
参数 | Dockerfile最小支持版本 |
---|---|
--from | |
--chown | |
--chmod | 1.2 |
--link | 1.4 |
--parents | 1.7-labs |
--exclude | 1.7-labs |
具体间官方文档:
Dockerfile reference | Docker DocsFind all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.https://docs.docker.com/reference/dockerfile/#copy
12. ADD和COPY指令在功能上是相似的,但目的略有不同。
- ADD和COPY在功能上相似。
- COPY支持从构建上下文或从多阶段构建中的一个阶段将文件复制到容器中。
- ADD支持从远程HTTPS和Git url获取文件的特性,以及在从构建上下文添加文件时自动提取tar文件的特性
在多阶段构建中,您通常希望使用COPY将文件从一个阶段复制到另一个阶段。如果您需要将构建上下文中的文件临时添加到容器中以执行RUN指令,那么您通常可以用绑定挂载代替COPY指令。例如,要临时为RUN pip安装指令添加一个requirements.txt文件:
RUN --mount=type=bind,source=requirements.txt,target=/tmp/requirements.txt \pip install --requirement /tmp/requirements.txt
13. VOLUME创建卷挂载
您应该使用VOLUME指令来公开由Docker容器创建的任何数据库存储区域、配置存储或文件和文件夹。
强烈建议您对映像中可变部分或用户可服务部分的任何组合使用VOLUME。
VOLUME ["/data"]
14. USER设定用户名和群组ID
USER <user>[:<group>]USER <UID>[:<GID>]
默认情况下,Docker 容器以 Root 用户身份运行。如果您在 Docker 容器内大规模部署应用程序,这会带来巨大的安全威胁。您可以使用USER指令更改或切换到 Docker 容器内的不同用户。为此,您首先需要在容器内创建一个用户和一个组。
14.1 使用示例
我们将使用USER指令将容器内的用户从 Root 切换到我们将创建的用户。
-
第 1 步:创建 Dockerfile
您可以在Dockerfile中指定创建新用户和组以及切换用户的指令。在此示例中,我们将简单地创建一个 Ubuntu 映像,并通过除 Root 用户之外的其他用户来使用 bash。
FROM ubuntu:latest
RUN apt-get -y update
RUN groupadd -r user && useradd -r -g user user
USER user
在上面的dockerfile中,我们已经拉取了基础镜像 Ubuntu 并更新了它。我们创建了一个名为user的新组,并在该组内创建了一个具有相同名称的新用户。使用USER选项,我们已经切换了用户。
-
第 2 步:构建 Docker 镜像
创建Dockerfile后,我们现在可以使用 Build 命令创建 Docker 映像。
sudo docker build -t user-demo
-
第 3 步:运行 Docker 容器
使用 Docker Run 命令来运行容器。
sudo docker run -it user-demo bash
第 4 步:验证输出
现在,您可以使用id命令检查默认用户和组是否已更改为我们在Dockerfile中创建的用户和组。
id
使用Dockerfile中的USER指令将 Docker 容器的默认用户从 Root 切换到我们可以使用useradd和groupadd命令创建的另一个用户。
15. WORKDIR 设置工作目录
WORKDIR /path/to/workdir
- 使用RUN、CMD、ENTRYPOINT、COPY和ADD指令,需要使用前先设定工作目录,因此可通过WORKDIR指令预先设置工作目录。如果不设置,Dockerfile仍然会默认创建
- Dockerfile文件中可以使用多个WORKDIR指令。
- 如果WORKDIR后面跟随的相对路径,其相对的路径是根据上一个WORKDIR指令的路径
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
输出结果 /a/b/c
- WORKDIR指令参数可以引用ENV变量
ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
输出结果: /path/$DIRNAME
- 如果未指定,则默认工作目录为/
- 如果我们dockerfile中没有用 FROM scratch 指令,而是基于 FROM baseiamge,那么工作目录通常是由基础镜像决定的。所以使用过程中,dockerfile中最好显式设定
“FROM scratch”是指构建一个完全空的镜像。这种方式通常用于构建小而轻量的容器,特别适合Go、Rust等编译为静态可执行文件的语言。使用
scratch
镜像的好处包括:
- 更小的体积:由于没有多余的库和工具,最终生成的镜像体积可以大幅减少。
- 控制性更强:开发者可以完全控制镜像中的内容,避免不必要的依赖和安全风险。
16. ARG 构建镜像时设置变量
ARG <name>[=<default value>] [<name>[=<default value>]...]
ARG指令定义了一个变量,用户可以在构建时使用 docker build 命令 --build-ARG <varname>=<value> 标志将该变量传递给构建器。
一个dockerfile文件中可以有多个ARG指令。
16.1 ARG指令可以包含一个默认值
FROM busybox
ARG user1=someuser
ARG buildno=1
# ...
docker build 时如果传递了值,该值会覆盖默认值
16.2 ARG变量有效范围
ARG生命后,开始起效
FROM busybox
USER ${username:-some_user}
ARG username
USER $username
# ...
调用方式
docker build --build-arg username=what_user .
第2行上的USER指令计算结果为some_user,因为还没有声明username变量。
第3行定义了username变量,从此位置往后,Dockerfile指令中就可以引用该变量
第4行USER的值是
what_user
,此时username参数有一个在命令行上传递的what_user值在ARG指令定义username变量之前,对username变量的任何使用都会导致一个空字符串。
在多个构建阶段的dockerfile中,在A阶段ARG声明的变量x,如果构建时B阶段继承了A阶段,那么B阶段也继承并共享A阶段的变量x,B阶段在使用的时候可以直接引用变量。相反,如果C阶段没有继承A阶段,那么必须通过ARG x 的方式,引用才能够使用,否则无法使用。具体参加下图:
16.3 ARG使用方式
- ARG和ENV使用覆盖
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=v1.0.0
RUN echo $CONT_IMG_VER
ENV会覆盖ARG参数值。
执行以下命令后,打印结果是v1.0.0而不是v2.0.1 ,这是因为第三行局部作用域覆盖了从其他方式传递的参数变量值。
docker build --build-arg CONT_IMG_VER=v2.0.1 .
16.14 docker预定义的ARG参数
Docker有一组预定义的ARG变量,你可以在Dockerfile中使用这些变量,而不需要相应的ARG指令。
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
ALL_PROXY
all_proxy
通过以下命令示例使用
docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .
其他更多ARG指令使用见官方文档
Dockerfile reference | Docker DocsFind all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.https://docs.docker.com/reference/dockerfile/#automatic-platform-args-in-the-global-scope
17. ONBUILD 当前镜像被其他镜像使用的时候的触发指令
ONBUILD <INSTRUCTION>
当镜像A被用作其他构建阶段的基础镜像的时候,会触发 ONBUILD 后的指令动作。可以理解为一个触发器。常用在一些不同配置或者守护进程中。
比如 某个镜像构建的时候包括了这些ONBUILD指令,以下构建后新的镜像名:alpine:baseimage
FROM alpine AS baseimage
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
此时如果其他构建基于上面镜像构建:
FROM alpine:baseimage
后续就会执行 基础镜像中的ADD 和 RUN的指令操作。
常见使用场景:
- 应用程序构建: 基础镜像包含编译环境(如 JDK、Maven、Node.js),
ONBUILD
指令可以自动添加源代码 (ONBUILD ADD . /app
) 并执行构建命令 (ONBUILD RUN mvn package
或ONBUILD RUN npm install
)。 - 标准化配置: 确保所有派生镜像都包含特定的配置文件或设置。
- 依赖注入: 自动安装特定于下游应用类型的依赖库。
更多参考博客
理解 Dockerfile ONBUILD 指令:构建可扩展的基础镜像 - Leo-Yide - 博客园在 Dockerfile 的世界里,指令是构建镜像蓝图的基石。除了常见的 FROM, RUN, COPY, CMD 等指令外,还有一个相对特殊但非常有用的指令——ONBUILD。ONBUILD 指令允许我们在基础镜像中定义一组“触发”指令,这些指令在构建基础镜像时并不会执行,而是在任何 下游 镜像(https://www.cnblogs.com/leojazz/p/18820017
18. STOPSIGNAL 指定在容器停止时发送给容器的信号
在Dockerfile中,STOPSIGNAL
指令是用来指定在容器停止时发送给容器的信号。这在某些情况下很有用,比如你想要在容器停止时执行一些清理工作。
然而,值得注意的是,STOPSIGNAL
指令已经被标记为不推荐使用(deprecated)并且在Docker的后续版本中可能会被移除。官方文档推荐使用 CMD
或 ENTRYPOINT
指令来处理容器的启动和停止逻辑。
19. HEALTHCHECK 启动时检查容器的健康状况
指令告诉 Docker 如何测试一个容器,以检查它是否仍在工作
Dockerfile中使用HEALTHCHECK的形式有两种:
1、HEALTHCHECK [options] CMD command
2、HEALTHCHECK NODE 意思是禁止从父镜像继承的HEALTHCHECK生效
options的可设定参数:
interval:间隔(s秒、m分钟、h小时),从容器运行起来开始计时interval秒(或者分钟小时)进行第一次健康检查,随后每间隔interval秒进行一次健康检查;还有一种特例请看timeout解析。
--start-period=DURATION 启动时间, 默认 0s, 如果指定这个参数, 则必须大于 0s ;--start-period 为需要启动的容器提供了初始化的时间段, 在这个时间段内如果检查失败, 则不会记录失败次数。 如果在启动时间内成功执行了健康检查, 则容器将被视为已经启动, 如果在启动时间内再次出现检查失败, 则会记录失败次数。
timeout:执行command需要时间,比如curl 一个地址,如果超过timeout秒则认为超时是错误的状态,此时每次健康检查的时间是timeout+interval秒。
retries:连续检查retries次,如果结果都是失败状态,则认为这个容器是unhealth的
CMD关键字后面可以跟执行shell脚本的命令或者exec数组。CMD后面的命令执行完的返回值代表容器的运行状况,可能的值:0 health状态,1 unhealth状态,2 reserved状态,这个没细研究,用的也很少。
注意:在Dockerfile中只能有一个HEALTHCHECK指令。如果您列出多个,则只有最后一个HEALTHCHECK将生效。
20. SHELL 设置镜像默认shell
SHELL ["executable", "parameters"]
默认dockerfile中shell命令是:
Linux 环境:["/bin/sh", "-c"]
Windows 环境:["cmd", "/S", "/C"]
使用SHELL命令可以直接覆盖。这尤其是在windows特别管用,因为window下有cmd和powershell两种脚本命令
FROM microsoft/windowsservercore# Executed as cmd /S /C echo default
RUN echo default# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S", "/C"]
RUN echo hello