В процессе разработки приложений мы часто сталкиваемся с необходимостью опубликовать приложение — чтобы им могли пользоваться другие люди, чтобы оно было постоянно запущенным и не зависело, например, от состояния ПК разработчика.
В этой статье мы рассмотрим способ публикации веб-приложения на виртуальный выделенный сервер с помощью контейнеров Docker.
cloud
Контейнеризация — это метод, применяемый в разработке программ, при котором сервисы вместе со своими зависимостями «упаковываются» в специальные контейнеры. Далее эти контейнеры можно развернуть на сервере или, например, локально — и быть точно уверенным в том, что мы тестируем и разворачиваем одну и ту же версию приложения.
Контейнеры также изолируют приложения друг от друга в общей операционной системе, при этом, в сравнении с виртуальными машинами, они гораздо менее требовательны к ресурсам.
Docker — это проект с открытым исходным кодом, который позволяет автоматизировать деплой ПО в виде специальных контейнеров. Эти контейнеры могут выполняться в разных средах — как на Linux, так на Windows или Mac. В целом, контейнеры Docker можно сравнить с виртуальными машинами, однако контейнеры используют ядро операционной системы хоста (сервера, где мы разворачиваем приложение) совместно. Виртуальные машины используют собственное ядро ОС, поэтому они требуют больше ресурсов.
Основная цель создания образов — привести среду вместе с зависимостями вашего приложения к единообразию. Это означает, что вы можете отладить образ на одном компьютере, а затем развернуть его на другом компьютере и получить ту же среду.
Основные термины Docker:
У Docker есть отличная документация, и для большего погружения рекомендуем с ней ознакомиться.
Мы будем разворачивать шаблонное web API на ASP.NET Core. Для этого добавим новую папку и в терминале выполним команду:
dotnet new webapi
Теперь у нас есть шаблонное приложение. Его можно запустить, выполнив команду:
dotnet run
Перейдя на http://localhost:5167/swagger/index.html
(порт может отличаться), мы увидим сгенерированную документацию Swagger к нашему API и сможем попробовать выполнить запрос:
Итак, приложение работает, теперь его надо добавить в Docker и развернуть на сервере. Для начала добавим файл Dockerfile, чтобы описать, из чего будет состоять наш контейнер:
# укажем, на основе какого образа будем
# делать наш контейнер. Для сборки приложения используем dotnet-sdk
# и назовём этот образ builder
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS builder
# укажем директорию для нашего приложения внутри контейнера
WORKDIR /Application
# Скопируем все файлы из проекта в файловую систему контейнера
COPY . ./
# Запустим restore для загрузки зависимостей
RUN dotnet restore
# Опубликуем собранный dll в папку "output"
RUN dotnet publish -c Release -o output
# Теперь соберём образ, в котором наше приложение
# будет запущено. Для запуска приложения достаточно
# среды выполнения aspnet, без sdk
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /Application
# Скопируем файлы приложения из предыдущего образа
COPY --from=builder /Application/output .
# укажем команду, которая будет запускать приложение
ENTRYPOINT ["dotnet", "dotnet-app.dll"]
Запустим команду docker build -t dotnet-app .
, чтобы собрать наше приложение:
С помощью параметра -t dotnet-app
мы даём название образу, а с помощью параметра .
(точка в конце — текущая директория) указываем контекст, в котором docker будет искать Dockerfile и собирать его.
Используя команду docker images
, мы можем посмотреть список существующих образов и информацию о них:
Теперь мы можем запустить контейнер с помощью команды:
docker run -p 5000:80 dotnet-app
С помощью параметра -p 5000:80
мы говорим докеру, чтобы порт 80 из контейнера был открыт на 5000 порту нашей ОС.
По адресу http://localhost:5000/WeatherForecast
мы можем использовать наше приложение.
В стандартном шаблоне приложения ASP.NET Swagger доступен, только если установлена переменная среды Development. Эта логика описана в файле program.cs
:
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
По умолчанию контейнер разворачивается в среде Production. Мы можем убрать условие if (app.Environment.IsDevelopment())
или добавить переменную окружения в Dockerfile:
ENV ASPNETCORE_ENVIRONMENT=Development
...
Теперь надо пересобрать приложение:
docker build -t dotnet-app .
И снова его запустить:
docker run -p 5000:80 dotnet-app
Теперь нам доступен Swagger:
Итак, у нас есть образ контейнера, и мы хотим его использовать для развёртывания на сервере. Для этого нам необходимо этот образ как-то отправить на сервер. Для этих целей подойдёт docker registry. Можно развернуть свой, а можно использовать https://hub.docker.com.
Если Docker Hub недоступен, можно использовать наш бесплатный прокси, который возобновляет этот доступ.
После прохождения авторизации необходимо нажать на кнопку «Create Repository», дать название нашему репозиторию и сохранить его:
Теперь вернёмся в терминал и выполним команду:
docker login
Чтобы отправить образ контейнера в репозиторий, сначала соберём образ, указав в названии ваш логин:
docker build -t [ваш логин]/dotnet-app .
А затем выполним команду:
docker push [ваш логин]/dotnet-app:latest
Для начала арендуем выделенный сервер. Я использую Timeweb Cloud.
Для приложения вполне хватит минимальной конфигурации. Готовый сервер с Docker можно выбрать из маркетплейса, а если будете ставить Docker сами — есть инструкция.
С помощью SSH можно авторизоваться на вашем сервере. В консоли выполним команду docker login
, чтобы авторизоваться в registry, а затем выполним команду:
docker pull [ваш логин]/dotnet-app
И запустим наше приложение:
docker run -p 5000:80 [ваш логин]/dotnet-app -d
Параметр -d
используется для запуска контейнера в фоновом режиме.
Теперь мы можем использовать наше API по IP-адресу сервера, где мы его развернули:
Подготовили для вас выгодные тарифы на облачные серверы
Мы научились упаковывать приложение ASP.NET Core в Docker, публиковать его в docker registry и запускать на VPS. Для более полного погружения советую вам почитать документацию Microsoft: Образы Docker для ASP.NET Core | Microsoft Learn
До скорых встреч!