教程:将 PHP、MySQL 和 Redis 应用部署到 Azure 应用服务

本教程介绍如何在 Azure 应用服务中创建安全的 PHP 应用连接到 MySQL 数据库(使用 Azure Database for MySQL 灵活服务器)。 你还将部署 Azure Cache for Redis 以在应用程序中启用缓存代码。 Azure 应用服务是一种可缩放程度高、支持自修补的 Web 托管服务,可轻松地在 Windows 或 Linux 上部署应用。 完成本教程后,Linux 上的 Azure 应用服务中将会运行一个 Laravel 应用。

标题为“任务列表”的 Azure 应用示例的屏幕截图,显示了添加的新任务。

先决条件

1 - 运行示例

首先,将示例数据驱动的应用设置为起点。 为方便起见,示例存储库包含一个开发容器配置。 开发容器包含开发应用程序所需的所有内容,包括示例应用程序所需的数据库、缓存和所有环境变量。 开发容器可以在 GitHub codespace 中运行,这意味着可使用 Web 浏览器在任何计算机上运行示例。

步骤 1:在新浏览器窗口中:

  1. 登录到 GitHub 帐户。
  2. 导航到 https://github.com/Azure-Samples/laravel-tasks/fork
  3. 选择“创建分支”。

屏幕截图显示如何创建示例 GitHub 存储库分支。

步骤 2:在 GitHub 分支中:

  1. 选择“代码”“在主分支上创建 codespace”。> 要设置好 codespace 需要几分钟时间。 此外,提供的 .env 文件已包含 Laravel 需要在本地运行的虚拟APP_KEY变量

显示如何在 GitHub 中创建 codespace 的屏幕截图。

步骤 3:在 codespace 终端中

  1. 运行 composer install
  2. 使用 php artisan migrate 运行数据库迁移。
  3. 使用 php artisan serve 运行应用。
  4. 看到通知 Your application running on port 80 is available. 时,选择“在浏览器中打开”。 应在新的浏览器选项卡中看到该示例应用程序。若要停止应用程序,请键入 Ctrl+C

显示如何在 GitHub codespace 中运行示例应用程序的屏幕截图。

遇到问题? 检查故障排除部分

2 - 创建应用服务、数据库和缓存

此步骤创建 Azure 资源。 本教程中所使用的步骤会创建一组安全默认的资源,其中包括应用服务、Azure Database for MySQL 和 Azure Redis 缓存。 对于创建过程,需要指定:

  • Web 应用程序的名称。 它以 https://<app-name>-<hash>.<region>.azurewebsites.net 的形式用作应用的 DNS 名称的一部分。
  • 用于在全球范围内实际部署应用程序的区域。 它还用作应用的 DNS 名称的一部分。
  • 应用的运行时堆栈。 在此处选择要用于应用的 PHP 版本。
  • 应用程序托管计划。 它是一个定价等级,包括应用程序的一组功能和扩展容量。
  • 应用程序的资源组。 使用资源组可将应用程序所需的所有 Azure 资源分组到一个逻辑容器中。

登录到 Azure 门户并按照以下步骤创建 Azure 应用服务资源。

步骤 1:在 Azure 门户中:

  1. 在 Azure 门户顶部的搜索栏中,输入“Web 应用数据库”。
  2. 在“市场”标题下方,选择标记为“Web 应用 + 数据库”的项目。 还可以直接导航到创建向导

显示如何使用顶部工具栏中的搜索框查找“Web 应用 + 数据库”创建向导的屏幕截图。

步骤 2:在“创建 Web 应用 + 数据库”页上,按下面所述填写表单。

  1. 资源组:选择 “新建 ”并使用 msdocs-laravel-mysql-tutorial 的名称。
  2. 区域:你附近的任何 Azure 区域。
  3. 名称msdocs-laravel-mysql-XYZ ,其中 XYZ 是任意三个随机字符。 该名称在 Azure 中必须唯一。
  4. 运行时堆栈PHP 8.3
  5. 添加 Azure Cache for Redis?
  6. 托管计划基本。 准备就绪后,可以稍后纵向扩展到生产定价层。
  7. 默认情况下,选择 MySQL - 灵活服务器作为数据库引擎。 Azure Database for MySQL 是 Azure 上完全托管的 MySQL 数据库即服务,与最新的社区版本兼容。
  8. 选择“查看 + 创建”。
  9. 验证完成后,选择“创建”。

显示如何在“Web 应用 + 数据库”向导中配置新应用程序和数据库的屏幕截图。

步骤 3:该部署需要数分钟才能完成。 部署完成后,选择“转到资源”按钮。 你会直接转到应用服务应用,但以下资源现已创建:

  • 资源组:所有已创建资源的容器。
  • 应用服务计划:为应用服务定义计算资源。 现在基本层中建立了 Linux 计划。
  • 应用服务:表示应用并在应用服务计划中运行。
  • 虚拟网络:与应用服务应用集成,并隔离后端网络流量。
  • 专用终结点:虚拟网络中数据库服务器和 Redis 缓存的访问终结点。
  • 网络接口:表示专用 IP 地址,每个专用终结点各一个。
  • Azure Database for MySQL 灵活服务器:只能从专用终结点后面访问。 你的数据库和用户创建于此服务器上。
  • Azure Cache for Redis:只能通过其私有终结点访问。
  • 专用 DNS 区域:在虚拟网络中启用数据库服务器和 Redis 缓存的 DNS 解析。

屏幕截图显示已完成的部署过程。

3 - 保护连接机密

创建向导已经为你生成了连接变量作为应用设置。 但是,安全最佳做法是将机密完全保留在应用服务之外。 你将借助服务连接器把机密移动到密钥保管库,并将应用设置更改为密钥保管库引用

步骤 1:检索现有的连接字符串

  1. 在应用服务页面的左侧菜单中,选择“设置”>“环境变量”
  2. 选择 AZURE_MYSQL_PASSWORD
  3. “值”字段中的“添加/编辑应用程序”设置中,复制密码字符串供以后使用。 你看到的应用设置允许连接到受专用终结点保护的 MySQL 数据库和 Redis 缓存。 但是,机密直接保存在应用服务应用中,这不是最好的做法。 你将对此进行更改。

显示如何查看应用设置值的屏幕截图。

步骤 2:创建密钥保管库以安全管理机密

  1. 在顶部搜索栏中,键入“密钥保管库”,然后选择市场>密钥保管库
  2. 资源组中,选择 msdocs-laravel-mysql-tutorial
  3. 在“密钥保管库名称”中,键入仅包含字母和数字的名称。
  4. 在“区域”中,将其设置为资源组所在的同一位置。

显示如何创建密钥保管库的屏幕截图。

步骤 3:使用专用终结点保护密钥保管库

  1. 选择“网络”选项卡。
  2. 取消选择“启用公共访问”
  3. 选择“创建专用终结点”。
  4. 资源组中,选择 msdocs-laravel-mysql-tutorial
  5. 在对话框中,在“位置”中,选择与应用服务应用相同的位置。
  6. “名称”中,键入 msdocs-laravel-mysql-XYZVaultEndpoint
  7. 虚拟网络中,选择 msdocs-laravel-mysql-XYZVnet
  8. 在“子网”中,msdocs-laravel-mysql-XYZSubnet。
  9. 选择“确定”。
  10. 依次选择“查看 + 创建”、“创建”。 等待密钥保管库部署完成。 应会看到“部署已完成”。

屏幕截图显示了如何使用专用终结点保护密钥保管库。

步骤 4:配置 MySQL 连接器

  1. 在顶部搜索栏中,键入 msdocs-laravel-mysql,然后选择名为 msdocs-laravel-mysql-XYZ 的应用服务资源。
  2. 在应用服务页面的左侧菜单中,选择“设置”>“服务连接器”。 已经有两个连接器,这是应用创建向导为你创建的。
  3. 选中 MySQL 连接器旁边的复选框,然后选择“ 编辑”。
  4. 选择“身份验证”选项卡。
  5. 在“密码”中,粘贴你之前复制的密码。
  6. 选择“在密钥保管库中存储机密”。
  7. 在“密钥保管库连接”下,选择“创建新连接”。 在编辑对话框顶部打开“创建连接”对话框。

截图显示如何通过密钥保管库连接来编辑服务连接。

步骤 5:建立密钥保管库连接

  1. 在密钥保管库连接的“创建连接”对话框中,在“密钥保管库”中选择之前创建的密钥保管库
  2. 选择 审阅 + 创建
  3. 验证完成后,选择“创建”。

显示如何配置密钥保管库服务连接器的屏幕截图。

步骤 6:完成 MySQL 连接器设置

  1. 返回到“defaultConnector”编辑对话框。 在“身份验证”选项卡中,等待创建密钥保管库连接器。 完成后,“密钥保管库连接”下拉列表会自动选择相应选项。
  2. 选择“下一页:网络”。
  3. 选择“保存”。 等待“更新成功”通知出现

显示 defaultConnector 中选择的密钥保管库连接的屏幕截图。

步骤 7:将 Redis 连接器配置为使用密钥保管库机密

  1. 在“服务连接器”页中,选中 Cache for Redis 连接器旁边的复选框,然后选择“编辑”。
  2. 选择“身份验证”选项卡。
  3. 选择“在密钥保管库中存储机密”。
  4. 在“密钥保管库连接”下,选择创建的密钥保管库。
  5. 选择“下一页:网络”。
  6. 选择“配置防火墙规则以启用对目标服务的访问权限”。 应用创建向导已使用专用终结点保护 SQL 数据库。
  7. 选择“保存”。 等待“更新成功”通知出现

屏幕截图显示如何编辑 Cache for Redis 服务连接器来建立密钥保管库连接。

步骤 8:验证密钥保管库集成

  1. 在左侧菜单中,再次选择“设置”>“环境变量”。
  2. 在AZURE_MYSQL_PASSWORD旁边,选择“显示值”。 该值应为 @Microsoft.KeyVault(...),表明它是密钥保管库引用,因为机密现于密钥保管库中托管。
  3. 若要验证 Redis 连接字符串,请选择“AZURE_REDIS_CONNECTIONSTRING”旁边的“显示值”。

显示如何在 Azure 中查看 MySQL 密码值的屏幕截图。

总之,保护连接机密的过程包括:

  • 从应用服务应用的环境变量中检索连接机密。
  • 创建密钥保管库。
  • 使用系统分配的托管标识创建密钥保管库连接。
  • 更新服务连接器以将机密存储在密钥保管库中。

遇到问题? 检查故障排除部分


4 - 配置 Laravel 变量

步骤 1: 创建 CACHE_DRIVER 为应用设置。

  1. 在“应用设置”选项卡中,选择“添加”
  2. 在“名称”字段中,输入“CACHE_DRIVER”。
  3. 在“值”字段中,输入 redis。
  4. 选择 “应用”,然后再次 应用 ,然后 确认

显示CACHE_DRIVER设置的“添加/编辑应用程序设置”对话框的屏幕截图。

步骤 2: 使用 步骤 1 中的相同步骤创建以下应用设置:

  • MYSQL_ATTR_SSL_CA:使用 /home/site/wwwroot/ssl/DigiCertGlobalRootCA.crt.pem 作为值。 此应用设置指向访问 MySQL 服务器所需的 TLS/SSL 证书的路径。 为了方便起见,它包含在示例存储库中。
  • LOG_CHANNEL:使用 stderr 作为值。 此设置告知 Laravel 通过管道将日志传递给 stderr,这使它可用于应用服务日志。
  • APP_DEBUG:使用 true 作为值。 它是一个 Laravel 调试变量,用于启用调试模式页面。
  • APP_KEY:使用 base64:Dsz40HWwbCqnq0oxMsjq7fItmKIeBfCBGORfspaI1Kw= 作为值。 它是一个 Laravel 加密变量

屏幕截图显示如何在配置页中保存设置。

重要

为方便起见,在此处使用 APP_KEY 值。 对于生产方案,应在命令行中使用 php artisan key:generate --show 专门为你的部署进行生成。

理想情况下,APP_KEY 应用设置也应配置为 Key Vault 引用,这是一个多步骤过程。 有关详细信息,请参阅 如何将APP_KEY应用设置更改为 Key Vault 参考?

5 - 部署示例代码

在此步骤中,使用 GitHub Actions 配置 GitHub 部署。 这只是部署到应用服务的许多方法之一,也是一种在部署过程中持续集成的好方法。 默认情况下,进入 GitHub 存储库的每个 git push 都会启动生成和部署操作。

步骤 1:在左侧菜单中,选择“部署”>“部署中心”。

显示如何在“应用服务”中打开部署中心的屏幕截图。

步骤 2:在“部署中心”页中:

  1. 在“源”中,选择“GitHub”。 默认情况下,选择 GitHub Actions 作为生成提供程序。
  2. 登录到 GitHub 帐户,并按照提示授权 Azure。
  3. 在“组织”中,选择你的帐户。
  4. 存储库中,选择 msdocs-postgresql-sample-app
  5. 在“分支”中,选择“主”
  6. 对于“身份验证类型”,请选择“用户分配的标识”。
  7. 在顶部菜单中,选择“保存”。 应用服务会将工作流文件提交到所选 GitHub 存储库中(在 .github/workflows 目录中)。 默认情况下,部署中心会为工作流创建用户分配的标识,以便使用 Microsoft Entra(OIDC 身份验证)进行身份验证。 有关其他身份验证选项,请参阅使用 GitHub Actions 部署到应用服务

显示如何使用 GitHub Actions 配置 CI/CD 的屏幕截图 (Django)。

步骤 3:返回示例分支的 GitHub codespace,运行 git pull origin main。 这会将新提交的工作流文件拉取到 codespace。

显示 GitHub 代码空间内 git pull 操作的屏幕截图。

步骤 4(选项 1:使用 GitHub Copilot):

  1. 选择“聊天”视图,然后选择 +,即可开始新的聊天会话。
  2. 问:“@workspace 应用如何连接到数据库和 Redis?Copilot 可能会给出有关如何在 config/database.php 中进行配置的一些说明。”
  3. 问:“@workspace在生产模式下,我的应用在应用服务 Web 应用中运行,该应用使用 Azure 服务连接器连接到 MySQL 灵活服务器。我需要使用的环境变量名称是什么?”Copilot 可能会为你提供类似于选项 2 中的代码建议 :没有 GitHub Copilot 步骤,甚至告诉你在 config/database.php 文件中进行更改。
  4. 在资源管理器中打开 配置/database.php 并添加代码建议。
  5. 问:“@workspace 我的应用服务应用还使用 Azure 服务连接器连接到使用 Django 客户端类型的 Redis 缓存。 我需要使用什么环境变量名称?*”Copilot 可能会提供类似于以下“选项 2:不使用 GitHub Copilot”步骤中的代码建议,甚至还会告知你在 azureproject/production.py 文件中进行更改。 如果系统提示,请登录到 GitHub Copilot for Azure 以获取更准确的答案。
  6. 添加代码建议。 GitHub Copilot 不会每次都提供相同的响应,而且并不总是正确的。 可能需要提出更多问题来微调其响应。 有关提示,请参阅我可以在 codespace 中使用 GitHub Copilot 做什么?

屏幕截图显示如何在新的 GitHub Copilot 聊天会话中提问。

步骤 4(选项 2:不使用 GitHub Copilot):

  1. 在资源管理器中打开 配置/数据库.php 。 找到 mysql 部分并进行如下更改:
  2. 将 (第 49 行) 替换为 DB_HOSTAZURE_MYSQL_HOST
  3. 将 (第 51 行) 替换为 DB_DATABASEAZURE_MYSQL_DBNAME
  4. 将 (第 52 行) 替换为 DB_USERNAMEAZURE_MYSQL_USERNAME
  5. 将 (第 53 行) 替换为 DB_PASSWORDAZURE_MYSQL_PASSWORD
  6. 将 (第 50 行) 替换为 DB_PORTAZURE_MYSQL_PORT
  7. 滚动到 Redis cache 部分并进行以下更改:
  8. REDIS_HOST (line) 替换为 AZURE_REDIS_HOST
  9. REDIS_PASSWORD 替换为 AZURE_REDIS_PASSWORD
  10. REDIS_PORT 替换为 AZURE_REDIS_PORT
  11. REDIS_CACHE_DB 替换为 AZURE_REDIS_DATABASE
  12. 在同一部分中,添加一行 'scheme' => 'tls',。 此配置告知 Laravel 使用加密连接到 Redis。

显示已打开的 GitHub 代码空间和配置/database.php的屏幕截图。

步骤 5:

  1. 选择“源代码管理”扩展。
  2. 在文本框中,键入类似 Configure Azure database and cache connectons 的提交消息。 或者,选择 ,让 GitHub Copilot 为你生成提交消息。
  3. 选择“提交”,然后使用“是”进行确认
  4. 选择“同步更改 1”,然后使用“确定”进行确认。

显示正在提交并推送到 GitHub 的更改的屏幕截图。

步骤 6:返回到 Azure 门户中的“部署中心”页

  1. 选择“日志”选项卡,然后选择“刷新”以查看新的部署运行。
  2. 在部署运行的日志项中,选择具有最新时间戳的“生成/部署日志”条目。

显示如何在部署中心打开部署日志的屏幕截图。

步骤 7:你已转到 GitHub 存储库,并看到 GitHub Action 正在运行。 工作流文件定义两个单独的阶段,即生成和部署阶段。 等待 GitHub 运行以显示“成功”状态。 大约需要 10 分钟。

屏幕截图显示 GitHub 正在运行。

遇到问题? 检查故障排除部分

6 - 生成数据库架构

创建向导将 MySQL 数据库服务器置于专用终结点后面,因此只能从虚拟网络中进行访问。 由于应用服务应用已与虚拟网络集成,因此使用数据库运行数据库迁移的最简单方法是直接从应用服务容器中运行。

步骤 1:返回“应用服务”页,在左侧菜单中,

  1. 选择“开发工具”“SSH”。>
  2. 选择“转到”。

显示如何从 Azure 门户打开应用的 SSH shell 的屏幕截图。

步骤 2:在 SSH 终端中:

  1. 运行 cd /home/site/wwwroot。 下面是所有已部署的文件。
  2. 运行 php artisan migrate --force。 如果该命令成功,则应用服务会成功连接到 MySQL 数据库。

显示在 SSH shell 中运行的命令及其输出的屏幕截图。

提示

在 SSH 会话中,只有在 /home 中对文件进行的更改才能在应用重启后保持。 不会保留 /home 外部的更改。

7 - 更改网站根

Laravel 应用程序生命周期在 /public 目录中开始。 应用服务的默认 PHP 容器使用 Nginx,这将在应用程序的根目录中开始。 若要更改站点根路径,需要在 PHP 容器中更改 Nginx 配置文件 (/etc/nginx/sites-available/default)。 为方便起见,示例存储库包含一个名为 default 的自定义配置文件。 如前所述,你不想使用 SSH shell 替换此文件,因为更改发生在 /home 外,并且将在应用程序重启后丢失。

步骤 1

  1. 在左侧菜单中选择“配置”。
  2. 选择“常规设置”选项卡。

显示如何在“应用服务”的配置页中打开常规设置选项卡的屏幕截图。

步骤 2:在“常规设置”选项卡中:

  1. 在“启动命令”框中,输入以下命令:cp /home/site/wwwroot/default /etc/nginx/sites-available/default && service nginx reload。
  2. 选择“ 保存”,然后选择“ 继续”。 该命令会替换 PHP 容器中的 Nginx 配置文件并重启 Nginx。 此配置可确保每次启动容器时都会对容器进行相同的更改。

显示如何在“应用服务”中配置启动命令的屏幕截图。

8 - 浏览到应用

步骤 1:在“应用服务”页中:

  1. 从左侧菜单中选择“概述”。
  2. 选择应用 的默认域

显示如何从 Azure 门户中启动应用服务的屏幕截图。

步骤 2:将一些任务添加到列表。 恭喜,你的数据驱动的安全 PHP 应用正在 Azure 应用服务中运行。

在应用服务中运行的 Laravel 应用的屏幕截图。

提示

示例应用程序实现缓存端模式。 当你在进行数据更改后重新加载页面时,网页中显示的“响应时间”会快得多,因为它是从缓存而不是从数据库加载数据。

9 - 流式传输诊断日志

Azure 应用服务捕获已记录到控制台的所有消息,以帮助你诊断应用程序的问题。 示例应用在其每个终结点中输出控制台日志消息,以演示此功能。 默认情况下,Laravel 的日志记录功能(例如 Log::info())会输出到本地文件。 之前的 LOG_CHANNEL 应用设置使日志条目可从应用服务日志流访问。

步骤 1:在“应用服务”页中:

  1. 从左菜单中选择“应用服务日志”。
  2. 在“应用程序日志记录”下,选择“文件系统”。

显示如何在 Azure 门户的应用服务中启用本机日志的屏幕截图。

步骤 2:在左侧菜单中,选择“日志流”。 将显示应用的日志,包括平台日志和容器内部的日志。

显示如何在 Azure 门户中查看日志流的屏幕截图。

清理资源

完成后,可以通过删除资源组从 Azure 订阅中删除所有资源。

步骤 1:在 Azure 门户顶部的搜索栏中:

  1. 输入资源组名称。
  2. 选择资源组。

显示如何在 Azure 门户中搜索和导航到资源组的屏幕截图。

步骤 2:在资源组页上,选择“删除资源组”。

显示 Azure 门户中“删除资源组”按钮位置的屏幕截图。

步骤 3:

  1. 输入资源组名称以确认删除。
  2. 选择“删除”。

Azure 门户中删除资源组确认对话框的屏幕截图。

2.创建 Azure 资源并部署示例应用

在此步骤中,将创建 Azure 资源并将示例应用部署到 Linux 上的应用服务。 本教程中使用的步骤创建一组默认安全的资源,其中包括应用服务和 Azure Database for MySQL。

GitHub codespace 已具有 Azure 开发人员 CLI (AZD)。

  1. 使用 php artisan key:generate --show: 生成 Laravel 加密密钥:

    php artisan key:generate --show
    
  2. 通过运行 azd auth login 命令并按照提示登录到 Azure:

    azd auth login
    
  3. 使用 azd up 命令创建必要的 Azure 资源并部署应用代码。 按照提示为 Azure 资源选择所需的订阅和位置。

    azd up
    
  4. 出现提示时,请提供以下答案:

    问题 答案
    输入新环境名称 键入唯一名称。 AZD 模板将此名称用作 Azure 中 Web 应用的 DNS 名称的一部分 (<app-name>-<hash>.azurewebsites.net)。 允许使用字母数字字符和下划线。
    选择要使用的 Azure 订阅 选择订阅。
    选择要使用的 Azure 位置 选择一个位置。
    输入“appKey”基础结构安全参数的值 在此处使用 php artisan key:generate --show 的输出。 AZD 模板会为此创建一个可在应用中使用的 Key Vault 密钥。
    输入“databasePassword”基础结构安全参数的值 MySQL 的数据库密码。 它长度必须至少为 8 个字符,并且包含大写字母、小写字母、数字和特殊字符。

    azd up 命令需要大约 15 分钟来完成(Redis 缓存需要的时间最长)。 它还会编译和部署应用程序代码,但你稍后将修改代码以使用应用服务。 在运行时,该命令会提供有关预配和部署过程的消息,包括指向 Azure 中部署的链接。 完成后,命令还会显示指向部署应用程序的链接。

    此 AZD 模板包含使用以下 Azure 资源生成安全默认体系结构的文件(azure.yamlinfra 目录):

    • 资源组:所有已创建资源的容器。
    • 应用服务计划:为应用服务定义计算资源。 现在 B1 层中建立了 Linux 计划。
    • 应用服务:表示应用并在应用服务计划中运行。
    • 虚拟网络:与应用服务应用集成,并隔离后端网络流量。
    • Azure Database for MySQL 灵活服务器:只能通过 DNS 区域集成从虚拟网络访问。 将在服务器上为你创建数据库。
    • Azure Cache for Redis:只能从虚拟网络中访问。
    • 专用终结点:虚拟网络中密钥保管库和 Redis 缓存的访问终结点。
    • 专用 DNS 区域:启用虚拟网络中的密钥保管库、数据库服务器和 Redis 缓存的 DNS 解析。
    • Log Analytics 工作区:充当应用日志传送的目标容器,还可以在其中查询日志。
    • 密钥保管库:使用 AZD 重新部署时,用于保留数据库密码。

遇到问题? 检查故障排除部分

3.在应用程序代码中使用 Azure 连接字符串

你使用的 AZD 模板已为你生成了连接变量作为应用设置,并将它们输出到终端,以方便你使用。 使用应用设置可以将连接机密保留在代码存储库之外。

  1. 在 AZD 输出中,找到以 AZURE_MYSQL_AZURE_REDIS_. 开头的应用设置。 仅显示设置名称。 如 AZD 输出中所示:

     App Service app has the following app settings:
             - AZURE_KEYVAULT_RESOURCEENDPOINT
             - AZURE_KEYVAULT_SCOPE
             - AZURE_MYSQL_DBNAME
             - AZURE_MYSQL_FLAG
             - AZURE_MYSQL_HOST
             - AZURE_MYSQL_PASSWORD
             - AZURE_MYSQL_PORT
             - AZURE_MYSQL_USERNAME
             - AZURE_REDIS_DATABASE
             - AZURE_REDIS_HOST
             - AZURE_REDIS_PASSWORD
             - AZURE_REDIS_PORT
             - AZURE_REDIS_SSL
     

    开头 AZURE_MYSQL_ 的设置是 MySQL 数据库的连接变量,开头 AZURE_REDIS_ 的设置是 Redis 缓存的设置。 稍后需要在代码中使用它们。 为方便起见,AZD 模板会显示 Azure 门户中应用的应用设置页的直接链接。

  2. 从资源管理器中,打开 config/database.php。 这是数据库和 Redis 缓存连接的配置文件。

  3. 找到定义mysql连接(第46至64行)的部分,并将DB_HOSTDB_PORTDB_DATABASEDB_USERNAMEDB_PASSWORD替换为来自AZD输出的AZURE_MYSQL_应用设置。 连接 mysql 应类似于以下代码。

    'mysql' => [
        'driver' => 'mysql',
        'url' => env('DATABASE_URL'),
        'host' => env('AZURE_MYSQL_HOST', '127.0.0.1'),
        'port' => env('AZURE_MYSQL_PORT', '3306'),
        'database' => env('AZURE_MYSQL_DBNAME', 'forge'),
        'username' => env('AZURE_MYSQL_USERNAME', 'forge'),
        'password' => env('AZURE_MYSQL_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'prefix_indexes' => true,
        'strict' => true,
        'engine' => null,
        'options' => extension_loaded('pdo_mysql') ? array_filter([
            PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
        ]) : [],
    ],
    

    有关 Laravel 中的数据库配置的详细信息,请参阅 Laravel 文档

  4. 找到定义 Redis 缓存连接(第 140-147 行)的部分,并用 AZD 输出中的 REDIS_HOST 应用设置替换 REDIS_PASSWORDREDIS_PORTREDIS_CACHE_DBAzure_REDIS_。 此外,请将'scheme' => 'tls',添加到连接中。 缓存连接应类似于以下代码:

    'cache' => [
        'scheme' => 'tls',
        'url' => env('REDIS_URL'),
        'host' => env('AZURE_REDIS_HOST', '127.0.0.1'),
        'username' => env('REDIS_USERNAME'),
        'password' => env('AZURE_REDIS_PASSWORD'),
        'port' => env('AZURE_REDIS_PORT', '6379'),
        'database' => env('AZURE_REDIS_DATABASE', '1'),
    ],
    

    有关 Laravel 中的 Redis 缓存配置的详细信息,请参阅 Laravel 文档

    注释

    请记住,你的更改尚未部署。 在下一步结束时,将部署更改。

4. 在 Web 应用中配置 Laravel 设置

  1. 在资源管理器中打开 infra/resources.bicep。 这是定义创建的 Azure 资源的 Bicep 文件。

  2. 找到定义应用设置的部分(第 510 到 514 行),然后取消注释。 这些应用设置包括:

    设置 DESCRIPTION
    CACHE_DRIVER 告知 Laravel 使用 Redis 作为其缓存(请参阅 Laravel 文档)。
    MYSQL_ATTR_SSL_CA 需要在 Azure 中打开与 MySQL 的 TLS 连接。 为了方便起见,证书文件包含在示例存储库中。 此变量由 config/database.php 中的 mysql 连接使用
    LOG_CHANNEL 告知 Laravel 通过管道将日志传递给 stderr,这使它可用于应用服务日志(请参阅 Laravel 文档)。
    APP_DEBUG 在 Laravel 中启用调试模式页面(请参阅 Laravel 文档)。
    APP_KEY Laravel 加密变量。 AZD 模板已经创建了 Key Vault 密钥(第 212-217 行),因此可以通过 Key Vault 引用来访问它。
  3. infra/resources.bicep 中,查找应用服务应用的资源定义并取消注释第 315 行:

    appCommandLine: 'cp /home/site/wwwroot/default /etc/nginx/sites-available/default && service nginx reload'
    

    Laravel 应用程序生命周期/public 目录中开始,而不是应用程序根目录。 应用服务的默认 PHP 容器使用 Nginx,该容器在应用程序根目录中启动。 若要更改站点根路径,需要在 PHP 容器中更改 Nginx 配置文件 (/etc/nginx/sites-available/default)。 为方便起见,示例存储库包含名为 default 的替换配置文件,它告知 Nginx 在 /public 目录中查找。 每次应用启动时,appCommandLine 中的此自定义命令都会运行,以便在从干净状态重新加载 Linux 容器时应用文件替换。

  4. 返回 codespace 终端,再次运行 azd up

    azd up
    

提示

azd upazd packageazd provisionazd deploy 一起运行,这很合理,因为你正在进行基础设施和应用程序的更改。 若要仅进行基础结构更改,请运行 azd provision。 若要仅将更改部署到应用程序代码,请运行 azd deploy

遇到问题? 检查故障排除部分

5.生成数据库架构

使用受虚拟网络保护的 MySQL 数据库,运行 Laravel 数据库迁移的最简单方法是在应用服务中与 Linux 容器建立 SSH 会话。

  1. 在 AZD 输出中,找到 SSH 会话的 URL,并在浏览器中导航到该 URL。 它在输出中如下所示:

     Open SSH session to App Service container at: https://<app-name>-<hash>.scm.azurewebsites.net/webssh/host
     
  2. 在 SSH 会话中,从 /home/site/wwwroot 目录运行数据库迁移:

    cd /home/site/wwwroot
    php artisan migrate --force
    

    如果该命令成功,则应用服务会成功连接到数据库

注释

只有对 /home 中文件的更改才能在应用重启之后持久保存。

遇到问题? 检查故障排除部分

6. 找到并打开应用

  1. 在 AZD 输出中,找到应用的 URL 并在浏览器中导航到该 URL。 该 URL 在 AZD 输出中如下所示:

     Deploying services (azd deploy)
    
       (✓) Done: Deploying service web
       - Endpoint: https://<app-name>-<hash>.azurewebsites.net/
     
  2. 将一些任务添加到列表。

    Laravel Web 应用的屏幕截图,其中 MySQL 在 Azure 中运行,其中显示了任务。

    恭喜,你已在 Azure 应用服务中运行了一个 Web 应用,并安全连接到了 Azure Database for MySQL。

遇到问题? 检查故障排除部分

7.流式传输诊断日志

Azure 应用服务捕获已记录到控制台的所有消息,以帮助你诊断应用程序的问题。 为方便起见,AZD 模板已启用对本地文件系统的日志记录以及将日志传送到 Log Analytics 工作区

示例应用在其每个终结点中输出控制台日志消息,以演示此功能。 默认情况下,Laravel 的日志记录功能(例如 Log::info())会输出到本地文件。 之前的 LOG_CHANNEL 应用设置使日志条目可从应用服务日志流访问。

Route::get('/', function () {
    Log::info("Get /");
    $startTime = microtime(true);
    // Simple cache-aside logic
    if (Cache::has('tasks')) {
        $data = Cache::get('tasks');
    } else {
        $data = Task::orderBy('created_at', 'asc')->get();
        Cache::add('tasks', $data);
    }
    return view('tasks', ['tasks' => $data, 'elapsed' => microtime(true) - $startTime]);
});

在 AZD 输出中,找到流式传输应用服务日志的链接,并在浏览器中导航到该链接。 该链接在 AZD 输出中如下所示:

Stream App Service logs at: https://portal.azure.com/#@/resource/subscriptions/<subscription-guid>/resourceGroups/<group-name>/providers/Microsoft.Web/sites/<app-name>/logStream

遇到问题? 检查故障排除部分

8.清理资源

若要删除当前部署环境中的所有 Azure 资源,请运行 azd down 并按照提示进行操作。

azd down

故障排除

在数据库迁移过程中出现错误 php_network_getaddresses: getaddrinfo for mysqldb failed: No address associated with hostname...

它指示未正确配置 MySQL 连接变量。 验证 AZURE_MYSQL_ 是否已在 3 中正确配置应用设置。在应用程序代码中使用 Azure 连接字符串。

我在浏览器中收到一个空白页。

它指示应用服务在 /public 中找不到 PHP 启动文件。 按照 4. 在 Web 应用中配置 Laravel 设置 中的步骤进行。

我在浏览器中获得了一个显示为Unsupported cipher or incorrect key length.的调试页面。

它表明 APP_KEY 被设置为无效键。 运行 azd up 时,请确保将 appKey 设置为 php artisan key:generate --show 的输出。

我在浏览器中获得了一个显示为Uncaught Error: Class "Illuminate\..." not found.的调试页面。

此错误和类似的错误表示之前未运行composer installazd up,或者 /vendor 目录中的包已过时。 运行composer installazd deploy再次。

我在浏览器中获得了一个显示为php_network_getaddresses: getaddrinfo for redishost failed: Name or service not known.的调试页面。

它指示未正确配置 Redis 连接变量。 验证 AZURE_REDIS_ 是否已在 3 中正确配置应用设置。在应用程序代码中使用 Azure 连接字符串。

我在浏览器中获得了一个显示为SQLSTATE[42S02]: Base table or view not found: 1146 Table 'XXXX-XXXXXXXXX-mysql-database.tasks' doesn't exist的调试页面。

这意味着你尚未运行数据库迁移,或者数据库迁移未成功。 按照步骤 5 生成数据库架构的指引进行操作。

常见问题

此设置花费有多大?

所创建资源的定价如下所示:

  • 应用服务计划在基本层中创建,可以进行纵向扩展或缩减。 请参阅应用服务定价
  • MySQL 灵活服务器在 B1ms 层中创建,可以扩展或缩减规模。 使用 Azure 免费帐户时,B1ms 层在 12 个月内免费,不能超过每月限制。 参阅 Azure Database for MySQL 价格信息
  • Azure Cache for Redis 是在缓存大小最小的基本层中创建的。 此层的相关成本很低。 你可将其纵向扩展到更高的性能层,以实现更高的可用性、聚类分析和其他功能。 请了解 Azure Cache for Redis 定价
  • 除非配置额外的功能(例如对等互连),否则虚拟网络不会产生费用。 请参阅 Azure 虚拟网络定价
  • 专用 DNS 区域会产生少量费用。 请参阅 Azure DNS 定价

如何使用其他工具连接到被虚拟网络保护的 MySQL 数据库?

  • 要从命令行工具进行基本访问,可以从应用的 SSH 终端运行 mysql
  • 若要从 MySQL Workbench 等桌面工具进行连接,计算机必须位于虚拟网络中。 例如,它可以是连接到其中一个子网的 Azure VM,也可以是与 Azure 虚拟网络建立了站点到站点 VPN 连接的本地网络中的计算机。
  • 还可以将 Azure Cloud Shell 与虚拟网络集成。

如何将APP_KEY应用设置更改为 Key Vault 引用?

在门户中的步骤4 - 配置 Laravel 变量中,可以通过在 GitHub 代码开发空间中运行以下 Azure CLI 命令,将APP_KEY更改为 Key Vault 引用:

# Change the following variables to match your environment
SUBSCRIPTION_ID=<subscription-id>
RESOURCE_GROUP=<resource-group-name>
KEY_VAULT_NAME=<key-vault-name>
APP_SERVICE_NAME=<app-name>
SECRET_NAME=laravelAppKey

# Set the subscription ID
az account set --subscription $SUBSCRIPTION_ID

# Assign 'Key Vault Secrets Officer' role to your user at the scope of the key vault
az role assignment create \
  --assignee $(az ad signed-in-user show --query id -o tsv) \
  --role $(az role definition list --name "Key Vault Secrets Officer" --query "[].id" -o tsv) \
  --scope $(az keyvault show --name $KEY_VAULT_NAME --resource-group $RESOURCE_GROUP --query id --output tsv)

# Add the secret to the key vault
az keyvault secret set \
  --vault-name $KEY_VAULT_NAME \
  --name $SECRET_NAME \
  --value $(php artisan key:generate --show)

# Add Key Vault reference to the App Service configuration
az webapp config appsettings set \
  --resource-group $RESOURCE_GROUP \
  --name $APP_SERVICE_NAME \
  --settings "APP_KEY=@Microsoft.KeyVault(SecretUri=https://$KEY_VAULT_NAME.vault.azure.net/secrets/$SECRET_NAME)"

还可以在门户中执行相同的操作。 有关详细信息,请参见:

  1. 密钥保管库作用域角色分配
  2. 向 Key Vault 添加机密
  3. 从 Key Vault 检索机密
  4. 配置应用设置

本地应用开发如何与 GitHub Actions 配合使用?

以应用服务自动生成的工作流文件为例,每个 git push 文件都会启动新的生成和部署运行。 从 GitHub 存储库的本地克隆中,将所需的更新推送到 GitHub。 例如:

git add .
git commit -m "<some-message>"
git push origin main

为什么 GitHub Actions 部署速度这么慢?

应用服务自动生成的工作流文件定义了一个先构建后部署的双作业运行方案。 由于每个作业都在自己的干净环境中运行,因此工作流文件可确保 deploy 作业可以访问 build 作业的文件。

两个作业过程的大部分时间都是花费在上传和下载项目上。 如果需要,可以通过将这两个作业合并为一个作业来简化工作流文件,省去了上传和下载步骤。

我无权创建用户分配的标识

请参阅从部署中心设置 GitHub Actions 部署

在我的代码空间里,我可以用 GitHub Copilot 做些什么?

你可能注意到,创建 codespace 时,GitHub Copilot 聊天视图已经存在。 为了你的方便,我们在容器定义中包含了 GitHub Copilot 聊天扩展(参见 .devcontainer/devcontainer.json)。 不过,你需要一个 GitHub Copilot 帐户(可免费试用 30 天)。

下面是与 GitHub Copilot 交谈时的一些提示:

  • 在单次聊天会话中,问题和答案相互关联,你可以调整问题来微调所获得的答案。
  • 默认情况下,GitHub Copilot 无法访问你存储库中的任何文件。 若要询问有关文件的问题,请首先在编辑器中打开该文件。
  • 为了让 GitHub Copilot 在准备答案时有权访问存储库中的所有文件,请在问题开头加上 @workspace。 有关详细信息,请参阅 Use the @workspace agent
  • 在聊天会话中,GitHub Copilot 可以建议更改,甚至可以(在使用 @workspace 时)建议在何处进行更改,但系统不允许它为你进行更改。 你可以自行添加建议的更改并对其进行测试。

后续步骤

请继续学习下一教程,了解如何使用自定义域和证书保护应用。

或者,查看其他资源: