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 CLI 参考以了解 --file 标志。
注意我们建议为您的项目主要 Dockerfile 使用默认名称(
Dockerfile)。
Docker 镜像
Docker 镜像由层组成。每个层都是 Dockerfile 中构建指令的结果。层按顺序堆叠,每个层都是表示应用于前一层更改的增量。
示例
以下是使用 Docker 构建应用程序的典型工作流程。
以下示例代码显示了一个使用 Flask 框架编写的小型“Hello World”Python 应用程序。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"为了在不使用 Docker Build 的情况下发布和部署此应用程序,您需要确保
- 所需的运行时依赖项已安装在服务器上
- 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 记法遵循 Docker 镜像命名的 name:tag 标准。当您构建镜像时,您使用此记法来命名您的镜像。您可以在您的项目中利用许多公共镜像,通过使用 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 的开头时,该符号才会被解释为指令。否则,它被视为注释。
安装依赖项
第二个 RUN 指令安装 Python 应用程序所需的 flask 依赖项。
RUN pip install flask==3.0.*此指令的前提是 pip 已安装到构建容器中。第一个 RUN 命令安装 pip,这确保我们可以使用该命令安装 flask Web 框架。
复制文件
下一个指令使用 COPY 指令将 hello.py 文件从本地构建上下文复制到镜像的根目录。
COPY hello.py /构建上下文是您可以在 Dockerfile 指令(如 COPY 和 ADD)中访问的一组文件。
在 COPY 指令之后,hello.py 文件被添加到构建容器的文件系统。
设置环境变量
如果您的应用程序使用环境变量,您可以使用 ENV 指令在 Docker 构建中设置环境变量。
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 主机上的 https://:8000。
提示为了改进 Visual Studio Code 中 Dockerfile 的 linting、代码导航和漏洞扫描,请参阅 Docker VS Code 扩展。