你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
Azure 应用服务 在 Windows 上提供预定义的应用程序堆栈,例如 ASP.NET 或 Node.js。 这些应用程序堆栈在 IIS 上运行。 预配置的 Windows 环境锁定了操作系统,不允许对其进行以下操作:
- 管理权限。
- 软件安装。
- 全局程序集缓存更改。
有关详细信息,请参阅应用服务上的操作系统功能。
可以从 Visual Studio 部署自定义配置的 Windows 映像,以进行应用所需的 OS 更改。 这样做可以轻松迁移需要自定义 OS 和软件配置的本地应用。 本教程演示如何将使用 Windows 字体库中安装的自定义字体的 ASP.NET 应用迁移到应用服务。 你将自定义配置的 Windows 映像从 Visual Studio 部署到 Azure 容器注册表,然后在应用服务中运行它。
先决条件
- 注册 Docker Hub 帐户。
- 安装用于 Windows 的 Docker。
- 配置 Docker 来运行 Windows 容器。
- 安装 Visual Studio 2022,其中包含 ASP.NET 和 Web 开发 以及 Azure 开发工作负载。 如果已安装 Visual Studio 2022:
- 通过选择 帮助>检查更新,在 Visual Studio 中安装最新更新。
- 在 Visual Studio 中,通过选择 工具获取工具和功能,添加工作负载。
在本地设置应用
下载示例
在此步骤中,你将设置本地 .NET 项目。
- 下载示例项目 。
- 提取(解压缩)custom-font-win-container-master.zip 文件。
示例项目包括一个简单的 ASP.NET 应用程序,该应用程序使用安装在 Windows 字体库中的自定义字体。 不需要安装字体。 但是,此示例是一个与基础 OS 集成的应用示例。 要将此类应用迁移到应用服务,可以选择重新构建代码以移除集成,或者通过自定义 Windows 容器将其按原样迁移。
安装字体
在 Windows 资源管理器中,转到 custom-font-win-container-master/CustomFontSample,右键单击 FrederickatheGreat-Regular.ttf,然后选择“ 安装”。
该字体在 Google Fonts 中公开发布。
运行应用
在 Visual Studio 中打开 custom-font-win-container-master/CustomFontSample.sln 文件。
选择 Ctrl+F5 在不调试的情况下运行应用。 该应用将显示在默认浏览器中。
由于应用使用已安装的字体,因此应用无法在应用服务沙盒中运行。 但是,你可以改用 Windows 容器来部署它,因为你可以在 Windows 容器中安装字体。
配置 Windows 容器
在解决方案资源管理器中,右键单击 CustomFontSample 项目,选择添加>容器业务流程支持。
选择Docker ComposeOK。
现在,项目设置为在 Windows 容器中运行。
Dockerfile 添加到 CustomFontSample 项目,docker-compose 项目添加到解决方案。
在解决方案资源管理器中,打开 Dockerfile。
需要使用受支持的父映像。 通过将 FROM 行替换为以下代码,更改父映像:
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.7.2-windowsservercore-ltsc2019
将以下行添加到文件末尾并保存该文件:
RUN ${source:-obj/Docker/publish/InstallFont.ps1}
可以在 CustomFontSample 项目中找到 InstallFont.ps1。 它是一个安装该字体的简单脚本。 可在 PowerShell 库 中找到更复杂的脚本版本。
注意
若要在本地测试 Windows 容器,请确保在本地计算机上启动 Docker。
发布到 Azure 容器注册表
Azure 容器注册表可以存储用于容器部署的映像。 可以将应用服务配置为使用容器注册表中托管的映像。
打开“发布”窗口
在解决方案资源管理器中,右键单击 CustomFontSample 项目,然后选择“ 发布”。
创建并发布注册表
在 “发布 ”窗口中,选择 “Azure”,然后选择“ 下一步”。
选择 Azure 容器注册表,然后选择“ 下一步”。
选择要在其中发布注册表的订阅,然后选择新建。
使用 Azure 帐户登录
在“Azure 容器注册表”窗口中,选择“添加帐户”,然后登录到 Azure 订阅。 如果已登录,请从下拉列表中选择包含所需订阅的帐户。
配置注册表
使用下表中的建议值作为指南配置新的容器注册表。 完成后,选择创建。
| 设置 | 建议值 |
|---|---|
| DNS 前缀 | 保留生成的注册表名称,或将其更改为另一个唯一的名称。 |
| 资源组 | 选择“新建”,输入 myResourceGroup,然后选择“确定”。 |
| SKU | 基本。 有关详细信息,请参阅定价层。 |
| 注册表位置 | 西欧 |
选择完成。
终端窗口随即打开并显示映像部署进度。 等待部署完成。
登录 Azure
登录到 Azure 门户。
创建 Web 应用
选择“创建资源”,然后在“Web 应用”下选择“创建”。
配置应用基本信息
在“ 基本信息 ”选项卡上,使用下表作为指南配置设置。
| 设置 | 建议值 |
|---|---|
| 订阅 | 确保选择正确的订阅。 |
| 资源组 | 选择 “新建”,输入 myResourceGroup,然后选择 “确定”。 |
| 名称 | 输入唯一名称。 Web 应用的 URL 为 https://<app-name>.azurewebsites.net,其中 <app-name> 是应用名称。 |
| 发布 | 容器 |
| 操作系统 | Windows |
| 区域 | 西欧 |
| Windows 计划 | 选择 “新建”,输入 myAppServicePlan,然后选择 “确定”。 |
“ 基本信息 ”选项卡应如下所示:
配置 Windows 容器
在“ 容器 ”选项卡上,配置自定义 Windows 容器,如下表所示,然后选择“ 查看 + 创建”。
| 设置 | 建议值 |
|---|---|
| 图像来源 | Azure 容器注册表 |
| 注册表 | 选择前面创建的镜像仓库。 |
| 图像 | customfontsample |
| 标记 | 最新 |
完成应用创建
选择“创建”,等待 Azure 创建所需的资源。
浏览到 Web 应用
部署完成后,会显示一条通知消息:
选择“转到资源”。
在应用页中,选择 URL 下的链接。
如果会打开一个如以下页面所示的新浏览器页面:
等待几分钟,然后重试,直到主页显示你所需的字体:
恭喜! 已将 ASP.NET 应用程序迁移到 Windows 容器中的 App Service。
查看容器启动日志
加载 Windows 容器可能需要一些时间。 若要查看进度,请转到以下 URL。 (请将 <app-name> 替换为你的应用名称。)
https://<app-name>.scm.azurewebsites.net/api/logstream
流式传输的日志如下所示:
14/09/2018 23:16:19.889 INFO - Site: fonts-win-container - Creating container for image: customfontsample20180914115836.azurecr.io/customfontsample:latest.
14/09/2018 23:16:19.928 INFO - Site: fonts-win-container - Create container for image: customfontsample20180914115836.azurecr.io/customfontsample:latest succeeded. Container Id 329ecfedbe370f1d99857da7352a7633366b878607994ff1334461e44e6f5418
14/09/2018 23:17:23.405 INFO - Site: fonts-win-container - Start container succeeded. Container: 329ecfedbe370f1d99857da7352a7633366b878607994ff1334461e44e6f5418
14/09/2018 23:17:28.637 INFO - Site: fonts-win-container - Container ready
14/09/2018 23:17:28.637 INFO - Site: fonts-win-container - Configuring container
14/09/2018 23:18:03.823 INFO - Site: fonts-win-container - Container ready
14/09/2018 23:18:03.823 INFO - Site: fonts-win-container - Container start-up and configuration completed successfully
Azure 应用服务使用 Docker 容器技术来托管内置映像和自定义映像。 若要查看内置映像的列表,请运行 Azure CLI 命令 az webapp list-runtimes --os linux。 如果这些映像无法满足需要,可以生成并部署自定义映像。
注意
你的容器应面向 x86-64 体系结构。 ARM64 不受支持。
本教程介绍如何执行下列操作:
- 将自定义 Docker 映像推送到 Azure 容器注册表。
- 将自定义映像部署到应用服务。
- 配置环境变量。
- 使用托管标识将映像拉取到应用服务中。
- 访问诊断日志。
- 启用从容器注册表到应用服务的 CI/CD。
- 使用 SSH 连接到容器。
完成本教程会导致 Azure 帐户中产生一点容器注册表费用,如果容器托管时间超过一个月,还会产生其他费用。
设置初始环境
本教程需要 2.0.80 或更高版本 Azure CLI。 如果你使用的是 Azure Cloud Shell,则已安装最新版本。
- 请确保拥有具有活动订阅的 Azure 帐户。 免费创建帐户。
在 Azure Cloud Shell 中使用 Bash 环境。 有关详细信息,请参阅 Azure Cloud Shell 入门。
如需在本地运行 CLI 参考命令,请安装 Azure CLI。 如果你使用的是 Windows 或 macOS,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI。
如果使用的是本地安装,请使用 az login 命令登录到 Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅 使用 Azure CLI 向 Azure 进行身份验证。
系统提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展的详细信息,请参阅 使用和管理 Azure CLI 中的扩展。
运行 az version 以查找已安装的版本及其依赖库。 若要升级到最新版本,请运行 az upgrade。
- 安装 Docker,用于构建 Docker 映像。 安装 Docker 可能需要重启计算机。
安装 Docker 后,请打开终端窗口,验证是否已安装 Docker:
docker --version
克隆或下载示例应用
可以通过 Git 克隆或下载获取本教程的示例。
使用 Git Bash 克隆存储库
克隆示例存储库:
git clone https://github.com/Azure-Samples/docker-django-webapp-linux.git --config core.autocrlf=input
请确保包括 --config core.autocrlf=input 参数,以确保 Linux 容器中使用的文件中的行尾正确。
然后,导航到以下文件夹:
cd docker-django-webapp-linux
从 GitHub 下载 ZIP
可以转到 https://github.com/Azure-Samples/docker-django-webapp-linux 并选择 “代码>本地>下载 ZIP”,而不是使用 Git 克隆。
将 ZIP 文件解压缩到名为 docker-django-webapp-linux 的文件夹中。
然后在 docker-django-webapp-linux 文件夹中打开终端窗口。
准备样品容器
较新的浏览器终端和 az webapp exec 可提供对运行中的 Linux 容器进行认证访问,而无需 SSH 服务器或在镜像中嵌入 SSH 密码。 遗留的 Kudu WebSSH 和 az webapp ssh 访问可能仍然需要 SSH 服务器。 示例代码仓库包含旧版 SSH 配置。 在构建之前,将其 Dockerfile 的内容替换为以下仅适用于应用的配置:
FROM tiangolo/uwsgi-nginx-flask:python3.6
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt --no-cache-dir
ADD . /code/
COPY init.sh /usr/local/bin/
RUN chmod u+x /usr/local/bin/init.sh
EXPOSE 8000
ENTRYPOINT ["init.sh"]
用以下脚本替换 init.sh 的内容,保留Linux行尾:
#!/bin/bash
set -e
exec python /code/manage.py runserver 0.0.0.0:8000
把遗留 的sshd_config 文件从本地样本文件夹里移除,这样 ADD . /code/ 就不会把它复制到镜像里。
Dockerfile 安装应用的依赖,复制应用和启动脚本,并公开应用的端口。 入口点只启动 Python 应用程序。 这些更改会移除样本的SSH安装和凭证。 映像包含较新的浏览器终端的 /bin/bash 以及默认的 az webapp exec shell。
在本地生成和测试映像
注意
Docker Hub 对每个 IP 的匿名拉取数和每个免费用户经过身份验证的拉取数施加配额。 如果发现来自 Docker Hub 的请求受到限制,请尝试运行 docker login(如果尚未登录)。
运行以下命令生成映像:
docker build --tag appsvc-tutorial-custom-image .通过在本地运行 Docker 容器来测试构建是否正常工作:
docker run -it -p 8000:8000 appsvc-tutorial-custom-image此
docker run命令使用-p参数指定端口并包括映像名称。-it允许你使用 Ctrl+C 停止它。提示
如果在 Windows 上运行时显示错误“*standard_init_linux.go:211: exec 用户进程导致‘无此类文件或目录’”,则表示 init.sh 文件包含 CRLF 行尾而不是预期的 LF 行尾。 如果使用 Git 来克隆示例存储库,但省略了
--config core.autocrlf=input参数,就会发生此错误。 在这种情况下,请使用--config参数再次克隆存储库。 如果已编辑 init.sh 并将其保存为 CRLF 行尾格式,也可能会发生此错误。 在这种情况下,请再次保存文件,并且仅使用 LF 行尾。浏览到
http://localhost:8000,验证 Web 应用和容器是否正常运行。
创建用户分配的托管标识
应用服务可以使用默认托管标识或用户分配的托管标识向容器注册表进行身份验证。 在本教程中,你将使用用户分配的托管标识。
- Azure CLI
- Azure 门户
运行 az group create 命令创建资源组:
az group create --name msdocs-custom-container-tutorial --location westeurope可以更改
--location值以指定您附近的区域。在资源组中创建托管标识:
az identity create --name myID --resource-group msdocs-custom-container-tutorial
创建容器注册表
- Azure CLI
- Azure 门户
使用以下
az acr create命令创建容器注册表。 用一个用于你的注册表的唯一名称替换<registry-name>。 该名称只能包含字母和数字,并且必须在整个 Azure 中都是唯一的。az acr create --name <registry-name> --resource-group msdocs-custom-container-tutorial --sku Basic --admin-enabled true该
--admin-enabled参数允许使用管理凭据将映像推送到注册表。通过运行
az credential acr show命令检索管理凭据:az acr credential show --resource-group msdocs-custom-container-tutorial --name <registry-name>此命令的 JSON 输出提供两个密码以及镜像仓库的用户名。
将示例映像推送到容器注册表
在本部分中,会将映像推送到 Container Registry,稍后由 App Service 使用。
在生成示例映像的本地终端中,使用
docker login命令登录到容器注册表:docker login <registry-name>.azurecr.io --username <registry-username>将
<registry-name>和<registry-username>替换为前面步骤中的值。 出现提示时,键入上一部分中的某个密码。在本部分的所有剩余步骤中使用相同的注册表名称。
成功登录后,为本地 Docker 映像打标签,以便将其推送到该注册表:
docker tag appsvc-tutorial-custom-image <registry-name>.azurecr.io/appsvc-tutorial-custom-image:latest使用
docker push命令将映像推送到注册表:docker push <registry-name>.azurecr.io/appsvc-tutorial-custom-image:latest第一次上传映像可能需要几分钟时间,因为它包含基本映像。 后续上传速度通常较快。
在等待期间,可以完成下一部分中的步骤,将应用服务配置为从注册表部署。
为注册表的托管标识授权
创建的托管标识尚未获得从容器注册表拉取的授权。 在此步骤中,你将启用授权。
- Azure CLI
- Azure 门户
检索托管标识的主体 ID:
principalId=$(az identity show --resource-group msdocs-custom-container-tutorial --name myID --query principalId --output tsv)检索容器注册表的资源 ID:
registryId=$(az acr show --resource-group msdocs-custom-container-tutorial --name <registry-name> --query id --output tsv)授予托管标识访问容器注册表的权限:
az role assignment create --assignee $principalId --scope $registryId --role "AcrPull"有关这些权限的详细信息,请参阅什么是 Azure 基于角色的访问控制?
创建 Web 应用
- Azure CLI
- Azure 门户
使用
az appservice plan create命令创建应用服务计划:az appservice plan create --name myAppServicePlan --resource-group msdocs-custom-container-tutorial --is-linux应用服务计划对应托管 Web 应用的虚拟机。 默认情况下,前面的命令使用平价的 B1 定价层,该定价层第一个月免费提供。 可以使用
--sku参数指定层级。使用
az webapp create命令创建 Web 应用:az webapp create --resource-group msdocs-custom-container-tutorial --plan myAppServicePlan --name <app-name> --deployment-container-image-name <registry-name>.azurecr.io/appsvc-tutorial-custom-image:latest请将
<app-name>替换为 Web 应用的名称。 该名称在全 Azure 中必须是唯一的。 同时将<registry-name>替换为上一部分中注册表的名称。提示
可以随时使用命令
az webapp config container show --name <app-name> --resource-group msdocs-custom-container-tutorial检索 Web 应用的容器设置。 该映像在DOCKER_CUSTOM_IMAGE_NAME属性中指定。 当通过 Azure DevOps 或 Azure 资源管理器模板部署 Web 应用时,映像还可能出现在名为LinuxFxVersion的属性中。 这两个属性的作用相同。 如果 Web 应用的配置中同时存在这两个属性,则优先使用LinuxFxVersion。
配置 Web 应用
在此步骤中,按如下方式配置 Web 应用:
- 将应用配置为将请求发送到端口 8000。 示例容器在端口 8000 上侦听 Web 请求。
- 将应用配置为使用托管标识从容器注册表拉取映像。
- 从容器注册表配置持续部署。 (每次将映像推送到注册表都会触发你的应用拉取新映像。)在将 Web 应用配置为从容器注册表拉取数据时,此步骤不是必需的,但它可以在有新映像被推送到注册表时通知 Web 应用。 如果未完成此步骤,则必须通过重启 Web 应用来手动触发映像拉取。
- Azure CLI
- Azure 门户
使用
az webapp config appsettings set按应用代码的需要设置WEBSITES_PORT环境变量:az webapp config appsettings set --resource-group msdocs-custom-container-tutorial --name <app-name> --settings WEBSITES_PORT=8000将
<app-name>替换为上一步使用的名称。使用
az webapp identity assign以下命令在 Web 应用中启用用户分配的托管标识:id=$(az identity show --resource-group msdocs-custom-container-tutorial --name myID --query id --output tsv) az webapp identity assign --resource-group msdocs-custom-container-tutorial --name <app-name> --identities $id将
<app-name>替换为上一步使用的名称。使用托管标识将应用配置为从 Container Registry 拉取。
appConfig=$(az webapp config show --resource-group msdocs-custom-container-tutorial --name <app-name> --query id --output tsv) az resource update --ids $appConfig --set properties.acrUseManagedIdentityCreds=True将
<app-name>替换为上一步使用的名称。设置 Web 应用用于从容器注册表拉取的客户端 ID。 如果使用系统分配的托管标识,则不需要此步骤。
clientId=$(az identity show --resource-group msdocs-custom-container-tutorial --name myID --query clientId --output tsv) az resource update --ids $appConfig --set properties.AcrUserManagedIdentityID=$clientId在应用服务中启用 CI/CD。
cicdUrl=$(az webapp deployment container config --enable-cd true --name <app-name> --resource-group msdocs-custom-container-tutorial --query CI_CD_URL --output tsv)CI_CD_URL是应用服务为你生成的 URL。 注册表应使用此 URL 来通知应用服务发生了映像推送。 实际上,它并不会为你创建 Webhook。在容器注册表中创建 Webhook。 使用上一步中获取的CI_CD_URL。
az acr webhook create --name appserviceCD --registry <registry-name> --uri $cicdUrl --actions push --scope appsvc-tutorial-custom-image:latest若要测试 Webhook 是否已正确配置,请 ping webhook 并查看是否获得 200 正常响应。
eventId=$(az acr webhook ping --name appserviceCD --registry <registry-name> --query id --output tsv) az acr webhook list-events --name appserviceCD --registry <registry-name> --query "[?id=='$eventId'].eventResponseMessage"提示
若要查看有关所有 Webhook 事件的所有信息,请删除
--query参数。如果你正在流式查看容器日志,应在 Webhook ping 后看到
Starting container for site消息,因为 Webhook 会触发应用重启。
转到 Web 应用
- Azure CLI
- Azure 门户
若要测试应用,请转到 https://<app-name>.azurewebsites.net。 将 <app-name> 替换为您的 Web 应用名称。
首次尝试访问应用时,应用可能需要一些时间来响应,因为 App Service 必须从镜像注册表中拉取整个映像。 如果浏览器超时,刷新页面即可。 拉取初始映像后,后续测试将运行得更快。
访问诊断日志
- Azure CLI
- Azure 门户
等待应用服务拉取映像时,通过将容器日志流式传输到终端来确切了解应用服务执行的操作是非常有用的。
启用容器日志记录:
az webapp log config --name <app-name> --resource-group msdocs-custom-container-tutorial --docker-container-logging filesystem启用日志流:
az webapp log tail --name <app-name> --resource-group msdocs-custom-container-tutorial如果没有立即看到控制台日志,请在 30 秒后重新查看。
还可以通过浏览器访问
https://<app-name>.scm.azurewebsites.net/api/logs/docker来检查日志文件。不论任何时候,想要停止日志流式处理,请选择 Ctrl+C。
修改应用程序代码并重新部署
在本部分中,你将对 Web 应用代码进行更改,重新生成映像,然后将其推送到容器注册表。 然后,应用服务会自动从容器注册表中拉取更新后的映像,以更新正在运行的 Web 应用。
在本地 docker-django-webapp-linux 文件夹中,打开文件 app/templates/app/index.html。
更改第一个 HTML 元素,使其与以下代码相匹配。
<nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">Azure App Service - Updated Here!</a> </div> </div> </nav>保存所做更改。
转到 docker-django-webapp-linux 文件夹并重新生成映像:
docker build --tag appsvc-tutorial-custom-image .将映像的标记更新为
latest:docker tag appsvc-tutorial-custom-image <registry-name>.azurecr.io/appsvc-tutorial-custom-image:latest将
<registry-name>替换为注册表的名称。将映像推送到镜像仓库:
docker push <registry-name>.azurecr.io/appsvc-tutorial-custom-image:latest当映像推送完成时,Webhook 会通知应用服务有关推送的信息,应用服务会尝试拉取更新后的映像。 等待几分钟,然后转到
https://<app-name>.azurewebsites.net,验证更新是否已部署。
使用 SSH 连接到容器
当容器运行时,你可以通过 App Service 的经过身份验证的 Kudu 代理,使用新版浏览器终端或 az webapp exec 访问它。 你不需要在镜像中安装或启动 SSH 服务器,即可使用这些选项。
关于访问先决条件以及应用或插槽控制,请参见 “打开容器 Shell (SSH) 并运行命令”。
打开与容器的 SSH 连接。
- Azure CLI
- Azure 门户
使用Azure CLI 2.90.0或更高版本,登录你的Azure账户。 在本地终端用预览
az webapp exec命令打开交互式 shell:az webapp exec --resource-group msdocs-custom-container-tutorial --name <app-name>如果图片中有,请使用使用
top,检查应用内正在运行的进程。
如需使用分离式命令执行而不是交互式会话,请参阅在没有交互式会话的情况下运行命令。 请求接受并不能确认命令是否成功完成。
清理资源
- Azure CLI
- Azure 门户
本文中创建的资源可能会持续产生费用。 若要清理资源,只需删除包含这些资源的资源组即可:
az group delete --name msdocs-custom-container-tutorial
后续步骤
你已了解:
- 将自定义映像部署到专用容器注册表。
- 将自定义映像部署到应用服务。
- 更新并重新部署映像。
- 访问诊断日志。
- 使用 SSH 连接到容器。
- 将自定义 Docker 映像推送到容器注册表。
- 将自定义映像部署到应用服务。
- 配置环境变量。
- 使用托管标识将映像拉取到应用服务中。
- 访问诊断日志。
- 启用从容器注册表到应用服务的 CI/CD。
- 使用 SSH 连接到容器。
前往下一个教程:
或者查看其他资源: