Azure 函数无法启动 - "Didn't respond to HTTP pings on port X" (Docker/VNet)



我真的很难弄清楚如何设置一个使用Docker容器映像并连接到VNet的Azure函数。我在任何地方都找不到这种设置的任何示例。

我遇到的主要问题是,在我的容器启动并运行后,它似乎没有响应底层框架用来确定函数是否启动并运行的HTTP ping。我认为主要的问题是,当你设置一个使用Docker的Linux服务并将其连接到VNet时,所使用的端口不是标准的(据我所知(。我已经更新了dockerfile中的ENTRYPOINT行以相应地处理此问题,但是用于测试ping的端口不是通过docker run命令公开的端口。以下是与此启动错误相关的日志条目:

INFO  - Starting container for site
INFO  - docker run -d -p 8635:8635 --name evo-item-exporter-stage_0_42c1415b_middleware -e WEBSITE_CORS_ALLOWED_ORIGINS=https://functions.azure.com,https://functions-staging.azure.com,https://functions-next.azure.com -e WEBSITE_CORS_SUPPORT_CREDENTIALS=False -e WEBSITES_ENABLE_APP_SERVICE_STORAGE=false -e WEBSITE_SITE_NAME=evo-item-exporter-stage -e WEBSITE_AUTH_ENABLED=False -e PORT=8635 -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=evo-item-exporter-stage.azurewebsites.net -e WEBSITE_INSTANCE_ID=47d698ac06f21187d3dc07a6ddd707f955f4ca9b939be455493969c8c2fb4bb8 appsvc/middleware:1907112318 /Host.ListenUrl=http://0.0.0.0:8635 /Host.DestinationHostUrl=http://10.5.6.4:3236 /Host.UseFileLogging=true 
INFO  - Logging is not enabled for this container.
Please use https://aka.ms/linux-diagnostics to enable logging to see container logs here.
INFO  - Initiating warmup request to container evo-item-exporter-stage_0_42c1415b_msiProxy for site evo-item-exporter-stage
INFO  - Container evo-item-exporter-stage_0_42c1415b_msiProxy for site evo-item-exporter-stage initialized successfully and is ready to serve requests.
INFO  - Initiating warmup request to container evo-item-exporter-stage_0_42c1415b for site evo-item-exporter-stage
ERROR - Container evo-item-exporter-stage_0_42c1415b for site evo-item-exporter-stage has exited, failing site start
INFO  - Initiating warmup request to container evo-item-exporter-stage_0_42c1415b_middleware for site evo-item-exporter-stage
INFO  - Container evo-item-exporter-stage_0_42c1415b_middleware for site evo-item-exporter-stage initialized successfully and is ready to serve requests.
ERROR - Container evo-item-exporter-stage_0_42c1415b didn't respond to HTTP pings on port: 3236, failing site start. See container logs for debugging.
INFO  - Stoping site evo-item-exporter-stage because it failed during startup.

正如您在本例中看到的,端口8635正在被映射(到端口8635(,并被指定为环境变量,该变量来自底层vnet设置。然而,HTTP ping正在被发送到端口3236。我知道这是/Host的一部分。DestinationHostUrl参数接近docker运行命令的末尾,但我不知道如何访问此参数,因为它不像PORT那样作为环境变量传递。

这是我的Dockerfile:

FROM mcr.microsoft.com/azure-functions/dotnet:2.0 AS base
WORKDIR /app
EXPOSE 80
ENV PORT=80
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY ["nuget.config", ""]
COPY ["ItemExporter/app.ItemExporter/app.ItemExporter.csproj", "ItemExporter/app.ItemExporter/"]
COPY ["ItemExporter/evo.Domain/evo.Domain.csproj", "ItemExporter/evo.Domain/"]
COPY ["ItemExporter/evo.DependencyInjection/evo.DependencyInjection.csproj", "ItemExporter/evo.DependencyInjection/"]
COPY ["ItemExporter/evo.Infrastructure/evo.Infrastructure.csproj", "ItemExporter/evo.Infrastructure/"]
RUN dotnet restore "ItemExporter/app.ItemExporter/app.ItemExporter.csproj"
COPY . .
WORKDIR "/src/ItemExporter/app.ItemExporter"
RUN dotnet build "app.ItemExporter.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "app.ItemExporter.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV AzureWebJobsScriptRoot=/app
#See the Azure function docker file to get the correct entrypoint syntax
#in case this changes in the future
#https://github.com/Azure/azure-functions-host/blob/dev/Dockerfile
#The --urls=... part is needed to run inside an Azure App Service w/ vnet integration
ENTRYPOINT dotnet /azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost.dll --urls="http://0.0.0.0:$PORT"

仅供参考Azure Function工具链创建的默认Dockerfile不起作用。它出现了这样的错误:

(Failed to bind to address http://[::]:5169: address already in use.) ---> System.IO.IOException: Failed to bind to address http://[::]:5169: address already in use. ---> Microsoft.AspNetCore.Connections.AddressInUseException: Address already in use ---> System.Net.Sockets.SocketException: Address already in use

为了避免这个错误,我必须使用PORT环境变量和--urls参数来执行上面所说的操作。

我想我需要做的是将另一个端口添加到我传递给ENTRYPOINT的--urls=...参数中,但我不知道如何做到这一点。

有人知道如何设置同时使用Docker和VNet的Azure功能吗?

默认情况下,api监听端口是80对吗?但是VNet在每次重新启动时通过port环境变量动态地改变端口。即使您尝试手动将PORT环境变量设置为80,VNet仍然会覆盖它。它是VNet提供的安全性的一部分。

解决方案是api的侦听端口必须始终指向每个环境变量port是什么

在docker映像中,使用PORT环境变量作为主web服务器的侦听端口,而不是使用硬编码的端口号

如文档中所述


建议

一个选项是代码级别,让你的应用程序监听PORT环境变量,比如这个js示例或asp示例。这里的问题是,您必须始终在任何运行应用程序的地方配置PORT环境变量(本地、暂存或生产(,除非您进行额外的更改以检测ENV PORT是否会进一步陷入兔子洞。


另一个选项是在docker构建期间将侦听端口配置为环境端口。Dockerfile中的ENTRYPOINT命令如下所示:

ENTRYPOINT "dotnet" "Tutorial.WebApi.dll" --urls="http://0.0.0.0:${PORT:-80}"

我相信,当您使用函数基标记的-appservice变体时,我们会注意转发正确的端口。

https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-function-linux-custom-image?tabs=bash%2Cportal&pivots=编程语言csharp#启用ssh连接

因此,从以下内容修改dockerfile中的这一行:

FROM mcr.microsoft.com/azure-functions/dotnet:2.0 AS base

到此

FROM mcr.microsoft.com/azure-functions/dotnet:2.0-appservice AS base

可能解决

最新更新