Azure Function Failing to Start - “Didn't respond to HTTP pings on port X” (Docker/VNet)

安稳与你 提交于 2020-05-28 03:57:18

问题


I'm really struggling to figure out how to setup an Azure Function that uses a Docker container image and is connected to a VNet. I cannot find any examples of this setup anywhere.

The main issue I'm running into is that after my container is up and running, it does not seem to be responding to the HTTP pings the underlying framework uses to determine if the function is up and running. I believe the primary issue is that when you setup a Linux service that uses Docker and connect it to a VNet, the ports used are not standard (from what I understand). I have updated the ENTRYPOINT line in my dockerfile to handle this accordingly, however the port that is used to test for pings is not the port that is exposed via the docker run command. Here are the log entries that pertain to this startup error:

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.

As you can see in this example, port 8635 is being mapped (to port 8635) and is being specified as an environment variable, which is coming from the underlying vnet setup. However, the HTTP pings are being sent to port 3236. I see that this is part of the /Host.DestinationHostUrl parameter towards the end of the docker run command, but I don't see how I can get access to this parameter since it's not being passed as an environment variable like the PORT is.

Here is my 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"

FYI The default Dockerfile created by the Azure Function tool chain does not work. It errors out with an error like this:

(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

To get around this error, I had to do what I said above by using the PORT environment variable and --urls parameter.

I assume what I need to do is add this other port to the --urls=... parameter I'm passing to the ENTRYPOINT, but cannot figure out how to do this.

Does anyone have any idea how to setup an Azure function that uses both Docker and VNet?


回答1:


By default, the api listening port is 80 right? but VNet dynamically changes the port on every restart via PORT environment variable. Even if you attempt to set the PORT environment variable manually to 80, VNet still overrides it. Its part of the security provided by Vnet.

The solution is the api's listening port must always point to what every the environment variable PORT is.

In your docker image, use the PORT environment variable as the main web server’s listening port, instead of using a hardcoded port number

As mentioned in the doc


Suggestions

One option is code level, make your app listen to the PORT environment variable, like this js example or an asp example. The problem here is that you have to always configure the PORT environment variable anywhere you run your app (locally or staging or production), not unless you make additional changes to detect ENV PORT going down the rabbit hole further.


Another option is to configure the listening port to ENVIRONMENT PORT during docker build. The ENTRYPOINT command in the Dockerfile looks like this:

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



回答2:


I believe we take care of forwarding the right ports when you use the -appservice variant of the functions base tag.

https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-function-linux-custom-image?tabs=bash%2Cportal&pivots=programming-language-csharp#enable-ssh-connections

So modifying this line in the dockerfile from this:

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

To this

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

May resolve



来源:https://stackoverflow.com/questions/60675890/azure-function-failing-to-start-didnt-respond-to-http-pings-on-port-x-dock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!