***🎬慕斯主页***:*******************************修仙—别有洞天******************************** ♈️*今日夜电波:秒針を噛む—ずっと真夜中でいいのに。* 0:34━━━━━━️💟──────── 4:20 🔄 ◀️ ⏸ ▶️ ☰ 💗关注👍点赞🙌收藏*您的每一次鼓励都是对我莫大的支持*😍
首先理解几个概念
Dockerfile是什么?
Dockerfile
是一个文本文件,其中包含了构建 Docker 镜像的一系列指令。这些指令定义了镜像的内容,包括基础镜像的选择、镜像内的工作目录设置、依赖包的安装、环境变量的设定、端口的暴露、容器启动时要执行的命令等。
Docker 使用
Dockerfile
来自动化镜像的构建过程,这使得开发者能够轻松地创建可复现的镜像,并确保无论在哪个环境中构建,镜像都是一致的。
Dockerfile
的语法允许你以一种声明式的方式来描述你的镜像应该是什么样子的,而不是去记录一系列交互式的步骤。
以下是一个简单的
Dockerfile
示例:
# 使用官方 Python 运行时作为父镜像
FROM python:3.8-slim
# 设置作者信息
LABEL maintainer="[email protected]"
# 设置工作目录
WORKDIR /app
# 将当前目录内容复制到容器的 /app 中
COPY . /app
# 安装任何需要的包
RUN pip install --no-cache-dir -r requirements.txt
# 设置环境变量
ENV NAME World
# 暴露端口
EXPOSE 80
# 定义当容器启动时运行的命令
CMD ["python", "./your-daemon-or-script.py"]
Dockerfile
中的指令从上至下执行,第一条指令通常是
FROM
,用于指定基础镜像。之后的指令如
COPY
,
RUN
,
CMD
,
EXPOSE
和
ENV
等用于定制镜像的具体细节。
使用
docker build
命令并指向包含
Dockerfile
的目录,可以构建出一个 Docker 镜像。构建完成后,你可以使用这个镜像来运行 Docker 容器。
为什么需要 Dockerfile?
可以按照需求自定义镜像
和 docker commit 一样能够自定义镜像,官方的镜像可以说很少能直接满足
我们应用的,都需要我们自己打包自己的代码进去然后做成对应的应用镜像对外使用。
很方便的自动化构建,重复执行
通过 dockerfile 可以自动化的完成镜像构建,而不是像 docker commit 一样,
手动一个命令一个命令执行,而且可以重复执行, docker commit 的话很容易忘记执行了哪个命令,哪个命令没有执行。
维护修改方便,不再是黑箱操作
使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像,dockerfile 很容易二次开发。
更加标准化,体积可以做的更小
docker 容器启动后,系统运行会生成很多运行时的文件,如果使用 commit 会
导致这些文件也存储到镜像里面,而且 commit 的时候安装了很多的依赖文件,没有有效的清理机制的话会导致镜像非常的臃肿。使用 Dockerfile 则会更加标准化,而且提供多级构建,将编译和构建分开,不会有运行时的多余文件,更加的标准化。
Dockerfile 指令详解
1. FROM
功能:设置基础镜像,所有后续的指令都将基于这个镜像进行。
语法:FROM <image> [AS <name>] 或 FROM <image>[:<tag>] [AS <name>]
参数:
- <image>: 镜像名称。
- <tag>: 镜像的标签,默认是latest。
- <name>: 为后续构建层设置别名(可选)。
- <platform>:构建的 cpu 架构,如 linux/amd64, linux/arm64, windows/amd64
- <digest>:是镜像的哈希码;
- AS <name>: 指定构建步骤的名称,配合 COPY --from=<name>可以完成多级构建
样例:
2. MAINTAINER
注意:此指令已被LABEL maintainer取代。
功能:设置镜像的维护者信息。
语法(旧):MAINTAINER <name>
样例(旧):MAINTAINER John Doe john.doe@example.com
新推荐方式:LABEL maintainer="John Doe john.doe@example.com"
3. LABEL
功能:为镜像添加元数据。
语法:LABEL <key>=<value> <key>=<value> ...
样例:LABEL maintainer="John Doe john.doe@example.com"
4. COPY
功能:从宿主机复制文件或目录到容器内。
语法:COPY <src>... <dest> 或 COPY ["<src>",... "<dest>"](用于包含空格的路径)
参数
○ <src>:要复制的源文件或目录, 支持使用通配符;
○ <dest>:目标路径,即正在创建的 image 的文件系统路径; 建议<dest>使用
绝对路径,否则, COPY 指定以 WORKDIR 为当前路径
在路径中有空白字符时,通常使用第 2 种格式;
○ --chown:修改用户和组
○ --from <name>可选项 :
可以从之前构建的步骤中拷贝内容,结合 FROM .. AS <name>往往用作多级构建
注意事项
○ <src>必须是 build 上下文中的路径, 不能是其父目录中的文件;
○ 如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制;
○ 如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以 / 结尾;
○ 如果<dest>事先不存在,它将会被自动创建,这包括父目录路径。
样例:COPY ./index.html /data/web/html/
5. ADD
功能:与COPY类似,但会自动解压压缩文件(如tar.gz),也会自动完成下载(根据URL路径)。
语法:ADD <src>... <dest> 或 ADD ["<src>",... "<dest>"]
参数
<src>:要复制的源文件或目录, 支持使用通配符;
<dest>:目标路径,即正在创建的 image 的文件系统路径; 建议<dest>使用
绝对路径,否则, ADD 指定以 WORKDIR 为其实路径;在路径中有空白字符时,通常使用第 2 种格式;
--chown:修改用户和组
样例:ADD app.tar.gz /usr/src/app
6. WORKDIR
功能:设置工作目录,之后的RUN、CMD、ENTRYPOINT等指令都会在这个目录下执行。
语法:WORKDIR /path/to/workdir
注意事项
默认的工作目录是/
如果提供了相对路径,它将相对于前一条 WORKDIR 指令的路径。
WORKDIR 指令可以解析先前使用设置的环境变量 ENV
样例:WORKDIR /usr/src/app
7. RUN
功能:在镜像中执行命令并创建新的镜像层。
语法:RUN <command> 或 RUN ["executable", "param1", "param2"]
参数
○ 第一种格式中, <command>通常是一个 shell 命令, 且以“/bin/sh -c”来运
行它,Windows 默认为 cmd /S /C。如果一个脚本 test.sh 不能自己执行,必须要/bin/sh -c test.sh 的方式来执行,那么,如果使用 RUN 的 shell 形式,最后得到的命令相当于:
Bash/bin/sh -c "/bin/sh -c 'test.sh'"
○ 第二种语法格式中的参数是一个 JSON 格式的数组,其中<executable>为要
运行的命令,后面的 <paramN>为传递给命令的选项或参数;然而,此种格式指定的命令不会以“/bin/sh -c”来发起,因此常见的 shell 操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此 shell 特性的话,可以将其替换为类似下面的格式。 RUN ["/bin/bash", "-c", "<executable>","<param1>"]
样例:RUN apt-get update && apt-get install -y tree
8. VOLUME
功能:创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。
语法:VOLUME ["/data"]
注意事项
如果挂载点目录路径下此前有文件存在, docker run 命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
其实 VOLUME 指令只是起到了声明了容器中的目录作为匿名卷,但是并没有将匿名卷绑定到宿主机指定目录的功能。
volume 只是指定了一个目录,用以在用户忘记启动时指定-v 参数也可以保证容器的正常运行。比如 mysql,你不能说用户启动时没有指定-v,然后删了容器,就把 mysql 的数据文件都删了,那样生产上是会出大事故的,所以 mysql 的 dockerfile 里面就需要配置 volume,这样即使用户没有指定-v,容器被删后也不会导致数据文件都不在了。还是可以恢复的。
volume 与-v 指令一样,容器被删除以后映射在主机上的文件不会被删除。
如果-v 和 volume 指定了同一个位置,会以-v 设定的目录为准,其实volume 指令的设定的目的就是为了避免用户忘记指定-v 的时候导致的数据丢失,那么如果用户指定了-v,自然而然就不需要 volume 指定的位置了。
样例:VOLUME ["/var/log/nginx"]
9. EXPOSE
功能: 用于为容器声明打开指定要监听的端口以实现与外部通信。
该 EXPOSE 指令实际上并不发布端口。它充当构建图像的人和运行容器的人之间的一种文档,关于要发布哪些端口。要在运行容器时实际发布端口,使用-p 参数发布和映射一个或多个端口,或者使用-Pflag 发布所有暴露的端口并将它们映射宿主机端口。
语法:EXPOSE <port> [<port>/<protocol>...]
参数
<protocol>: tcp/udp 协议
<port>:端口
样例:EXPOSE 80 443
10. ENV
功能:设置环境变量。
语法:ENV <key> <value> 或 ENV <key>=<value> ...
样例:ENV MY_VAR SomeValue
11. CMD
功能:类似于 RUN 指令, CMD 指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同○ RUN 指令运行于映像文件构建过程中,而 CMD 指令运行于基于 Dockerfile构建出的新映像文件启动一个容器时○ CMD 指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过, CMD 指定的命令其可以被 docker run 的命令行选项所覆盖○ 在 Dockerfile 中可以存在多个 CMD 指令,但仅最后一个会生效
语法:CMD ["executable","param1","param2"] 、CMD ["param1","param2"] (as default parameters to ENTRYPOINT) 或 CMD command param1 param2
注意事项
第二种则用于为 ENTRYPOINT 指令提供默认参数
json 数组中,要使用双引号,单引号会出错
样例:CMD ["echo","Hello Docker!"]
12. ENTRYPOINT
功能:用于指定容器的启动入口.
语法:ENTRYPOINT ["executable", "param1", "param2"] 或 ENTRYPOINT command param1 param2
注意事项
json 数组中,要使用双引号,单引号会出错
样例:ENTRYPOINT ["/usr/sbin/nginx"],也可以直接启动对应的程序:ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]。你可以发现后面这个指令的作用好像同前面我们的CMD的指令是一样的,实际上他们也是有区别的,比如:我们以docker run -it myweb:v0.1(内为CMD指令)/myweb:v0.2(内为ENTRYPOINT指令) echo "hello word!"。v0.1版本会直接替换掉我们dockerfile里面的CMD命令,而v0.2版本则会显示无效,是不可以被覆盖掉的,这个echo "hello word!"是作为参数喂给了nginx,但是nginx不认识这个命令,会报错invalid option。
13. ARG
功能:定义构建时变量,可以在docker build时使用--build-arg <varname>=<value>来指定。
语法:ARG <name>[=<default value>]
注意事项
Dockerfile 可以包含一个或多个 ARG 指令
ARG 支持指定默认值
使用范围:定义之后才能使用,定义之前为空,如下面的案例,执行命令docker build --build-arg username=what_user .第二行计算结果为some_user ,不是我们指定的 build-arg 中的参数值 what_user
ENV 和 ARG 同时存在, ENV 会覆盖 ARG
样例:ARG user=defaultuser
14. VOLUME
功能:
VOLUME
指令用于在镜像中创建一个或多个挂载点,这些挂载点可以在容器运行时从宿主机或其他容器挂载数据。它主要用于持久化数据或需要共享数据的场景。
语法:VOLUME ["/path/to/volume", ...] 或 VOLUME /path/to/volume
(注意:当使用单个路径时,不需要方括号和引号)
参数:
/path/to/volume
:容器内的路径,将作为挂载点。
样例:
VOLUME ["/data", "/config"]
15. SHELL
功能:
SHELL
指令允许覆盖用于命令的默认shell形式。Linux上默认是
["/bin/sh", "-c"]
,但在某些情况下(如使用Alpine Linux时),你可能希望使用
["/bin/bash", "-c"]
或其他shell。需要注意:SHELL 指令必须以 JSON 格式写入 Dockerfile、SHELL 指令可以多次出现、每个 SHELL 指令都会覆盖所有先前的 SHELL 指令,并影响所有后续指令、该 SHELL 指令在 Windows 上特别有用,因为 windows 行有两种不同的shell: cmd 和 powershell。
语法:
SHELL ["executable", "parameters"]
参数:
executable
:shell程序的路径。parameters
:传递给shell程序的参数(可选)。
样例:
SHELL ["/bin/bash", "-c"]
16. USER
功能:
USER
指令设置运行后续命令(如RUN、CMD、ENTRYPOINT)的用户和(可选的)组。
语法:
USER <user>[:<group>]或USER <UID>[:<GID>]
参数:
<user>
或<UID>
:用户名称或UID。<group>
或<GID>
:组名称或GID(可选)。
样例:
USER nginx或USER 1001:1001
17. HEALTHCHECK
功能:
HEALTHCHECK
指令用于告诉Docker如何检查容器的健康状况。它可以在容器内部运行命令来检查服务是否正常运行。
语法:
有两种形式:
HEALTHCHECK [OPTIONS] CMD command
:在容器内执行命令来检查健康状态。HEALTHCHECK NONE
:禁用任何健康检查继承自基础镜像。
参数:
OPTIONS
:可选的,如--interval=DURATION
(每隔多长时间探测一次,默认 30秒 )、--timeout=DURATION
(服务响应超时时长,默认 30 秒 )、--start-period=DURATION
、--retries=N
(认为检测失败几次为宕机,默认 3 次 )、--start-period= DURATION:(服务启动多久后开始探测,默认 0 秒 )。command
:用于检查健康的命令。- 返回值▪ 0:容器成功是健康的,随时可以使用▪ 1:不健康的容器无法正常工作▪ 2:保留不使用此退出代码
样例:
HEALTHCHECK --interval=5s --timeout=3s
CMD curl -f http://localhost/ || exit 1
18. ONBUILD
功能:
ONBUILD
指令为镜像添加触发器,这些触发器在构建基于当前镜像的派生镜像时执行。
语法:
ONBUILD <INSTRUCTION>
参数:
<INSTRUCTION>
:任何Dockerfile指令,如RUN、COPY等。
样例:
ONBUILD ADD . /app/src
19. STOPSIGNAL
功能:
STOPSIGNAL
指令设置将用于停止容器的系统调用信号。默认是SIGTERM。
语法:
STOPSIGNAL signal
参数:
signal
:停止容器的信号,如SIGTERM、SIGKILL等。
样例:
STOPSIGNAL 9
当我们通过日志来观察我们通过stop停止的容器时,可以发现他并不像先前我们那样打印了“丝滑”的退出信息,而是直接退出:
Dockerfile制作命令—docker build
docker build
命令是 Docker 命令行工具中用于构建 Docker 镜像的核心命令。当你编写了一个 Dockerfile 后,就可以使用
docker build
命令来根据这个 Dockerfile 中的指令构建一个新的 Docker 镜像。下面是对
docker build
命令的详细解释:
基本语法
docker build [OPTIONS] PATH | URL | -
- OPTIONS:这是可选的,用于指定构建过程中的各种选项,如标签(
-t
)、构建上下文的位置(通过--path
指定,但通常直接使用 PATH 参数)、缓存的使用(如--no-cache
)等。 - **PATH | URL | -**:这是必需的,指定了 Dockerfile 的位置。PATH 是一个本地路径,指向包含 Dockerfile 的目录;URL 是一个指向 Git 仓库的 URL,Docker 会从该仓库中克隆并查找 Dockerfile;
-
表示从标准输入(stdin)读取 Dockerfile,这通常与管道(pipe)结合使用。
常用选项
- -t, --tag=TAG:为构建的镜像指定一个标签(Tag),格式为
name:tag
。如果未指定标签,则默认使用latest
作为标签。 - --no-cache:在构建镜像时不使用缓存。默认情况下,Docker 会利用缓存来加速构建过程,但如果你需要确保构建过程完全从头开始,可以使用这个选项。
- --rm:在成功构建镜像后,删除构建过程中创建的中间容器。这是默认行为,但可以通过
--no-rm
选项来禁用。 - --pull:在构建之前尝试拉取所有镜像的最新版本。这对于确保构建过程使用最新版本的基础镜像特别有用。
- --file, -f:指定 Dockerfile 的名称。默认情况下,Docker 会查找名为
Dockerfile
的文件,但你可以使用--file
或-f
选项来指定一个不同的文件名。 - **--quiet, -q :**安静模式,成功后只输出镜像 ID。
- **--label=[] :**设置镜像使用的元数据。
- **--network: **默认 default。在构建期间设置 RUN 指令的网络模式。
示例
假设你有一个名为
myapp
的目录,其中包含了一个 Dockerfile,你可以使用以下命令来构建一个名为
myimage
的镜像:
docker build -t myimage .
这里,
.
表示当前目录(即
myapp
目录),
-t myimage
指定了镜像的标签为
myimage
。
如果你想要使用位于当前目录但名为
Dockerfile.prod
的文件来构建镜像,你可以这样做:
docker build -t myimage --file Dockerfile.prod .
或者简写为:
docker build -t myimage -f Dockerfile.prod .
注意事项
- 构建上下文(Build Context):
docker build
命令会将指定的 PATH 或 URL 目录(不包括其子目录中的文件)发送给 Docker 守护进程(daemon)。这个目录被称为构建上下文。因此,为了加快构建过程,应该避免将不需要的文件包含在构建上下文中。 - 缓存:Docker 构建过程会尽量利用缓存来加速构建。如果你更改了 Dockerfile,并且这些更改位于之前步骤之后,那么只有那些更改之后的步骤会重新执行。
- 多阶段构建:从 Docker 17.05 开始,Dockerfile 支持多阶段构建,允许你使用多个 FROM 语句来利用构建缓存和最小化最终镜像的大小。但是,请注意,多阶段构建中的每个阶段仍然会共享相同的构建上下文。
** 感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o!**
![](https://img-blog.csdnimg.cn/a2296f4aa7fd45e9b1a1c44f9b8432a6.gif)
** 给个三连再走嘛~ **
版权归原作者 慕斯( ˘▽˘)っ 所有, 如有侵权,请联系我们删除。