本文说明如何将自定义容器配置为在 Azure App Service 上运行。
本指南提供有关应用服务中的 Linux 应用的容器化的重要概念和说明。 如果不熟悉 Azure 应用服务,请先遵循 自定义容器快速入门 和 教程。 对于挎斗容器,请参阅教程:在 Azure 应用服务中为自定义容器配置挎斗容器。
注意
Windows 容器映像拉取身份验证不再支持服务主体。 建议对 Windows 和 Linux 容器使用托管标识
支持的父映像
对于自定义 Windows 映像,请为所需框架选择适当的父映像(基础映像):
- 若要部署 .NET Framework 应用,请使用基于 Windows Server 2019 Core 长期服务渠道 (LTSC) 发行版的父映像。
- 若要部署 .NET Core 应用,请使用基于 Windows Server 2019 Nano 年度渠道 (AC) 发行版的父映像。
在应用启动期间,下载父映像需要一些时间。 可以使用已在 Azure 应用服务中缓存的以下父映像之一来缩短启动时间:
- mcr.microsoft.com/windows/servercore:ltsc2022
- mcr.microsoft.com/windows/servercore:ltsc2019
- mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2022
- mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019
- mcr.microsoft.com/dotnet/runtime:6.0-nanoserver-ltsc2022
- mcr.microsoft.com/dotnet/runtime:6.0-nanoserver-1809
- mcr.microsoft.com/dotnet/aspnet:6.0-nanoserver-ltsc2022
- mcr.microsoft.com/dotnet/aspnet:6.0-nanoserver-1809
更改自定义容器的 Docker 映像
若要将现有的自定义容器从当前 Docker 映像更改为新映像,请使用以下命令:
az webapp config container set --name <app-name> --resource-group <group-name> --docker-custom-image-name <docker-hub-repo>/<image>
使用专用注册表中的映像
使用专用注册表(如 Azure 容器注册表)中的映像,请运行以下命令:
az webapp config container set --name <app-name> --resource-group <group-name> --docker-custom-image-name <image-name> --docker-registry-server-url <private-repo-url> --docker-registry-server-user <username> --docker-registry-server-password <password>
对于 <username> 和 <password>,请提供专用注册表帐户的登录凭据。
使用托管标识从 Azure 容器注册表拉取映像
使用以下步骤配置 Web 应用,以使用托管标识从 Azure 容器注册表 (ACR) 进行拉取。 这些步骤使用系统分配的托管标识。 可以改用用户分配的托管标识。
使用 az webapp identity assign 命令为 Web 应用启用系统分配的托管标识:
az webapp identity assign --resource-group <group-name> --name <app-name> --query principalId --output tsv
将应用名称>替换为<在上一步中使用的名称。 命令的输出(由
--query
和--output
参数筛选)是分配的标识的服务主体 ID。获取 Azure 容器注册表的资源 ID:
az acr show --resource-group <group-name> --name <registry-name> --query id --output tsv
将 <registry-name> 替换为注册表的名称。 通过
--query
和--output
参数筛选后,命令的输出是 Azure 容器注册表的资源 ID。授予托管标识访问容器注册表的权限:
az role assignment create --assignee <principal-id> --scope <registry-resource-id> --role "AcrPull"
请替换以下值:
- 将 <principal-id> 替换为
az webapp identity assign
命令中的服务主体 ID - 将 <registry-resource-id> 替换为
az acr show
命令中的容器注册表的 ID
有关这些权限的详细信息,请参阅什么是 Azure 基于角色的访问控制。
- 将 <principal-id> 替换为
配置应用,以使用托管标识从 Azure 容器注册表进行拉取。
az webapp config set --resource-group <group-name> --name <app-name> --generic-configurations '{"acrUseManagedIdentityCreds": true}'
请替换以下值:
- 将 <app-name> 替换为 Web 应用的名称。
提示
如果使用 PowerShell 控制台来运行命令,请在本步骤和下一步骤中对
--generic-configurations
参数中的字符串进行转义。 例如:--generic-configurations '{\"acrUseManagedIdentityCreds\": true'
(可选)如果应用使用用户分配的托管标识,请确保在 Web 应用中已进行了标识配置,然后设置
acrUserManagedIdentityID
属性来指定其客户端 ID:az identity show --resource-group <group-name> --name <identity-name> --query clientId --output tsv
替换用户分配的托管标识的
<identity-name>
,并使用输出<client-id>
来配置用户分配的托管标识 ID。az webapp config set --resource-group <group-name> --name <app-name> --generic-configurations '{"acrUserManagedIdentityID": "<client-id>"}'
你准备好了! Web 应用现在会使用托管标识从 Azure 容器注册表中进行拉取。
使用受网络保护的注册表中的映像
若要从虚拟网络或本地的注册表进行连接和拉取,应用必须与虚拟网络集成。 您还需要将 Azure 容器注册表与私有终结点进行虚拟网络集成。 配置好网络和 DNS 解析后,可通过配置 vnetImagePullEnabled
站点设置来启用通过虚拟网络的映像拉取路由:
az resource update --resource-group <group-name> --name <app-name> --resource-type "Microsoft.Web/sites" --set properties.vnetImagePullEnabled [true|false]
我看不到更新的容器
如果将 Docker 容器的设置更改为指向新的容器,可能需要几分钟,应用才能从新容器处理 HTTP 请求。 在拉取和启动新容器时,应用服务会继续处理来自旧容器的请求。 只有新容器已启动并准备好接收请求后,应用服务才会开始向新容器发送请求。
容器映像的存储方式
首次在应用服务中运行自定义 Docker 映像时,应用服务会执行 docker pull
并拉取所有映像层。 这些层存储在磁盘上,就像使用 Docker 本地一样。 每次应用重启时,应用服务都会执行一个 docker pull
。 它只会拉取已更改的层。 如果没有更改,应用服务将使用本地磁盘上的现有层。
如果应用由于某种原因(例如向上和向下扩展定价层)更改了计算实例,应用服务必须再次拉取所有层。 如果横向扩展以添加更多实例,则也是这种情况。 在极少数情况下,应用实例可能会在不进行扩展操作的情况下发生变化。
配置端口号
默认情况下,应用程序服务会假定您的自定义容器监听端口 80。 如果容器侦听其他端口,请在应用服务应用中设置 WEBSITES_PORT
应用设置。 可以使用 Cloud Shell 设置它。 在 Bash 中:
az webapp config appsettings set --resource-group <group-name> --name <app-name> --settings WEBSITES_PORT=8000
在 PowerShell 中:
Set-AzWebApp -ResourceGroupName <group-name> -Name <app-name> -AppSettings @{"WEBSITES_PORT"="8000"}
应用服务目前允许容器只为 HTTP 请求提供一个端口。
配置环境变量
自定义容器可能会使用需要在外部提供的环境变量。 可以通过 Azure CLI 将参数传入。 在 Bash 中:
az webapp config appsettings set --resource-group <group-name> --name <app-name> --settings DB_HOST="myownserver.mysql.database.chinacloudapi.cn"
在 PowerShell 中
Set-AzWebApp -ResourceGroupName <group-name> -Name <app-name> -AppSettings @{"DB_HOST"="myownserver.mysql.database.chinacloudapi.cn"}
当应用运行时,应用服务应用设置会自动作为环境变量注入到进程中。 可以通过 URL https://<app-name>.scm.chinacloudsites.cn/Env
来验证容器环境变量。
如果应用使用专用注册表或 Docker Hub 中的映像,则用于访问存储库的凭据保存在环境变量中:DOCKER_REGISTRY_SERVER_URL
和DOCKER_REGISTRY_SERVER_USERNAME
DOCKER_REGISTRY_SERVER_PASSWORD
。 由于存在安全风险,这些保留变量名都不会向应用程序公开。
对于基于 IIS 或 .NET Framework(版本 4.0 或更高)的容器,应用服务会自动将凭据注入到 System.ConfigurationManager
中,作为 .NET 应用设置和连接字符串。 对于所有其他语言或框架,它们作为进程的环境变量提供,其中包含以下前缀之一:
APPSETTING_
SQLCONTR_
MYSQLCONTR_
SQLAZURECOSTR_
POSTGRESQLCONTR_
CUSTOMCONNSTR_
此方法适用于单容器应用或多容器应用,其中环境变量是在 docker-compose.yml 文件中指定的。
使用持久共享存储
你可以在你的自定义容器文件系统中使用 C:\home 目录,以便在重新启动时持续保存文件,并在不同的实例中共享它们。 提供了 C:\home 目录,使自定义容器能够访问永久性存储。
禁用永久性存储后,不会在应用重启或多个实例之间保留对 C:\home 目录的写入。 启用永久性存储后,所有写入 C:\home 目录都会保留。 横向扩展应用的所有实例都可以访问它们。 容器启动时,持久性存储上已存在的任何文件都会覆盖容器中 C:\home 目录的任何内容。
唯一的例外是 C:\home\LogFiles 目录。 此目录存储容器和应用程序日志。 如果启用了应用程序日志记录,并且选择了文件系统选项,那么无论是否启用永久性存储,该文件夹总是存在。 换句话说,启用或禁用持久存储不影响应用程序的日志记录行为。
默认情况下,在 Windows 自定义容器上启用持久存储。 若要禁用它,请使用 Cloud Shell 将WEBSITES_ENABLE_APP_SERVICE_STORAGE
应用设置的值设为false
。 在 Bash 中:
az webapp config appsettings set --resource-group <group-name> --name <app-name> --settings WEBSITES_ENABLE_APP_SERVICE_STORAGE=false
在 PowerShell 中:
Set-AzWebApp -ResourceGroupName <group-name> -Name <app-name> -AppSettings @{"WEBSITES_ENABLE_APP_SERVICE_STORAGE"=false}
你可以在你的自定义容器文件系统中使用 /home 目录,以便在重新启动时持续保存文件,并在不同的实例中共享它们。 提供了 /home 目录,使自定义容器能够访问永久性存储。 在 /home 中保存数据有助于应用服务计划中包含的 存储空间配额 。
禁用永久性存储后,不会在应用重启或多个实例之间保留对 C:\home 目录的写入。 启用永久性存储后,所有写入 \home 目录都会保留。 横向扩展应用的所有实例都可以访问它们。 当容器启动时,持久存储中已存在的任何文件都将覆盖容器中 \home 目录中的内容。
唯一的例外是 \home\LogFiles 目录。 此目录存储容器和应用程序日志。 如果在文件系统选项下启用应用程序日志记录,则此文件夹在应用程序重启后始终保留,无论是否启用永久性存储。 换句话说,启用或禁用持久存储不影响应用程序的日志记录行为。
建议将数据写入 /home 或 装载的 Azure 存储路径。 在重启期间,在这些路径外部写入的数据不会持久。 数据将保存到独立于应用服务计划文件存储配额的平台托管主机磁盘空间。
默认情况下,持久存储在 Linux 自定义容器上处于已禁用状态。 若要启用它,请使用 Cloud Shell 将 WEBSITES_ENABLE_APP_SERVICE_STORAGE
应用设置的值设置为 true
。 在 Bash 中:
az webapp config appsettings set --resource-group <group-name> --name <app-name> --settings WEBSITES_ENABLE_APP_SERVICE_STORAGE=true
在 PowerShell 中:
Set-AzWebApp -ResourceGroupName <group-name> -Name <app-name> -AppSettings @{"WEBSITES_ENABLE_APP_SERVICE_STORAGE"=true}
备注
你还可以配置自己的持久存储。
检测 HTTPS 会话
应用服务在前端终止 TLS。 这意味着 TLS 请求永远不会到达你的应用。 无需(不应)在应用中实现对 TLS 的任何支持。
前端位于 Azure 数据中心内。 如果将 TLS 用于应用,则通过 Internet 的流量始终安全加密。
自定义 ASP.NET 计算机密钥注入
在容器启动过程中,会将自动生成的密钥作为 ASP.NET 加密例程的计算机密钥注入到容器中。 可以通过以下环境变量在容器中找到这些密钥:MACHINEKEY_Decryption
、MACHINEKEY_DecryptionKey
、MACHINEKEY_ValidationKey
、MACHINEKEY_Validation
。
如果应用程序依赖于这些密钥,每次重启时的新密钥可能会重置 ASP.NET 窗体身份验证和视图状态。 要阻止自动重新生成密钥,请手动将其设置为应用服务应用设置。
连接到容器
若要直接连接到 Windows 容器以执行诊断任务,请导航到 https://<app-name>.scm.chinacloudsites.cn/
并选择 SSH 选项。 此选项建立直接 SSH 会话,可在其中运行容器内的命令。
- 它独立于其上方的图形浏览器运行,只显示共享存储中的文件。
- 在向外扩展的应用程序中,SSH 会话连接到一个容器实例。 可以从顶部 Kudu 菜单中的 “实例 ”下拉列表中选择不同的实例。
- 共享存储中的更改除外,在重启应用时,从 SSH 会话中对容器所做的任何更改 都不会 保留。 此类更改不属于 Docker 镜像。 要保存更改,如注册表设置和软件安装,请将其设为 Dockerfile 的一部分。
访问诊断日志
应用服务记录 Docker 主机的操作以及容器中的活动。 默认情况下会启用 Docker 主机(平台日志)中的日志。 需要从容器中手动启用应用程序日志或 Web 服务器日志。 有关详细信息,请参阅启用应用程序日志记录和启用 Web 服务器日志记录。
有多种方法可访问 Docker 日志:
在 Azure 门户中
Docker 日志显示在 Azure 门户的应用的 “容器设置” 页中。 日志将被截断。 若要下载所有日志,请选择“ 下载”。
通过 Kudu
若要查看单个日志文件,请导航到 https://<app-name>.scm.chinacloudsites.cn/DebugConsole
并选择 LogFiles 文件夹。 若要下载整个 LogFiles 目录,请选择目录名称左侧的 “下载 ”图标。 还可以使用 FTP 客户端访问此文件夹。
在 SSH 终端中,默认情况下无法访问 C:\home\LogFiles 文件夹,因为未启用永久性共享存储。 要在控制台终端中启用此行为,请启用持久共享存储。
如果尝试使用 FTP 客户端下载当前正在使用的 Docker 日志,可能会由于文件锁定而出现错误。
使用 Kudu API
直接导航到 https://<app-name>.scm.chinacloudsites.cn/api/logs/docker
以查看 Docker 日志的元数据。 可能会列出多个日志文件。 使用该 href
属性可以直接下载日志文件。
要将所有日志一起下载到一个 ZIP 文件中,请访问 https://<app-name>.scm.chinacloudsites.cn/api/logs/docker/zip
。
自定义容器内存
默认情况下,在 Azure 应用服务中部署的所有 Windows 容器都配置了内存限制。 下表列出了每个应用服务计划 SKU 的默认设置。
应用服务计划 SKU | 每个应用的默认内存限额(以 MB 为单位) |
---|---|
P1v3 | 1024 |
P1Mv3 | 1024 |
P2v3 | 1536 |
P2Mv3 | 1536 |
可以通过 Azure CLI 或 Azure PowerShell 提供 WEBSITE_MEMORY_LIMIT_MB
应用设置来更改此值。 在 Bash 中:
az webapp config appsettings set --resource-group <group-name> --name <app-name> --settings WEBSITE_MEMORY_LIMIT_MB=2000
在 PowerShell中:
Set-AzWebApp -ResourceGroupName <group-name> -Name <app-name> -AppSettings @{"WEBSITE_MEMORY_LIMIT_MB"=2000}
该值以 MB 为单位定义,并且必须小于或等于主机的总物理内存。 例如,在 RAM 为 8 GB 的应用服务计划中,所有应用的累积总数 WEBSITE_MEMORY_LIMIT_MB
不得超过 8 GB。 有关每个定价层可用的内存量的详细信息,请参阅 应用服务定价。
自定义计算核心数
默认情况下,Windows 容器将运行,其中包含所选定价层的所有可用内核。 你可能想要减少过渡槽使用的核心数。 要减少容器使用的内核数,请将 WEBSITE_CPU_CORES_LIMIT
应用设置设置为首选的内核数。 可以通过 Azure CLI 进行设置。 在 Bash 中:
az webapp config appsettings set --resource-group <group-name> --name <app-name> --slot staging --settings WEBSITE_CPU_CORES_LIMIT=1
在 PowerShell 中:
Set-AzWebApp -ResourceGroupName <group-name> -Name <app-name> -AppSettings @{"WEBSITE_CPU_CORES_LIMIT"=1}
提示
更新应用设置会触发自动重启,这会导致最短的停机时间。 对于生产应用程序,请考虑将其切换到暂存槽,然后在暂存槽中更改应用设置,再切换回生产槽。
若要验证调整后的号码,请从 Azure 门户打开 SSH 会话或使用 Kudu 门户(https://<app-name>.scm.chinacloudsites.cn/webssh/host
)。 使用 PowerShell 输入以下命令。 每个命令返回一个数字。
Get-ComputerInfo | ft CsNumberOfLogicalProcessors # Total number of enabled logical processors. Disabled processors are excluded.
Get-ComputerInfo | ft CsNumberOfProcessors # Number of physical processors.
处理器可能是多核处理器或超线程处理器。 有关每个定价层可用核心数量的信息,请参阅应用程序服务定价。
自定义运行状况 ping 行为
应用服务认为容器在启动并响应 HTTP ping 时已成功启动。 运行状况 ping 请求包含标头 User-Agent= "App Service Hyper-V Container Availability Check"
。 如果容器在某个时间后启动但不响应 ping,应用服务会在 Docker 日志中记录事件。
如果你的应用程序占用大量资源,则容器可能无法及时响应 HTTP ping。 要控制 HTTP ping 失败时的操作,请设置 CONTAINER_AVAILABILITY_CHECK_MODE
应用设置。 可以通过 Azure CLI 进行设置。 在 Bash 中:
az webapp config appsettings set --resource-group <group-name> --name <app-name> --settings CONTAINER_AVAILABILITY_CHECK_MODE="ReportOnly"
在 PowerShell 中:
Set-AzWebApp -ResourceGroupName <group-name> -Name <app-name> -AppSettings @{"CONTAINER_AVAILABILITY_CHECK_MODE"="ReportOnly"}
下表列出了可能的值:
值 | 说明 |
---|---|
修理 | 连续进行三次可用性检查后重启容器。 |
ReportOnly | 默认值。 请不要重启容器,但在三次连续的可用性检查后,会在容器的 Docker 日志中报告。 |
关闭 | 不检查可用性。 |
支持组托管服务帐户
应用服务中的 Windows 容器当前不支持组托管服务帐户 (gMSA)。
启用 SSH
安全外壳 (SSH) 通常用于通过命令行终端以远程方式运行管理命令。 若要使用自定义容器启用 Azure 门户 SSH 控制台功能,请执行以下步骤:
使用以下示例内容创建标准
sshd_config
文件,并将其放置在应用程序项目根目录上:Port 2222 ListenAddress 0.0.0.0 LoginGraceTime 180 X11Forwarding yes Ciphers aes128-cbc,3des-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr MACs hmac-sha1,hmac-sha1-96 StrictModes yes SyslogFacility DAEMON PasswordAuthentication yes PermitEmptyPasswords no PermitRootLogin yes Subsystem sftp internal-sftp
注意
此文件配置 OpenSSH,并且必须包含以下项,以符合 Azure 门户 SSH 功能:
Port
必须设置为 2222。Ciphers
必须至少包含此列表中的一项:aes128-cbc,3des-cbc,aes256-cbc
。MACs
必须至少包含此列表中的一项:hmac-sha1,hmac-sha1-96
。
创建一个名为 entrypoint.sh 的入口点脚本,或更改任何现有的入口点文件。 添加命令以启动 SSH 服务,以及应用程序启动命令。 以下示例演示如何启动 Python 应用程序。 请根据项目语言/堆栈替换最后一个命令:
根据基础映像分发方式,将以下说明添加到 Dockerfile。 这些指示会分别复制新文件、安装 OpenSSH 服务器、设置适当的权限和配置自定义入口点,并公开应用程序和 SSH 服务器所需的端口:
COPY entrypoint.sh ./ # Start and enable SSH RUN apt-get update \ && apt-get install -y --no-install-recommends dialog \ && apt-get install -y --no-install-recommends openssh-server \ && echo "root:Docker!" | chpasswd \ && chmod u+x ./entrypoint.sh COPY sshd_config /etc/ssh/ EXPOSE 8000 2222 ENTRYPOINT [ "./entrypoint.sh" ]
注意
根密码必须完全
Docker!
是因为应用服务使用它来访问容器的 SSH 会话。 此配置不允许从外部建立到容器的连接。 容器的端口 2222 只能在专用虚拟网络的桥网络中访问,Internet 上的攻击者无法访问该端口。重新生成 Docker 映像并将其推送到注册表,然后在 Azure 门户中测试 Web 应用 SSH 功能。
有关故障排除的详细信息,请参阅 Azure 应用服务博客: 在适用于容器的 Linux Web 应用上启用 SSH
访问诊断日志
可以访问在容器中生成的控制台日志。
首先,请运行以下命令,以便启用容器日志记录功能:
az webapp log config --name <app-name> --resource-group <resource-group-name> --docker-container-logging filesystem
将 <app-name>
和 <resource-group-name>
替换为适合 Web 应用的名称。
启用容器日志记录功能以后,请运行以下命令来查看日志流:
az webapp log tail --name <app-name> --resource-group <resource-group-name>
如果没有立即看到控制台日志,请在 30 秒后重新查看。
为随时停止日志流式处理,请按 Ctrl++C。
也可通过浏览器在 https://<app-name>.scm.chinacloudsites.cn/api/logs/docker
中检查日志文件。
配置多容器应用
在 Docker Compose 中使用持久性存储
多容器应用(如 WordPress)需要持久存储才能正常工作。 要启用它,你的 Docker Compose 配置必须指向容器外部的存储位置。 在应用重新启动后,容器中的存储位置不会保存更改。
若要启用持久存储,请设置 WEBSITES_ENABLE_APP_SERVICE_STORAGE
应用设置。 在 Azure CLI 中使用 az webapp config appsettings set 命令。
az webapp config appsettings set --resource-group <group-name> --name <app-name> --settings WEBSITES_ENABLE_APP_SERVICE_STORAGE=TRUE
在 docker-compose.yml 文件中,将 volumes
选项映射到 ${WEBAPP_STORAGE_HOME}
。
WEBAPP_STORAGE_HOME
是一个应用服务中的环境变量,它被映射到应用的持久性存储。 例如:
wordpress:
image: <image name:tag>
volumes:
- "${WEBAPP_STORAGE_HOME}/site/wwwroot:/var/www/html"
- "${WEBAPP_STORAGE_HOME}/phpmyadmin:/var/www/phpmyadmin"
- "${WEBAPP_STORAGE_HOME}/LogFiles:/var/log"
预览限制
多容器功能目前处于预览状态。 不支持以下应用服务平台功能:
- 身份验证/授权
- 托管标识
- CORS
- Docker Compose 方案不支持虚拟网络集成。
- 目前,Azure 应用服务上的 Docker Compose 的限制为 4,000 个字符。
Docker Compose 选项
以下列表显示了支持和不支持的 Docker Compose 配置选项:
支持的选项
- command
- entrypoint
- 环境
- image
- ports
- 重启
- services
- volumes(不支持映射到 Azure 存储)
不支持的选项
- build(不允许)
- depends_on(已忽略)
- 网络(忽略)
- secrets(忽略)
- 除了 80 和 8080 之外的端口(忽略)
- 默认环境变量(如
$variable and ${variable}
)与 docker 中的不同
语法限制
- “version x.x”始终需要是文件中的第一个 YAML 语句
- 端口部分必须使用带引号的数字
- 图像>卷部分必须带引号,并且不能具有权限定义
- 卷部分在卷名后不得有空的大括号
注意
未显式指明的任何其他选项在公共预览版中将被忽略。
日志中的 robots933456
你可能会在容器日志中看到以下消息:
2019-04-08T14:07:56.641002476Z "-" - - [08/Apr/2019:14:07:56 +0000] "GET /robots933456.txt HTTP/1.1" 404 415 "-" "-"
可以放心忽略此消息。 /robots933456.txt
是一个虚拟 URL 路径,应用服务使用它来检查容器能否为请求提供服务。 404 响应只是指示该路径不存在,但它让应用服务知道容器处于正常状态并已准备就绪,可以响应请求。
相关内容
或查看更多资源: