使用 Azure 容器应用和 PostgreSQL 生成和部署 Python Web 应用

本文是有关如何将 Python Web 应用容器化和部署到 Azure 容器应用的教程的一部分。 容器应用让你能够部署容器化应用,而无需管理复杂的基础结构。

本部分教程将介绍如何容器化和部署 Python 示例 Web 应用(Django 或 Flask)。 具体而言,就是在云中生成容器映像,然后再将其部署到 Azure 容器应用。 定义的环境变量可使容器应用连接到 Azure Database for PostgreSQL - 灵活服务器实例,而示例应用程序会在该实例中存储数据。

此服务示意图重点介绍了本文所涉及的组件:生成和部署容器映像。

《教程 - 在 Azure 容器应用上部署 Python 应用》中的服务的屏幕截图。突出显示的部分是本文所涉及的内容。

获取示例应用

分叉并将示例代码克隆到开发人员环境。

步骤 1. 转到示例应用程序(DjangoFlask)的 GitHub 存储库,然后选择“分叉”。

请按照以下步骤将目录分叉到 GitHub 帐户。 也可以直接将代码存储库下载到本地计算机,而无需分叉或 GitHub 帐户,但这样无法设置教程稍后将讨论的 CI/CD。

步骤 2. 使用 git clone 命令将分叉的存储库克隆到 python-container 文件夹中:

# Django
git clone https://github.com/$USERNAME/msdocs-python-django-azure-container-apps.git python-container

# Flask
# git clone https://github.com/$USERNAME/msdocs-python-flask-azure-container-apps.git python-container

步骤 3. 更改目录。

cd python-container

从 Web 应用代码生成容器映像

完成这些步骤后,将获得一个 Azure 容器注册表,其中包含根据示例代码生成的一个 Docker 容器映像。

可以在 Azure Cloud Shell 中或装有 Azure CLI 的工作站上运行 Azure CLI 命令。

步骤 1. 使用“az group create”命令创建资源组。

az group create \
--name pythoncontainer-rg \
--location <location>

<location> 是命令 az account list-locations -o table 输出中的 Azure 位置 Name 值之一。

步骤 2. 使用 az acr create 命令创建一个容器注册表。

az acr create \
--resource-group pythoncontainer-rg \
--name <registry-name> \
--sku Basic \
--admin-enabled

<registry-name> 在 Azure 中必须唯一,并且包含 5-50 个字母数字字符。

可以通过以下方式来查看为管理员创建的凭据:

az acr credential show \
--name <registry-name> \
--resource-group pythoncontainer-rg

步骤 3. 使用 az acr login 命令登录注册表。

az acr login --name <registry-name>

该命令会在名称中添加“azurecr.io”,以创建完全限定的注册表名称。 如果成功登录,将出现“登录成功”消息。 如果访问注册表的订阅不同于创建注册表的订阅,请使用 --suffix 开关。

步骤 4. 使用 az acr build 命令生成映像。

az acr build \
--registry <registry-name> \
--resource-group pythoncontainer-rg \
--image pythoncontainer:latest .

请注意:

  • 命令末尾的点 (".") 表示要生成的源代码的位置。 如果不是在示例应用根目录下运行此命令,请指定代码的路径。

  • 如果在 Azure Cloud Shell 中运行该命令,请使用 git clone 首先将存储库拉入 Cloud Shell 环境,然后将目录更改为项目的根目录,以便正确理解点 (".") 的含义。

  • 如果不使用 -t(与 --image 相同)选项,则命令会将本地上下文生成排入队列,而不会将其推送到注册表。 在不推送的情况下生成映像可用于检查映像是否已生成。

步骤 5。 使用 az acr repository list 命令确认容器映像已创建。

az acr repository list --name <registry-name>

创建 PostgreSQL 灵活服务器实例

示例应用程序(DjangoFlask)将餐厅评论数据存储在 PostgreSQL 数据库中。 在这些步骤中,将创建包含数据库的服务器。

可以在 Azure Cloud Shell 中或装有 Azure CLI 的工作站上运行 Azure CLI 命令。

步骤 1. 使用 az postgres flexible-server create 命令在 Azure 中创建 PostgreSQL 服务器。 此命令需要运行几分钟才能完成的情况并不少见。

