geekdoc-python-zh/docs/pythonland/71.md

9.4 KiB
Raw Permalink Blame History

如何使用 Docker 来容器化您的 Python 项目

原文:https://python.land/deployment/containerize-your-project

您的 Python 项目是否难以从源代码构建难以与同事共享或者难以部署到生产环境中Docker 是为您的 Python 项目解决这一问题的理想工具。

对于那些难以部署的项目,存在几个原因,这里只是几个:

  • 该项目需要大量的依赖。
  • 该项目需要一些库的过时版本或一个过时的编译器。一旦您安装了它,其他项目可能会依次中断。
  • 你运行的是 Windows 或 Mac但该软件是为构建和运行 Linux 而设计的

出于类似的原因,在生产环境中运行您的软件也很困难!

如果你正面临这些问题,最好知道有一个简单的解决方法。它不需要虚拟化,而是使用一种叫做容器化的原理。简而言之,容器化是虚拟化的一个非常轻量级的替代方案。容器化世界中的事实标准是 Docker所以我们将用它来容器化一个示例 Python 项目。


目录

什么是容器?

容器是一个拥有运行软件所需的一切的实体。它包括:

  • 你的软件
  • 所有依赖项
  • 可能需要的所有系统工具和库

容器就像虚拟机,但是更轻量级。例如,他们几乎立即开始。容器只虚拟化操作系统,而 VM 虚拟化整个机器及其所有硬件。如果你想知道这到底是如何工作的,请阅读优秀的官方文档。

Docker containers are a bit like Virtual Machines, but much more lightweight

Docker 容器有点像虚拟机,但是它们不需要运行整个操作系统

码头集装箱已经成为一种标准。它们可以在任何地方运行:从您的开发 PC 到自托管服务器,再到像 Amazon、Google 和 Azure 这样的云托管服务。容器使得打包和运输你的软件变得容易,并且为它的运行提供了一个定义良好的环境。


什么是图像?

Docker 容器总是基于图像。首先定义一个图像,然后基于它启动一个或多个容器。您可以在一个文件(称为Dockerfile)中定义一个图像,这个文件可以和您的代码一起被签入一个像 git 这样的 VCS。这允许您记录和创建运行代码所需的确切环境。

你不必从头开始建立一个形象。许多软件项目提供了将软件容器化的映像。对于几乎所有的计算机语言,包括 Python都有多种基本映像可供选择。

就像 Python 类一样您可以用自己的细节来扩展这样的图像我将在下面演示。通过这样做您可以在现有图像上添加一个新层。由于这种分层Docker 图像可以非常高效地存储和构建。例如,许多映像可能都共享同一个 Debian Linux 基本映像,并使用它们自己特定的软件需求来扩展它:

An image showing how docker is build from multiple layers

Docker 图像由多个层构建而成


将您的 Python 项目归档

为你的软件创建一个容器是非常容易的。做了第一个 Docker 形象后,我的想法大致是这样的:“就这些?我一定是跳过了一步!”

在这里,我将创建一个 Python 项目作为示例,但这对于其他语言来说同样简单。此外,我将有意在 Windows 上工作,尽管我是一个真正的 Linux 迷。最重要的是,我根本不打算在 Windows 上安装 Python只是为了证明容器化的强大。

Thank you for reading my tutorials. I write these in my free time, and it requires a lot of time and effort. I use ads to keep writing these free articles, I hope you understand! Support me by disabling your adblocker on my website or, alternatively, buy me some coffee. It's much appreciated and allows me to keep working on this site!

如果你愿意,你可以跟着去。这篇文章包含你需要的一切。或者,您也可以从 Github 中克隆这段代码。

一个简单的网络应用

假设我们想使用 Flask 创建一个 web 服务。它有一些依赖关系,在Pipfile中定义,与 Pipenv 一起使用。

我从简单的开始,下面的Pipfile:

[packages]
Flask = "*"

