容器中的Python

在本教程中,您将学习如何:

  • 创建一个描述简单Python容器的Dockerfile文件。
  • 构建、运行并验证DjangoFlask或通用Python应用程序的功能。
  • 调试在容器中运行的应用程序。

先决条件

  • Install Docker 在您的机器上并添加到系统路径中。

  • 在Linux上,您还应该为非root用户账户启用Docker CLI,该账户将用于运行VS Code。

  • Docker扩展。要安装扩展,请打开扩展视图(⇧⌘X (Windows, Linux Ctrl+Shift+X)),搜索docker以过滤结果并选择由Microsoft开发的Docker扩展。

    选择Docker扩展

创建一个Python项目

如果您还没有Python项目,请按照教程Python入门进行操作。

注意: 如果你想将一个完整的Django或Flask网络应用容器化,你可以从以下示例之一开始:

注意: 对于本教程,请确保使用示例仓库的tutorial分支。

在验证您的应用程序运行正常后,您现在可以将您的应用程序容器化。

将Docker文件添加到项目中

  1. 在VS Code中打开项目文件夹。

  2. 打开命令面板 (⇧⌘P (Windows, Linux Ctrl+Shift+P)) 并选择Docker: 添加Docker文件到工作区...:

    将Dockerfile添加到Python项目

  3. 当提示选择应用类型时,选择Python: DjangoPython: FlaskPython: General作为应用类型。在本教程中,我们将重点介绍Python: General的情况,但也会包含Django和Flask的注意事项。

  4. 输入应用程序入口点的相对路径。这不包括您开始的工作区文件夹。如果您按照Python入门教程使用hello.py创建了一个Python应用程序,请选择该文件。

    Django: 选择 manage.py(根文件夹)或 subfolder_name/manage.py。请参阅 官方 Django 文档

    Flask: 选择创建Flask实例的路径。请参阅官方Flask文档

    提示: 你也可以输入一个文件夹的路径,只要这个文件夹包含一个__main__.py文件。

  5. 选择端口号。我们建议选择1024或以上的端口号,以减轻以root用户身份运行带来的安全问题。任何未使用的端口都可以,但Django和Flask使用标准的默认端口。

    Django: 默认端口 8000。

    Flask: 默认端口是5000。

  6. 当提示包含Docker Compose时,如果您不想要Docker Compose文件,请选择。如果您选择,您将需要验证Dockerfilewsgi.py文件的路径,以成功运行Compose Up命令。Compose通常用于同时运行多个容器。

  7. 有了所有这些信息,Docker 扩展会创建以下文件:

    • 一个Dockerfile。要了解有关此文件中IntelliSense的更多信息,请参阅概述

    • 一个.dockerignore文件,通过排除不需要的文件和文件夹(如.git.vscode__pycache__)来减小镜像大小。

    • 如果您正在使用Docker Compose,一个docker-compose.ymldocker-compose.debug.yml 文件。

    • 如果尚不存在,则创建一个用于捕获所有应用程序依赖项的requirements.txt文件。

    重要提示: 要使用我们的设置,Python框架(Django/Flask)和Gunicorn 必须包含requirements.txt文件中。如果虚拟环境/主机已经安装了这些先决条件,并且应该与容器环境相同,请通过在终端中运行pip freeze > requirements.txt来确保应用程序依赖项被移植过来。这将覆盖您当前的requirements.txt文件。

(可选)向镜像添加环境变量

此步骤不是必需的,但包含它是为了帮助您了解如何添加需要在容器环境中设置的环境变量。

Docker 扩展通过使用 IntelliSense 提供自动补全和上下文帮助,帮助您编写 Dockerfiles。要查看此功能的实际效果:

  1. 打开Dockerfile

  2. EXPOSE语句下方,输入⌃Space (Windows, Linux Ctrl+Space)以触发IntelliSense并滚动到ENV

    向Dockerfile添加环境变量

  3. 按下 TabEnter 来完成语句,然后将 key 设置为变量的名称,并设置 value

有关在Dockerfile中设置和使用环境变量的更多信息,请参阅Docker文档中的ENV指令和环境替换部分。

Gunicorn 对 Django 和 Flask 应用的修改

为了给Python网络开发者提供一个良好的起点,我们选择使用Gunicorn作为默认的网络服务器。由于它在默认的Dockerfile中被引用,因此它被包含在requirements.txt文件中作为依赖项。如果你在requirements.txt中没有看到它,请运行pip install gunicorn,然后运行pip freeze > requirements.txt以重新生成requirements.txt文件。

  • Django: 要使用Gunicorn,它必须绑定到一个应用程序可调用对象(应用程序服务器用来与你的代码通信的入口点)。这个可调用对象在Django应用程序的wsgi.py文件中声明。为了实现这种绑定,Dockerfile中的最后一行写道:

    CMD ["gunicorn", "--bind", "0.0.0.0:8000", "{workspace_folder_name}.wsgi"]
    

    如果你的项目没有遵循Django的默认项目结构(即工作区文件夹和一个与工作区同名的子文件夹中的wsgi.py文件),你必须在Dockerfile中覆盖Gunicorn的入口点以定位正确的wsgi.py文件。

    如果你的wsgi.py文件在根文件夹中,上述命令中的最后一个参数将是"wsgi"。在子文件夹中,参数将是"subfolder1_name.subfolder2_name.wsgi"

  • Flask: 要使用Gunicorn,它必须绑定到一个应用程序可调用对象(应用程序服务器用来与您的代码通信的对象)作为入口点。这个可调用对象与您创建的Flask实例的文件位置变量名称相对应。根据官方Flask文档,用户通常在主模块或包的__init__.py文件中以这种方式创建Flask实例:

    from flask import Flask
    app = Flask(__name__) # Flask instance named app
    

    为了实现这个绑定,Dockerfile 的最后一行说:

    CMD ["gunicorn", "--bind", "0.0.0.0:5000", "{subfolder}.{module_file}:app"]
    

    Docker: 添加Docker文件到工作区...命令期间,您配置了Flask实例的路径,然而,Docker扩展假定您的Flask实例变量名为app。如果不是这种情况,您必须在Dockerfile中更改变量名。

    如果你的主模块位于根文件夹中,文件名为main.py,并且Flask实例变量名为myapp,那么上述命令中的最后一个参数将是"main:myapp"。在子文件夹中,参数将是"subfolder1_name.subfolder2_name.main:myapp"

构建、运行和调试容器

Docker: 添加Docker文件到工作区... 命令会自动创建一个Docker启动配置,以便在调试模式下构建和运行您的容器。要调试您的Python应用程序容器:

  1. 导航到包含应用程序启动代码的文件,并设置断点。

  2. 导航到运行和调试并选择Docker: Python - GeneralDocker: Python - DjangoDocker: Python - Flask,视情况而定。

    选定的Docker调试配置

  3. 使用 F5 键开始调试。

    • The Docker image builds.
    • The Docker container runs.
    • The python debugger stops at the breakpoint.
  4. 单步跳过这一行。

  5. 准备就绪后,请按继续。

Docker 扩展将启动您的浏览器到一个随机映射的端口:

Django网站启动

提示: 要修改您的Docker构建设置,例如更改镜像标签,请导航到.vscode -> tasks.json中的docker-build任务下的dockerBuild属性。使用文件中的IntelliSense(⌃Space (Windows, Linux Ctrl+Space))以显示所有其他有效的指令。

使用 Docker 资源管理器

Docker Explorer 提供了一个交互式体验来检查和管理 Docker 资产,如容器、镜像等。要查看示例:

  1. 导航到Docker Explorer。

  2. 容器标签中,右键点击您的容器并选择查看日志

    查看容器的日志

  3. 输出将显示在终端中。

在Azure中构建镜像

您可以使用命令Azure Container Registry: Build Image in Azure来构建一个镜像,然后可以将其部署到Azure App Service或Azure Container Apps。

  1. 安装Azure资源扩展。打开命令面板 (⇧⌘P (Windows, Linux Ctrl+Shift+P)) 并搜索命令Azure: 登录。如果您没有Azure账户,可以注册免费试用

  2. 有两种方法可以在Azure中调用构建命令。你可以右键点击Dockerfile,然后选择在Azure中构建镜像。你也可以使用命令面板 (⇧⌘P (Windows, Linux Ctrl+Shift+P)) 并搜索命令Azure Container Registry: 在Azure中构建镜像

    在Azure中调用构建镜像命令

  3. 选择构建镜像的名称和标签。您将使用此名称和标签在容器注册表中识别它。

    选择构建镜像的名称和标签。

  4. 选择您想要使用的Azure订阅。

  5. 选择一个现有的Azure容器注册表,或创建一个新的。创建新注册表时,系统会要求您提供名称、资源组、位置以及定价选项,如基本、标准或高级。您可以在定价 - 容器注册表上阅读这些选项的成本。

  6. 指定基础操作系统,Linux 或 Windows。此选择必须与 Dockerfile 一致。

    选择构建镜像的基础操作系统

构建镜像的过程可能需要几分钟。您可以在终端中跟踪进度。如果遇到错误(Error: failed to download context.),请尝试使用容器注册表上的刷新选项,然后请求另一次构建。在重新构建之前,请手动删除旧镜像。

部署到 Azure App Service 或 Azure Container Apps

一旦容器镜像构建完成,它应该会出现在容器注册表中,并带有你指定的标签。现在它已经构建完成,你可以将其部署到Azure App Service或Azure Container Apps。对于部署到Azure App Service,推荐使用Azure App Service扩展,而对于部署到Azure Container Apps,则需要Azure Container Apps扩展。如果你安装了Azure Tools扩展包,你可以同时获得这两个扩展,该扩展包包含了一系列用于广泛Azure开发场景的工具。

  1. 右键点击图像标签并选择部署图像到Azure应用服务部署图像到Azure容器应用

    将镜像部署到Azure应用服务

  2. 提供网站的名称。这必须是一个唯一的名称,对于Django应用程序,它还必须在settings.py文件中的ALLOWED_HOSTS列表中列为有效的主机名。

  3. 提供一个资源组、位置和应用服务计划。如果您刚开始使用,可以选择免费计划。

  4. 图像已部署;该过程可能需要几分钟。一旦部署完成,会出现一个通知,其中包含一个按钮,您可以使用它来访问站点。您也可以使用站点的地址,{appname}.azurewebsites.net,其中{appname}是您在创建时为其指定的名称。如果一开始不起作用,请几分钟后再试。最初的几次尝试超时或返回错误并不罕见。这只是意味着应用服务尚未准备好接收请求。

  5. 在应用程序代码中进行一个小改动,使其在其中一个页面上可见,并保存文件。

  6. 使用Azure图标打开资源视图,并展开订阅节点以找到您在上一步中部署的App Service。

  7. 右键单击App Service节点并查看可用的选项。选择部署到Web应用,然后指定您的应用文件夹以进行部署。

    部署到Web应用

    当警告这将覆盖之前的部署时,选择部署以确认。

    这可能需要几分钟时间;您可以在终端窗口中监控进度。完成后,将提供一个访问站点的按钮。

    浏览网站按钮

    使用按钮并验证您的更改是否反映在网站上。

恭喜你,你已经使用VS Code中的Python创建并部署了一个托管在云端并实时在互联网上的网站!

释放资源

Azure门户中,删除资源组以释放您在此练习期间创建的所有资源。

下一步

你已经完成了!现在你的容器已经准备好了,你可能想要: