Docker и C#: полное руководство по контейнеризации .NET-приложений
Контейнеризация стала стандартом де-факто для развертывания современных приложений. Если вы разрабатываете на C# (.NET), Docker позволяет упаковать ваше приложение вместе со всеми зависимостями в легковесный, изолированный контейнер. В этой статье мы пройдем путь от создания простого Dockerfile до публикации и запуска готового образа. Вы узнаете, как контейнеризировать приложение на C#, оптимизировать размер образа и использовать лучшие практики.
1. Основы Docker для .NET-разработчика
Docker — это платформа для разработки, доставки и запуска приложений в контейнерах. Контейнер — это стандартизированная единица ПО, которая включает код и все его зависимости. В отличие от виртуальных машин, контейнеры используют общее ядро операционной системы, что делает их быстрее и легче.
Для C# (.NET) Docker особенно полезен, так как он решает проблему "у меня работает" — вы гарантируете, что приложение будет вести себя одинаково на машине разработчика, тестовом сервере и в продакшене. Основные компоненты:
- Docker Engine — среда выполнения контейнеров
- Dockerfile — текстовый файл с инструкциями по сборке образа
- Образ (Image) — неизменяемый шаблон для создания контейнеров
- Контейнер (Container) — запущенный экземпляр образа
Установите Docker Desktop для Windows/Mac или Docker Engine для Linux. После установки проверьте работу командой:
docker --version
2. Создание Dockerfile для C# (.NET) приложения
Начнем с простого ASP.NET Core Web API приложения. Создайте новый проект:
dotnet new webapi -n MyDockerApp
cd MyDockerApp
Теперь создайте файл Dockerfile (без расширения) в корне проекта. Вот базовая версия с многоэтапной сборкой (multi-stage build):
# Этап 1: сборка приложения
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
# Копируем csproj и восстанавливаем зависимости
COPY ["MyDockerApp.csproj", "."]
RUN dotnet restore
# Копируем остальной код и собираем проект
COPY . .
RUN dotnet publish -c Release -o /app/publish
# Этап 2: создание минимального образа для запуска
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
EXPOSE 80
EXPOSE 443
# Копируем собранное приложение из первого этапа
COPY --from=build /app/publish .
# Точка входа
ENTRYPOINT ["dotnet", "MyDockerApp.dll"]
Объяснение ключевых инструкций:
FROM— задает базовый образ (SDK для сборки, ASP.NET для запуска)WORKDIR— устанавливает рабочую директориюCOPY— копирует файлы из контекста сборки в образRUN dotnet restore— восстанавливает NuGet-пакетыRUN dotnet publish— компилирует и публикует приложениеEXPOSE— указывает порты, которые будет слушать контейнерENTRYPOINT— команда, выполняемая при запуске контейнера
Многоэтапная сборка критически важна для C#: финальный образ содержит только runtime и ваше приложение, без SDK и исходников. Это уменьшает размер образа с ~1.5 ГБ до ~200 МБ.
3. Сборка и запуск контейнера
Соберите образ Docker:
docker build -t my-dotnet-app:latest .
Флаг -t задает тег (имя:версия). Точка в конце означает текущую директорию как контекст сборки.
Запустите контейнер:
docker run -d -p 8080:80 --name my-app my-dotnet-app:latest
Параметры:
-d— запуск в фоновом режиме (detached)-p 8080:80— проброс порта: порт хоста 8080 → порт контейнера 80--name— задает имя контейнера
Проверьте, что приложение работает:
curl http://localhost:8080/weatherforecast
Для просмотра логов используйте:
docker logs my-app
Остановите и удалите контейнер:
docker stop my-app
docker rm my-app
4. Оптимизация и лучшие практики
Чтобы сделать контейнеризацию C# приложений профессиональной, следуйте этим рекомендациям:
4.1. Минимизация размера образа
- Используйте
dotnet publish --self-contained false(по умолчанию) — это использует общий runtime, а не встраивает его в приложение. - Для Linux-контейнеров выбирайте образ на основе Alpine:
mcr.microsoft.com/dotnet/aspnet:8.0-alpine. Размер снижается до ~100 МБ. - Удалите временные файлы в Dockerfile, если используете одноэтапную сборку (не рекомендуется).
4.2. Использование .dockerignore
Создайте файл .dockerignore в корне проекта, чтобы исключить ненужные файлы из контекста сборки:
bin/
obj/
.vs/
*.user
.git/
.gitignore
Dockerfile
.dockerignore
4.3. Безопасность
- Не запускайте контейнеры от root. Добавьте пользователя в Dockerfile:
RUN adduser -u 1000 --disabled-password appuser
USER appuser
- Не храните секреты (строки подключения, пароли) в образе. Используйте переменные окружения или Docker Secrets.
4.4. Docker Compose для многоконтейнерных приложений
Если ва