Azure Функция не запускается - «Не отвечает на HTTP-запросы на порт X» (Docker / VNet) - PullRequest
2 голосов
/ 13 марта 2020

Я действительно изо всех сил пытаюсь выяснить, как настроить функцию Azure, которая использует изображение контейнера Docker и подключена к VNet. Я нигде не могу найти никаких примеров этой установки.

Основная проблема, с которой я сталкиваюсь, заключается в том, что после того, как мой контейнер запущен и работает, он, похоже, не отвечает на HTTP-пинги, которые базовая структура использует для определить, работает ли функция. Я считаю, что основная проблема заключается в том, что при настройке службы Linux, которая использует Docker, и подключении ее к VNet, используемые порты не являются стандартными (насколько я понимаю). Я обновил строку ENTRYPOINT в моем dockerfile, чтобы обработать это соответствующим образом, однако порт, который используется для проверки на 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-запросы отправляются на порт 3236. Я вижу, что это является частью параметра /Host.DestinationHostUrl ближе к концу команды run 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"

FYI Dockerfile по умолчанию, созданный цепочкой инструментов Azure Function, не работает , Он выдает ошибку с такой ошибкой:

(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.

Я предполагаю, что мне нужно сделать, это добавить этот другой порт к параметру --urls=..., который я передаю ENTRYPOINT, но не могу понять, как это сделать.

Кто-нибудь знает, как настроить Azure функция, которая использует Docker и VNet?

Ответы [ 2 ]

1 голос
/ 21 марта 2020

По умолчанию порт прослушивания API равен 80, верно? но VNet динамически изменяет порт при каждом перезапуске через переменную среды PORT. Даже если вы попытаетесь установить переменную среды PORT вручную на 80, VNet все равно переопределяет ее. Свою часть безопасности обеспечивает Vnet.

Решение состоит в том, что порт прослушивания API должен всегда указывать на то, что является каждой переменной окружения PORT.

В изображении docker используйте переменную среды PORT в качестве порта прослушивания основного веб-сервера, а не используйте номер порта в жестком коде

Как уже упоминалось в do c


Предложения

Одна опция - это уровень кода, заставьте ваше приложение слушать PORT переменная окружения, например это js пример или asp пример . Проблема здесь заключается в том, что вы всегда должны настраивать переменную среды PORT везде, где вы запускаете свое приложение (локально или в стадии подготовки или производства), если только вы не вносите дополнительные изменения, чтобы обнаружить, что ENV PORT спускается по кроличьей норе дальше.


Другой вариант - настроить порт прослушивания на ПОРТ ОКРУЖАЮЩЕЙ СРЕДЫ во время docker сборки. Команда ENTRYPOINT в Dockerfile выглядит следующим образом:

ENTRYPOINT "dotnet" "Tutorial.WebApi.dll" --urls="http://0.0.0.0:${PORT:-80}"
0 голосов
/ 08 апреля 2020

Я считаю, что мы позаботимся о переадресации правильных портов, когда вы используете вариант -appservice базового тега функций.

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

Таким образом, изменив эту строку в файле Docker из этого:

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

К этому

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

Может разрешить

...