az postgres flexible-server create \
   --resource-group pythoncontainer-rg \
   --name <postgres-server-name>  \
   --location <location> \
   --admin-user <admin-username> \
   --admin-password <admin-password> \
   --sku-name Standard_D2s_v3 \
   --public-access 0.0.0.0 
  • “pythoncontainer-rg”→ 本教程中使用的资源组名称。 如果使用的是其他名称,请更改此值。

  • <postgres-server-name> → PostgreSQL 数据库服务器名称。 此名称必须在所有 Azure 中唯一。 服务器终结点为“https://<postgres-server-name>.postgres.database.azure.com”。 允许的字符包括 "A"-"Z"、"0"-"9" 和 "-"。

  • location → 使用用于 Web 应用的同一个位置。 <location> 是命令 az account list-locations -o table 输出中的 Azure 位置 Name 值之一。

  • <admin-username> → 管理员帐户的用户名。 它不能为“azure_superuser”、“admin”、“administrator”、“root”、“guest”或“public”。 本教程使用“demoadmin”。

  • admin-password:管理员用户的密码。 密码必须包含以下三个类别的 8 到 128 个字符:英文大写字母、英文小写字母、数字和非字母数字字符。

    重要

    创建用户名或密码时不要使用“$”字符。 之后,将使用这些值来创建环境变量,其中的“$”字符在用于运行 Python 应用的 Linux 容器中具有特殊含义。

  • <sku-name> → 定价层和计算配置的名称,例如“Standard_D2s_v3”。 有关详细信息,请参阅 Azure Database for PostgreSQL 定价。 要列出可用的 SKU,请使用 az postgres flexible-server list-skus --location <location>

  • <public-access> → 使用“0.0.0.0”,它允许从任何 Azure 服务(如容器应用)对服务器进行公开访问。

注意

如果计划使用 Azure CLI 以外的工具从本地工作站运行 PostgreSQL 服务器,则需要使用 az postgres flexible-server firewall-rule create 命令来添加防火墙规则。

在服务器上创建数据库

至此,你就拥有了一个 PostgreSQL 服务器。 在本部分中,你将在服务器上创建一个数据库。

可以在本地环境中使用 PostgreSQL 交互式终端 psqlAzure Cloud Shell,后者也可在 Azure 门户中访问。 在使用 psql 时,使用 Cloud Shell 通常会更方便,因为 shell 中包含了所有的依赖项。

步骤 1. 使用 psql 连接到数据库。

psql --host=<postgres-server-name>.postgres.database.azure.com \
     --port=5432 \
     --username=demoadmin@<postgres-server-name> \
     --dbname=postgres

其中 <postgres-server-name> 是 PostgreSQL 服务器的名称。 命令将提示输入管理员密码。

如果连接时遇到问题,请重启数据库并重试。 如果从本地环境连接,则必须将 IP 地址添加到数据库服务的防火墙规则列表中。

步骤 2. 创建数据库。

postgres=> 提示符下键入:

CREATE DATABASE restaurants_reviews;

命令末尾的分号 (";") 必不可少。 要验证数据库是否创建成功,请使用 \c restaurants_reviews 命令。 键入 \? 可显示帮助,键入 \q 会退出。

还可以使用 Azure Data Studio 或任何其他支持 PostgreSQL 的集成开发环境连接到 Azure PostgreSQL 灵活服务器并创建数据库。

将 Web 应用部署到容器应用中

容器应用部署到容器应用环境中,这些环境将起到安全边界的作用。 在以下步骤中,你将创建环境和环境中的容器,并配置容器以便使网站对外可见。

步骤 1. 登录 Azure 并进行身份验证(如需要)。

az login

步骤 2. 使用 az extension add 命令安装或升级 Azure 容器应用的扩展。

az extension add --name containerapp --upgrade

步骤 3. 使用 az containerapp env create 命令来创建容器应用环境。

az containerapp env create \
--name python-container-env \
--resource-group pythoncontainer-rg \
--location <location>

<location> 是命令 az account list-locations -o table 输出中的 Azure 位置 Name 值之一。

步骤 4. 获取 Azure 容器注册表的登录凭据。

az acr credential show -n <registry-name>

使用从命令输出中返回的用户名和其中一个密码。

步骤 5。 使用 az containerapp create 命令在环境中创建容器应用。

az containerapp create \
--name python-container-app \
--resource-group pythoncontainer-rg \
--image <registry-name>.azurecr.io/pythoncontainer:latest \
--environment python-container-env \
--ingress external \
--target-port 8000 \
--registry-server <registry-name>.azurecr.io \
--registry-username <registry-username> \
--registry-password <registry-password> \
--env-vars <env-variable-string>
--query properties.configuration.ingress.fqdn

<env-variable-string> 是一个由空格分隔的值组成的字符串,格式为 key="value",其值如下。

  • AZURE_POSTGRESQL_HOST=<postgres-server-name>.postgres.database.azure.com
  • AZURE_POSTGRESQL_DATABASE=restaurants_reviews
  • AZURE_POSTGRESQL_USERNAME=demoadmin
  • AZURE_POSTGRESQL_PASSWORD=<db-password>
  • RUNNING_IN_PRODUCTION=1
  • AZURE_SECRET_KEY=<YOUR-SECRET-KEY>

使用 python -c 'import secrets; print(secrets.token_hex())' 的输出生成 AZURE_SECRET_KEY 值。

下面是一个示例:--env-vars AZURE_POSTGRESQL_HOST="my-postgres-server.postgres.database.azure.com" AZURE_POSTGRESQL_DATABASE="restaurants_reviews" AZURE_POSTGRESQL_USERNAME="demoadmin" AZURE_POSTGRESQL_PASSWORD="somepassword" RUNNING_IN_PRODUCTION="1" AZURE_SECRET_KEY=asdfasdfasdf

步骤 7. 仅对 Django 迁移并创建数据库架构。 (在 Flask 示例应用中,这一步将自动完成,因此你可以跳过。)

使用 az containerapp exec 命令进行连接:

az containerapp exec \
--name python-container-app \
--resource-group pythoncontainer-rg

然后,在 shell 命令提示符下键入 python manage.py migrate

不需要为容器的修订版本进行迁移。

步骤 8。 测试网站。

之前输入的 az containerapp create 命令会输出一个应用程序 URL,可以用它来浏览应用程序。 URL 以“azurecontainerapps.io”结尾。 在浏览器中导航到 URL。 或者,也可以使用 az containerapp browse 命令。

下面是添加了一家餐厅和两条评论后的示例网站。

显示了本教程中生成的示例网站的屏幕截图。

排查部署问题

  • 你忘记了用于访问网站的应用程序 Url。

    • 在 Azure 门户中,转到容器应用的“概述”页面,然后查找“应用程序 URL”。
    • 在 VS Code 中,转到“Azure 视图”(Ctrl+Shift+A),并展开正在处理的订阅。 展开“容器应用”节点,然后展开托管环境,然后右键单击 python-container-app 并选择“浏览”。 它将使用应用程序 URL 来打开浏览器。
    • 在 Azure CLI 中使用命令 az containerapp show -g pythoncontainer-rg -n python-container-app --query properties.configuration.ingress.fqdn
  • 在 VS Code 中,在 Azure 中生成映像任务返回错误。

    • 如果“错误:未能下载上下文。 请检查 URL 是否不正确。“出现在 VS Code 的“输出”窗口中,则在 Docker 扩展中刷新注册表。 要刷新,请选择 Docker 扩展,转到“注册表”部分,找到注册表并将其选中。
    • 如果再次运行在 Azure 中生成映像任务,请检查上次运行的注册表是否存在,如果存在,请使用它。
  • 在创建容器应用期间,你会在 Azure 门户中看到一个包含“无法访问 ACR '<name>.azurecr.io'”的访问错误。

    • 当 ACR 上的管理员凭据被禁用时就会出现此错误。 要在门户中检查管理员状态,请转到 Azure 容器注册表,选择“访问密钥”资源,并确保“管理员用户”已启用。
  • 容器映像没有出现在 Azure 容器注册表中。

    • 检查 Azure CLI 命令输出或 VS Code 输出,并查找确认成功的消息。
    • 检查使用 Azure CLI 的构建命令或 VS Code 任务提示中是否正确指定了注册表的名称。
    • 确保证书没有过期。 例如,在 VS Code 中,在 Docker 扩展中找到目标注册表并刷新。 在 Azure CLI 中运行 az login
  • 网站返回“错误请求 (400)”。

    • 检查传入容器的 PostgreSQL 环境变量。 400 错误通常表示 Python 代码无法连接 PostgreSQL 实例。
    • 本教程中使用的示例代码会检查是否存在容器环境变量 RUNNING_IN_PRODUCTION,该变量可以设置为任何值,如“1”。
  • 网站返回“未找到 (404)”。

    • 检查“概述”页面上容器的“应用程序 Url”。 如果应用程序 Url 包含“internal”一词,则入口设置不正确。
    • 检查容器的入口。 例如,在 Azure 门户中,转到容器的“入口”资源,确保启用“HTTP 入口”,然后选择“接受来自任意位置的流量”。
  • 网站无法启动,你会看到“流超时”,或者未返回任何结果。

    • 查看日志。
      • 在 Azure 门户中,转到容器应用程序的修订版管理资源并检查容器的“配置状态”。
        • 如果为“预配”,则等预配配完成。
        • 如果“失败”,则选择修订版并查看控制台日志。 选择显示“生成时间”、“Stream_s”和 “Log_s ”列的顺序。 首先按最新日志排序,然后在“Stream_s”列查找 Python stderrstdout 消息。 Python 的“print”输出将是 stdout 消息。
      • 通过 Azure CLI,使用 az containerapp logs show 命令。
    • 如果使用 Django 框架,请检查数据库中是否存在 restaurants_reviews 表。 如果没有,请使用控制台访问容器并运行 python manage.py migrate

下一步