#.net #docker #asp.net-web-api #asp.net-core
#.net #docker #asp.net-web-api #asp.net-core
Вопрос:
Я новичок в Docker и действительно хочу испытать его возможности. Здесь я хотел бы запустить простой Asp.net базовый веб-api в Docker (с использованием docker run
) вместо того, чтобы запускать его с помощью IIS.
Это просто, потому что это именно автогенерация по умолчанию ASP.NET основной проект веб-API с именем только одного контроллера ValuesController
. Обычно при отладке с помощью IISExpress следующий URI должен выдавать массив значений:
http://localhost:[some_port]/api/values
Теперь я добавляю поддержку Docker для проекта (используя контейнер Windows). После создания образа Docker его можно перечислить с помощью docker images
. Теперь я запускаю образ Docker для размещения моего веб-api следующим образом:
docker run -t -rm -p 80:50633 hellodocker:dev
Он работает нормально, и я могу проверить это с помощью docker ps
. Однако, чтобы проверить, действительно ли это работает, я попытался ввести следующий адрес в браузере:
http://localhost/api/values
и это не работает, ничего не отображается, и это выглядело так же, как несуществующий сайт.
Когда я пытаюсь выполнить следующую команду docker exec [container_id] netstat
, она иногда показывает запись со статусом TIME_WAIT
, и почти все время ее нет. Хотя я не уверен, связано ли это с внешним прослушиванием.
Вот содержимое файла Dockerfile:
FROM microsoft/dotnet:2.2-aspnetcore-runtime-nanoserver-1803 AS base
WORKDIR /app
EXPOSE 50633
EXPOSE 44322
FROM microsoft/dotnet:2.2-sdk-nanoserver-1803 AS build
WORKDIR /src
COPY HelloDocker/HelloDocker.csproj HelloDocker/
RUN dotnet restore HelloDocker/HelloDocker.csproj
COPY . .
WORKDIR /src/HelloDocker
RUN dotnet build HelloDocker.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish HelloDocker.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "HelloDocker.dll"]
Я действительно застрял на этом. Приложение hello-world может просто распечатать простую строку, но это hellodocker
должно размещаться в docker и обслуживать любые HTTP-запросы точно так же, как когда мы размещаем его в IIS.
Обновить
После попытки удалить созданный образ и вместо него перестроить другой, он выглядит иначе после запуска с той же docker run
командой выше:
Hosting environment: Production
Content root path: C:app
Now listening on: http://[::]:80
Application started. Press Ctrl C to shut down.
Как и раньше, ничего не отображается, и корневой путь запроса становится C:app
.
Итак, на этот раз кажется более очевидным, что он прослушивает запросы. Однако он все еще не работает.
Комментарии:
1. Какой порт по умолчанию для сервера hello-world? Вы уверены, что это так
50633
?2. @Jack Gore Я не совсем уверен, это то, что я предположил, основываясь на
dockerfile
, вы можете увидеть строку EXPOSE 50633
Ответ №1:
Перед вашей инструкцией ENTRYPOINT попробуйте добавить
ENV ASPNETCORE_URLS=http:// :50633 DOTNET_RUNNING_IN_CONTAINER=true
итак, это выглядит так:
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENV ASPNETCORE_URLS=http:// :50633 DOTNET_RUNNING_IN_CONTAINER=true
ENTRYPOINT ["dotnet", "HelloDocker.dll"]
Помогает ли это?
Комментарии:
1. На самом деле я думаю, что нам не нужна эта строка (потому что она уже предоставляет веб-api через порт 80 по умолчанию, и мы можем просто сопоставить его с портом 80 хоста вместо сопоставления с 50633 на 80). Цель здесь — обслуживать запрос извне, независимо от используемого внутри порта. Однако ваш ответ заставляет прослушивать (внутренне) порт 50633, который не принудительно выполняется
EXPOSE
. С добавлением этой строки моя исходная команда работает. В любом случае, спасибо вам за это.
Ответ №2:
Я не уверен, почему я не мог найти решение на форумах Docker, но после попытки поиска Now listening on: http://[::]:80
и это привело меня к самой верхней ссылке на очень похожую проблему на форумах Docker здесь.
Итак, я попробовал одно решение, используя docker inspect [container_id]
first для поиска IP-адреса контейнера, и использовал этот IP для успешного доступа к веб-API 🙂
IP контейнера можно найти в Networks
разделе:
"Networks": {
"nat": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "e336becc4500435f7338ebd8f84fef47ec2fc247f77bc82b6dbf49553f68afd5",
"EndpointID": "a8ede68e3f4bb02392c295901f65d50f0ee014c114f564768d9c82a4644b0218",
"Gateway": "172.30.240.1",
"IPAddress": "172.30.242.85",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "00:15:5d:5a:29:8d",
"DriverOpts": null
}
}
Правильный адрес, который я использовал для тестирования веб-api сейчас, это:
http://172.30.242.85/api/values
Обновить:
Я предположил, что это EXPOSE 50633
означает, что docker предоставит веб-api через порт, 50633
поэтому я запускаю команду docker run -t -p 80:50633 hellodocker:dev
.
Но на самом деле порт, который он предоставляет здесь, по-прежнему используется по умолчанию 80
(не уверен, почему). Но, по крайней мере, это имеет смысл. Поэтому для сопоставления портов между docker и хост-машиной мы используем вместо этого команду docker run -t -p:80:80 hellodocker:dev
. Я пробовал это, и это отлично работает для http://localhost/api/values
.
Я думаю, что команда, использованная ранее, docker run -t -p:80:50633 hellodocker:dev
имеет бесполезное сопоставление портов (по крайней мере, для тестирования web api с хост-компьютера), потому что http://172.30.242.85/api/values
должно сработать, если docker действительно запускает web api для прослушивания порта по умолчанию 80
.