Как поместить проект в Docker container, указать зависимости от других контейнеров, обращаться к сервису другого контейнера?
Есть мой ASP.NET 8 проект (сервер), мое .net 8 консольное приложение (клиент), образ minio (или какой-либо другой образ с docker hub). Нужно, чтобы клиент мог достучаться до сервера, который в докер контейнере, из докера и из хоста. Сервер должен общаться с minio, который тоже в докер контейнере.
Ответы (1 шт):
Вещи, которые я долго гуглил или выпрашивал у уже "смешариков".
Dockerfile - файл со "скриптом", описывает по шагам, как билдить контейнер (аналог .sh скрипта, .bat, cmakelists.txt). Создается в папке проекта. Создал его Rider'ом (руками не писал), нормально работает. Мне понадобилось трогать там только EXPOSE - указывает порт, который будет открытым (оставил только EXPOSE 7666).
Пример (ASP.NET 8 проект):
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER $APP_UID
WORKDIR /app
EXPOSE 7666
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["MyServer/MyServer.csproj", "MyServer/"]
RUN dotnet restore "MyServer/MyServer.csproj"
COPY . .
WORKDIR "/src/MyServer"
RUN dotnet build "MyServer.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "MyServer.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyServer.dll"]
docker-compose.yaml - он нужен для конфигурации запуска контейнера(-ов). Создается в папке решения. Он сам запустит Dockerfile, если нужные контейнеры еще не собраны.
В Rider можно выполнить весь docker-compose.yaml (кнопка пуска около services), либо только какой-то конкретный сервис (запустить контейнер) (кнопка пуска около контейнера).
docker-compose.yaml можно выполнить из консоли, выполнив docker compose up в консоли в директории с этим файлом.
Как я понял, запускать контейнер в первый раз из интерфейса Docker Desktop (функционал ограничен) или запускать его из консоли без docker-compose.yaml (много букав писать) - кринж; ну и всё равно нужна автоматизация запуска и конфигурации.
В коде оставил комментарии, всё должно стать понятно.
#docker-compose.yaml
services: #далее перечисление контейнеров
minio: #как назовем контейнер
image: minio/minio:latest #docker image from docker hub
#(вроде должно само скачаться, если не скачано)
#вместо latest в проде следует использовать
#конкретную версию, на которой было протестировано,
#а то он упадет когда-нибудь.
command: server --console-address ":9001" /data/
ports: #проброс портов.
- "9050:9070" #с хоста можно отправить запрос в http(s)://localhost:9050,
#он придет в 9070 порт внутри контейнера (если EXPOSEd)
- "9000:9000"
- "9001:9001"
environment: #переменные среды)
MINIO_ROOT_USER: aaa111
MINIO_ROOT_PASSWORD: bbb222333
volumes: #внизу файла обьявление томов, тут использование
- minio-storage:/data #монтирует minio-storage как директорию /data
myserver: #название контейнера, в котором будет мой сервер
image: myserver #название образа (не с докер хаба, а локальное.
#появится в докере либо после запуска этого файла,
#либо докерфайла отдельно)
ports:
- "7777:7666"
build:
context: . #не знаю, что это. работает, не трогаю.
dockerfile: MyServer/Dockerfile #путь к докер файлу проекта
#относительно этого docker-compose.yaml,
#Он будет выполнен при выполнении этого файла,
#если сурскод потерял актуальность (не точно)
#или image еще не создан
depends_on: [minio] #перед запуском этого контейнера (myserver) сначала
#скачается/настроится/запустится контейнер minio
volumes:
- myserver-storage:/data
environment:
#
ASPNETCORE_URLS: "http://+:7666" #в ASP.NET 8 это позволяет задать порт 7666
#как прослушиваемый, вместо дефолтного 8080.
#если вместо http написать https, будет https (не факт, лучше загуглить)
#как я понял, launchSettings.json не актуален для докера
client: #мой "клиент"
image: client
build:
context: .
dockerfile: Client/Dockerfile
depends_on: [ myserver ] #перед запуском client должен быть запущен myserver
environment:
WEBAPI_URL: http://myserver:7666 #контейнер может стучаться в другой контейнер,
#используя название контейнера
volumes:
- trash-storage:/data
volumes: #тома в докере. существуют независимо от контейнеров.
minio-storage: #после двоеточия ничего можно не писать.
#будет создан том {название решения (.net)}_minio-storage
myserver-storage:
Если в MyServer/Dockerfile не написать EXPOSE 7666, то из другого контейнера нельзя будет достучаться в этот по порту 7666, хост тоже не достучится по порту 7777. если написать EXPOSE 7666, но не написать ports: - "7777:7666", то из других контейнеров все равно можно достучаться в этого контейнер по 7666 порту .
Еще по этой теме: