建立您的Python映像

预计阅读时间:11分钟

先决条件

通过入门第1部分中的方向和设置来理解Docker概念。

概述

现在,我们对容器和Docker平台有了一个很好的了解,让我们看一下构建我们的第一个映像。映像包括运行应用程序所需的所有内容-代码或二进制文件,运行时,依赖项以及所需的任何其他文件系统对象。

要完成本教程,您需要以下内容:

样品申请

让我们使用Flask框架创建一个简单的Python应用程序,作为示例。在本地计算机上创建一个名为的目录,python-docker然后按照以下步骤创建一个简单的Web服务器。

$ cd /path/to/python-docker
$ pip3 install Flask
$ pip3 freeze > requirements.txt
$ touch app.py

现在,让我们添加一些代码来处理简单的Web请求。在您喜欢的IDE中打开此工作目录,然后在app.py文件中输入以下代码。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, Docker!'

测试应用程序

让我们启动我们的应用程序,并确保它运行正常。打开终端,然后导航到您创建的工作目录。

$ python3 -m flask run

要测试该应用程序是否正常运行,请打开新的浏览器并导航至http://localhost:5000

切换回运行我们的服务器的终端,您应该在服务器日志中看到以下请求。您的计算机上的数据和时间戳将有所不同。

127.0.0.1 - - [22/Sep/2020 11:07:41] "GET / HTTP/1.1" 200 -

为Python创建一个Dockerfile

现在我们的应用程序可以正常运行,让我们看一下创建Dockerfile的过程。

Dockerfile是一个文本文档,其中包含用户可以在命令行上调用以组装映像的所有命令。当我们告诉Docker通过执行docker build命令来构建映像时,Docker读取这些指令并连续执行它们,从而创建一个Docker映像。

让我们逐步为应用程序创建一个Dockerfile。在工作目录的根目录中,创建一个名为的Dockerfile文件,然后在文本编辑器中打开该文件。

笔记

Dockerfile的名称并不重要,但是许多命令的默认文件名只是Dockerfile。因此,在本系列中,我们将其用作文件名。

添加到Dockerfile的第一行是# syntax解析器指令。虽然可选的,这个指令指示泊坞建设者解析Dockerfile当什么语法使用,并允许旧的码头工人版本的BuildKit启用开始构建之前升级解析器。解析器指令 必须出现在Dockerfile中的任何其他注释,空格或Dockerfile指令之前,应该是Dockerfiles中的第一行。

# syntax=docker/dockerfile:1

我们建议您使用docker/dockerfile:1,它始终指向版本1语法的最新版本。BuildKit会在构建之前自动检查语法更新,以确保您使用的是最新版本。

接下来,我们需要在Dockerfile中添加一行,以告诉Docker我们想要为应用程序使用什么基本映像。

# syntax=docker/dockerfile:1

FROM python:3.8-slim-buster

Docker映像可以从其他映像继承。因此,我们将使用已经具有运行Python应用程序所需的所有工具和软件包的官方Python图像,而不是创建自己的基本图像。

笔记

要了解有关创建自己的基本图像的更多信息,请参阅创建基本图像

为了使运行其余命令更容易,让我们创建一个工作目录。这指示Docker使用此路径作为所有后续命令的默认位置。这样,我们不必键入完整的文件路径,而是可以根据工作目录使用相对路径。

WORKDIR /app

通常,下载用Python编写的项目后,要做的第一件事就是安装pip软件包。这样可以确保您的应用程序安装了所有依赖项。

在运行之前pip3 install,我们需要将requirements.txt文件添加到映像中。我们将使用COPY命令来执行此操作。该COPY命令有两个参数。第一个参数告诉Docker您要将哪些文件复制到映像中。第二个参数告诉Docker您要将文件复制到哪里。我们将requirements.txt文件复制到我们的工作目录中/app

COPY requirements.txt requirements.txt

requirements.txt文件包含在图像中后,就可以使用RUN命令执行命令pip3 install。这与pip3 install在计算机上本地运行完全相同,但是这次模块已安装到映像中。

RUN pip3 install -r requirements.txt

至此,我们有了一个基于Python版本3.8的映像,并且我们已经安装了依赖项。下一步是将我们的源代码添加到图像中。我们将使用COPYrequirements.txt上面文件相同的命令。

COPY . .

COPY命令将获取当前目录中的所有文件,并将它们复制到映像中。现在,我们要做的就是告诉Docker在容器中执行映像时要运行什么命令。我们使用CMD命令执行此操作。注意,我们需要通过指定使应用程序在外部可见(即从容器外部)--host=0.0.0.0

CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]

这是完整的Dockerfile。

# syntax=docker/dockerfile:1

FROM python:3.8-slim-buster

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

COPY . .

CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]

目录结构

回顾一下,我们在本地计算机上创建了一个目录,python-docker并使用Flask框架创建了一个简单的Python应用程序。我们还使用该requirements.txt文件收集了我们的要求,并创建了一个Dockerfile,其中包含用于构建映像的命令。Python应用程序目录结构现在看起来像:

python-docker
|____ app.py
|____ requirements.txt
|____ Dockerfile

建立影像

现在我们已经创建了Dockerfile,让我们构建映像。为此,我们使用docker build命令。该docker build命令从Dockerfile和“上下文”构建Docker映像。构建的上下文是位于指定PATH或URL中的文件集。Docker构建过程可以访问此上下文中的任何文件。

构建命令可以选择带有--tag标志。标签用于设置图像名称和格式的可选标签name:tag。我们现在将省略可选项tag以简化操作。如果您不传递标签,Docker将使用“最新”作为其默认标签。您可以在构建输出的最后一行中看到这一点。

让我们构建我们的第一个Docker映像。

$ docker build --tag python-docker .
[+] Building 2.7s (10/10) FINISHED
 => [internal] load build definition from Dockerfile
 => => transferring dockerfile: 203B
 => [internal] load .dockerignore
 => => transferring context: 2B
 => [internal] load metadata for docker.io/library/python:3.8-slim-buster
 => [1/6] FROM docker.io/library/python:3.8-slim-buster
 => [internal] load build context
 => => transferring context: 953B
 => CACHED [2/6] WORKDIR /app
 => [3/6] COPY requirements.txt requirements.txt
 => [4/6] RUN pip3 install -r requirements.txt
 => [5/6] COPY . .
 => [6/6] CMD [ "python3", "-m", "flask", "run", "--host=0.0.0.0"]
 => exporting to image
 => => exporting layers
 => => writing image sha256:8cae92a8fbd6d091ce687b71b31252056944b09760438905b726625831564c4c
 => => naming to docker.io/library/python-docker

查看本地图像

要查看本地计算机上的图像列表,我们有两个选择。一种是使用CLI,另一种是使用Docker Desktop。当我们当前在终端中工作时,让我们看一下使用CLI列出图像。

要列出图像,只需运行docker images命令。

$ docker images
REPOSITORY      TAG               IMAGE ID       CREATED         SIZE
python-docker   latest            8cae92a8fbd6   3 minutes ago   123MB
python          3.8-slim-buster   be5d294735c6   9 days ago      113MB

您应该至少看到列出的两个图像。一个用于基本图像3.8-slim-buster,另一个用于我们刚刚构建的图像python-docker:latest

标记图片

如前所述,图像名称由斜杠分隔的名称组成。名称部分可能包含小写字母,数字和分隔符。分隔符定义为一个句点,一个或两个下划线或一个或多个破折号。名称组件不能以分隔符开头或结尾。

图像由清单和图层列表组成。此时,除了“标记”指向这些工件的组合之外,不必过多担心清单和图层。一个图像可以有多个标签。让我们为构建的图像创建第二个标签,并查看其图层。

要为我们上面构建的图像创建一个新标签,请运行以下命令。

$ docker tag python-docker:latest python-docker:v1.0.0

docker tag命令为图像创建一个新标签。它不会创建新图像。标签指向相同的图像,并且是引用图像的另一种方法。

现在,运行docker images命令以查看我们的本地图像列表。

$ docker images
REPOSITORY      TAG               IMAGE ID       CREATED         SIZE
python-docker   latest            8cae92a8fbd6   4 minutes ago   123MB
python-docker   v1.0.0            8cae92a8fbd6   4 minutes ago   123MB
python          3.8-slim-buster   be5d294735c6   9 days ago      113MB

您会看到我们有两个以开头的图像python-docker。我们知道它们是同一张图片,因为如果您查看该IMAGE ID列,您会发现两个图片的值相同。

让我们删除刚刚创建的标签。为此,我们将使用rmi命令。该rmi命令代表删除图像。

$ docker rmi python-docker:v1.0.0
Untagged: python-docker:v1.0.0

请注意,Docker的响应告诉我们,该映像尚未删除,而只是“未标记”。您可以通过运行docker images命令进行检查。

$ docker images
REPOSITORY      TAG               IMAGE ID       CREATED         SIZE
python-docker   latest            8cae92a8fbd6   6 minutes ago   123MB
python          3.8-slim-buster   be5d294735c6   9 days ago      113MB

带有标记的图像:v1.0.0已被删除,但我们python-docker:latest的机器上仍具有可用的标记。

下一步

在本模块中,我们看了如何设置示例Python应用程序,该示例程序将在本教程的其余部分中使用。我们还创建了一个Dockerfile,用于构建Docker映像。然后,我们看了一下标记图像和删除图像的过程。在下一个模块中,我们将研究如何:

将图像作为容器运行

反馈

通过提供您的反馈帮助我们改善此主题。通过在Docker Docs GitHub存储库中创建问题,让我们知道您的想法。或者,创建PR以建议更新。


python构建图像dockerfile