现在,我们将创建一个 Python 文件,只是为了证明事情按预期运行。我称之为app.py:

print("Hello world")

创建自己的 Docker Python 映像

接下来,我们需要创建一个定义容器的Dockerfile。如今,大多数项目都以 Docker 容器的形式提供软件的官方版本。在谷歌上快速搜索后,发现 Python 也是如此。他们甚至给了我们一个开始的例子。

他们的例子是基于 virtualenv 的,我们更喜欢 Pipenv所以它需要一些修改。这是我想到的:

FROM python:3
WORKDIR /usr/src/app
COPY Pipfile ./
RUN pip install --no-cache-dir pipenv && pipenv install
COPY *.py .
CMD [ "python", "./app.py" ]

要了解更多关于Dockerfile的语法,最好直接去 Dockerfiles 上的官方文档。

要构建您的容器,您需要运行docker build命令。如果您使用的是高级 IDE如 VSCode您将能够安装 Docker 扩展,允许您简单地右键单击Dockerfile,给它一个名称(称为标记),然后开始构建。在这种情况下,我更喜欢命令行,因为它能准确地显示我们在做什么,并让我们控制所有选项。因此,我们将在命令行上构建我们的映像:

C:\dev\python-docker> docker build -t my_webservice:latest .

让我们来分解一下:

  • 我们正在构建一个映像,并用名称 my_service 和版本latest对其进行标记(这是默认的,所以您可以忽略它)
  • 这个点仅仅意味着 Docker 需要在当前目录中查找 Docker 文件

第一次运行时,会有很多活动:

  • Docker 首先开始提取 python docker 图像
  • 接下来,我们将工作目录设置为/usr/src/app
  • 我们将 zip 文件复制到工作目录中
  • 我们运行 pip install 来安装 pipenv
  • 紧接着,我们运行 pipenv install 来安装我们的依赖项
  • 最后,我们将所有 python 文件复制到工作目录中

您应该会看到类似下面截图的内容:

Docker in action, pulling images

Docker 正在运行,提取图像

我们的图像完成了,我们可以用 docker run 运行它。让我们试试:

PS C:\dev\python-docker> docker run my_webservice
Hello world
PS C:\dev\python-docker>

改善我们的 Python Docker 映像

我们已经做好了基础工作,现在让我们创建一个实际的 web 服务。修改app.py使其看起来像这个基本的烧瓶示例:

from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
    return 'Hello, World!'

因为我们现在正在运行 Flask 应用程序,所以我们也需要修改 docker 文件中的 CMD:

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

如您所见,我们需要 Flask 来监听所有网络接口。否则,它将只是监听 docker 容器内的 localhost外部世界将无法访问它。

使用与之前相同的命令重建 Docker 映像:

C:\dev\python-docker> docker build -t my_webservice:latest .

因为我们将在端口 5000 (Flask 的默认端口)上运行实际的服务器所以我们需要公开这个端口。为了额外的安全和防止端口重叠Docker 默认情况下不会暴露端口。Docker 提供了强大的隔离,这也更安全!您可以使用-p命令行选项将一个端口从容器映射到 PC 上的一个端口:

C:\dev\python-docker> docker run -p 5000:5000 my_webservice
 * Environment: production
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

现在转到 http://127.0.0.1:5000/来看看这个服务的运行情况。您应该得到一个显示“Hello world”的页面并且应该在命令行上看到一个日志条目。

使用我预先构建的图像

如果您不想经历所有的步骤,但是仍然想测试运行这个例子,您可以通过使用下面的命令从我的 public Docker Hub account 中提取图像:

docker pull eriky/hello_world:latest

之后就可以用:docker run -p 5000:5000 eriky/hello_world开始镜像了。

如果你想从 GitHub 查看源代码,请点击这里的进入附带的库

继续学习

  • 了解如何使用持续集成自动构建和部署您的 Python 项目。
  • 如果你的应用程序成功了,这里有一些游击战术可以在不花费数百万的情况下扩展应用程序。