Dockerfile 概述
Dockerfile
一切都始于一个Dockerfile。
Docker通过从Dockerfile读取指令来构建镜像。Dockerfile是一个包含构建源代码指令的文本文件。Dockerfile指令语法由Dockerfile参考中的规范定义。
以下是最常见的指令类型:
| Instruction | Description |
|---|---|
FROM | Defines a base for your image. |
RUN | Executes any commands in a new layer on top of the current image and commits the result. RUN also has a shell form for running commands. |
WORKDIR | Sets the working directory for any RUN, CMD, ENTRYPOINT, COPY, and ADD instructions that follow it in the Dockerfile. |
COPY | Copies new files or directories from <src> and adds them to the filesystem of the container at the path <dest>. |
CMD | Lets you define the default program that is run once you start the container based on this image. Each Dockerfile only has one CMD, and only the last CMD instance is respected when multiple exist. |
Dockerfiles 是镜像构建的关键输入,可以根据您的独特配置促进自动化、多层镜像构建。Dockerfiles 可以从简单开始,并根据您的需求逐步扩展,以支持更复杂的场景。
文件名
用于Dockerfile的默认文件名是Dockerfile,没有文件扩展名。使用默认名称允许您运行docker build命令,而无需指定额外的命令标志。
某些项目可能需要针对特定目的使用不同的Dockerfiles。一个常见的约定是将这些文件命名为。你可以使用docker build命令的--file标志来指定Dockerfile的文件名。请参考
docker build CLI参考
以了解--file标志。
注意
我们建议使用默认的(
Dockerfile)作为您项目的主要Dockerfile。
Docker 镜像
Docker 镜像由层组成。每一层都是 Dockerfile 中构建指令的结果。层按顺序堆叠,每一层都是一个增量,表示对前一层的更改。
示例
以下是使用Docker构建应用程序的典型工作流程。
以下示例代码展示了一个使用Flask框架编写的简单的“Hello World”应用程序。
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.04
FROM 指令 将您的基础镜像设置为 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,更新 APT 包索引并在容器中安装 Python 工具。
评论
注意# install app dependencies这一行。这是一个注释。在Dockerfile中,注释以#符号开始。随着你的Dockerfile的发展,注释对于记录你的Dockerfile如何工作对于任何未来的读者和编辑者,包括未来的你自己,都是非常有帮助的!
注意
你可能已经注意到,注释使用的符号与文件第一行的语法指令相同。只有当模式匹配指令并且出现在Dockerfile的开头时,该符号才会被解释为指令。否则,它将被视为注释。
安装依赖
第二个RUN指令安装了Python应用程序所需的flask依赖项。
RUN pip install flask==3.0.*本指令的前提条件是pip已安装到构建容器中。第一个RUN命令安装了pip,这确保了我们能够使用该命令来安装Flask网络框架。
复制文件
下一条指令使用
COPY 指令 将
hello.py 文件从本地构建上下文复制到我们镜像的根目录中。
COPY hello.py /一个
构建上下文 是你在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的“执行形式”版本。也可以使用“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。