Dockerfile 概览
Dockerfile
一切从 Dockerfile 开始。
Docker 通过读取 Dockerfile 中的指令来构建镜像。Dockerfile 是一个包含构建源代码指令的文本文件。Dockerfile 指令语法由 Dockerfile 参考 中的规范参考定义。
这里是常见的指令类型:
| 说明 | 描述 |
|---|---|
FROM <image> | 定义您镜像的基础。 |
RUN <command> | 在当前镜像的新层上执行任何命令并将结果提交。RUN 还提供用于运行命令的 shell 形式。 |
WORKDIR <directory> | 为 Dockerfile 中其后的任何 RUN, CMD, ENTRYPOINT, COPY, 和 ADD 指令设置工作目录。 |
COPY <src> <dest> | 从<src>复制新的文件或目录,并将它们添加到容器文件系统中的路径<dest>。 |
CMD <command> | 允许您定义基于此镜像启动容器后运行的默认程序。每个 Dockerfile 只能有一个 CMD,当存在多个时,仅最后一个 CMD 实例会被尊重。 |
Dockerfile 是镜像构建的关键输入,可根据您的独特配置促进自动化的多层镜像构建。Dockerfile 可以从简单开始,并随着您的需求增长以支持更复杂的场景。
文件名
用于 Dockerfile 的默认文件名是 Dockerfile,不带文件扩展名。使用默认名称允许您运行 docker build 命令,无需指定其他命令标志。
某些项目可能需要为特定目的使用不同的Dockerfile。一个常见的约定是将这些文件命名为<something>.Dockerfile。您可以通过为docker build命令使用--file标志来指定Dockerfile文件名。
请参阅
docker build 命令行参考
以了解--file标志的用法。
注意
我们建议为项目的主Dockerfile使用默认值(
Dockerfile)。
Docker 镜像
Docker 镜像由多层组成。每一层都是 Dockerfile 中构建指令的结果。这些层按顺序堆叠,每一层都是相对于前一层变化的增量表示。
示例
使用 Docker 构建应用程序的典型工作流程如下。
以下示例代码展示了一个使用 Flask 框架编写的用 Python 编写的简单“Hello World”应用程序。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"为了在不使用 Docker 构建的情况下交付和部署此应用程序,您需要确保:
- 服务器上已安装所需的运行时依赖项
- Python 代码会被上传到服务器的文件系统
- 服务器使用必要的参数启动您的应用程序
以下 Dockerfile 创建了一个容器镜像,其中已安装所有依赖项,并且会自动启动您的应用程序。
# syntax=docker/dockerfile:1
FROM ubuntu:22.04
# install app dependencies
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip install flask==3.0.*
# install app
COPY hello.py /
# final configuration
ENV FLASK_APP=hello
EXPOSE 8000
CMD ["flask", "run", "--host", "0.0.0.0", "--port", "8000"]以下是此 Dockerfile 的内容分解:
Dockerfile 语法
在 Dockerfile 中添加的第一行是
# syntax 解析器指令。
虽然这是可选的,但该指令会指示 Docker 构建器在解析 Dockerfile 时使用哪种语法,并允许启用
BuildKit
的旧版 Docker 在开始构建之前使用特定的
Dockerfile 前端。
解析器指令
必须出现在 Dockerfile 中的任何其他注释、空白或 Dockerfile 指令之前,并且应该是 Dockerfile 的第一行。
# syntax=docker/dockerfile:1提示
我们推荐使用
docker/dockerfile:1,它始终指向版本1语法的最新发布。在构建之前,BuildKit会自动检查语法的更新,确保您使用的是最新版本。
基础镜像
在语法指令后面的行定义了要使用什么基础镜像:
FROM ubuntu:22.04FROM 指令将您的基础镜像设置为 Ubuntu 的 22.04 版本。其后的所有指令都在此基础镜像(Ubuntu 环境)中执行。符号 ubuntu:22.04 遵循 name:tag 命名 Docker 镜像的标准。构建镜像时,您使用此符号来命名镜像。您可以利用许多公共镜像,通过在 Dockerfile 中使用 FROM 指令将其导入到构建步骤中。
Docker Hub 包含大量官方镜像,可用于此目的。
环境设置
以下命令行在基础镜像中执行构建命令。
# install app dependencies
RUN apt-get update && apt-get install -y python3 python3-pip此
RUN 指令 在 Ubuntu 中执行一个 shell,该 shell 会更新 APT 包索引并在容器中安装 Python 工具。
评论
注意 # install app dependencies 行。这是一个注释。Dockerfile 中的注释以 # 符号开头。随着你的 Dockerfile 不断演进,注释对于记录 Dockerfile 的工作原理至关重要,无论是对未来的读者和编辑,还是对未来的你!
注意
你可能已经注意到,注释使用与Dockerfile文件第一行上的语法指令相同的符号表示。 只有当模式匹配指令且出现在Dockerfile的开头时,该符号才被解释为指令。否则,它被视为注释。
安装依赖项
第二个 RUN 指令安装 Python 应用程序所需的 flask 依赖项。
RUN pip install flask==3.0.*本说明的前提是 pip 已安装到构建容器中。第一个 RUN 命令安装了 pip,这确保我们可以使用该命令来安装 Flask Web 框架。
复制文件
下一步指令使用
COPY 指令 将本地构建上下文中的
hello.py 文件复制到我们镜像的根目录。
COPY hello.py /A
构建上下文 是一组文件,您可以在 Dockerfile 指令中访问,例如 COPY 和 ADD。
在 COPY 指令之后,hello.py 文件被添加到构建容器的文件系统中。
设置环境变量
如果你的应用程序使用环境变量,你可以在Docker构建中使用
ENV 指令来设置环境变量。
ENV FLASK_APP=hello这将设置我们稍后需要的 Linux 环境变量。本示例中使用的 Flask 框架使用此变量来启动应用程序。如果没有这个, Flask 将不知道在哪里找到我们的应用程序才能运行它。
暴露端口
EXPOSE 指令 标记我们的最终镜像在端口 8000 上有服务监听。
EXPOSE 8000此指令并非必需,但这是一个良好的实践,有助于工具和团队成员了解此应用程序正在执行的操作。
启动应用程序
最后,
CMD 指令 设置了用户基于此镜像启动容器时运行的命令。
CMD ["flask", "run", "--host", "0.0.0.0", "--port", "8000"]此命令启动 flask 开发服务器,监听所有地址上的端口 8000。此处的示例使用了 CMD 的“exec 形式”。
也可以使用“shell 形式”:
CMD flask run --host 0.0.0.0 --port 8000在这两个版本之间存在细微的差别,
例如它们如何捕获像 SIGTERM 和 SIGKILL 这样的信号。
有关这些差异的更多信息,请参阅
Shell 和 exec 形式
构建
要使用上一节中的 Dockerfile 示例构建容器镜像,您需要使用 docker build 命令:
$ docker build -t test:latest .
-t test:latest 选项指定镜像的名称和标签。
命令末尾的单个点(.)将
构建上下文设置为当前目录。这意味着构建期望在调用命令的目录中找到Dockerfile和hello.py文件。如果这些文件不在那里,构建将失败。
在镜像构建完成后,您可以使用docker run运行容器中的应用程序,指定镜像名称:
$ docker run -p 127.0.0.1:8000:8000 test:latest
这将容器的端口 8000 发布到 Docker 主机上的 http://localhost:8000。