你当前正在访问 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 中心帐户。
- 安装用于 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 Compose”“确定” 。
现在,项目设置为在 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 容器中的应用服务。
查看容器启动日志
加载 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 文件夹中打开终端窗口。
(可选)检查 Docker 文件
下面是名为 Dockerfile 的示例中的文件。 它描述了 Docker 映像并包含配置说明。
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/
# ssh
ENV SSH_PASSWD "root:Docker!"
RUN apt-get update \
&& apt-get install -y --no-install-recommends dialog \
&& apt-get update \
&& apt-get install -y --no-install-recommends openssh-server \
&& echo "$SSH_PASSWD" | chpasswd
COPY sshd_config /etc/ssh/
COPY init.sh /usr/local/bin/
RUN chmod u+x /usr/local/bin/init.sh
EXPOSE 8000 2222
#CMD ["python", "/code/manage.py", "runserver", "0.0.0.0:8000"]
ENTRYPOINT ["init.sh"]
- 第一组命令在环境中安装应用的要求。
- 第二组命令创建 SSH 服务器以在容器和主机之间提供改进了安全性的通信。
- 最后一行
ENTRYPOINT ["init.sh"]调用init.sh来启动 SSH 服务和 Python 服务器。
在本地生成和测试映像
注意
Docker 中心 对每个 IP 的匿名拉取数和每个免费用户经过身份验证的拉取数施加配额。 如果发现 Docker 中心的拉取受到限制,请尝试在尚未登录的情况下运行 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 应用和容器是否正常运行。
创建用户分配的托管标识
应用服务可以使用默认托管标识或用户分配的托管标识向容器注册表进行身份验证。 本教程使用用户分配的托管标识。
运行 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
创建容器注册表
使用以下
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 输出提供两个密码以及注册表的用户名。
将示例映像推送到容器注册表
在本部分中,会将映像推送到容器注册表,稍后由应用服务使用。
在生成示例映像的本地终端中,使用
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第一次上传映像可能需要几分钟时间,因为它包含基本映像。 后续上传速度通常较快。
在等待期间,可以完成下一部分中的步骤,将应用服务配置为从注册表部署。
为注册表的托管标识授权
创建的托管标识尚未获得从容器注册表拉取的授权。 在此步骤中,你将启用授权。
检索托管标识的主体 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 应用
使用
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 应用来手动触发映像拉取。
使用
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>替换为上一步使用的名称。使用托管标识将应用配置为从容器注册表拉取。
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 应用
首次尝试访问应用时,应用可能需要一些时间来响应,因为应用服务必须从注册表中拉取整个映像。 如果浏览器超时,刷新页面即可。 拉取初始映像后,后续测试将运行得更快。
访问诊断日志
等待应用服务拉取映像时,通过将容器日志流式传输到终端来确切了解应用服务执行的操作是非常有用的。
启用容器日志记录:
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 连接到容器
SSH 提高了容器与客户端之间的通信安全性。 若要启用与容器的 SSH 连接,必须为该连接配置自定义映像。 容器运行后,你可以打开 SSH 连接。
为 SSH 配置容器
本教程中使用的示例应用已在 Dockerfile 中具有必要的配置,该配置会安装 SSH 服务器,并设置登录凭据。 本部分仅供参考。 若要连接到容器,请跳到下一部分。
ENV SSH_PASSWD "root:Docker!"
RUN apt-get update \
&& apt-get install -y --no-install-recommends dialog \
&& apt-get update \
&& apt-get install -y --no-install-recommends openssh-server \
&& echo "$SSH_PASSWD" | chpasswd
注意
此配置不允许从外部建立到容器的连接。 SSH 只能通过 Kudu/SCM 站点使用。 Kudu/SCM 站点使用 Azure 帐户进行身份验证。
root:Docker! 使用 SSH 时不应更改。 SCM/KUDU 使用 Azure 门户凭据。 使用 SSH 时,更改此值将导致错误。
Dockerfile 还会将 sshd_config 文件复制到 /etc/ssh/ 文件夹,并在容器上公开端口 2222:
COPY sshd_config /etc/ssh/
# ...
EXPOSE 8000 2222
端口 2222 是一个仅供内部使用的端口,仅可供专用虚拟网络的桥网络中的容器访问。
最后,入口脚本 init.sh 启动 SSH 服务器。
#!/bin/bash
service ssh start
打开与容器的 SSH 连接。
转到
https://<app-name>.scm.azurewebsites.net/webssh/hostAzure 帐户并登录。 将<app-name>替换为 Web 应用的名称。登录后,你会被重定向到 Web 应用的信息页。 选择页面顶部的“SSH”,打开 shell 并使用命令。
例如,可以使用
top命令检查在应用中运行的进程。
清理资源
后续步骤
你已了解:
- 将自定义映像部署到专用容器注册表。
- 将自定义映像部署到应用服务。
- 更新并重新部署映像。
- 访问诊断日志。
- 使用 SSH 连接到容器。
- 将自定义 Docker 映像推送到容器注册表。
- 将自定义映像部署到应用服务。
- 配置环境变量。
- 使用托管标识将映像拉取到应用服务中。
- 访问诊断日志。
- 将 CI/CD 从容器注册表启用到应用服务。
- 使用 SSH 连接到容器。
转到下一教程:
或者查看其他资源: