Получите грант до 500 000 рублей на IT-инфраструктуру для бизнеса. Узнайте больше у персонального менеджера Связаться

Деплой приложения на ASP.NET Core на VPS с использованием Docker

Дмитрий Бахтенков
Технический писатель
09 июня 2023 г.
457
Время прочтения: 6 минут

В процессе разработки приложений мы часто сталкиваемся с необходимостью опубликовать приложение — чтобы им могли пользоваться другие люди, чтобы оно было постоянно запущенным и не зависело, например, от состояния ПК разработчика.

В этой статье мы рассмотрим способ публикации веб-приложения на виртуальный выделенный сервер с помощью контейнеров Docker.

Контейнеризация и Docker

Что такое контейнеризация?

Контейнеризация — это метод, применяемый в разработке программ, при котором сервисы вместе со своими зависимостями «упаковываются» в специальные контейнеры. Далее эти контейнеры можно развернуть на сервере или, например, локально — и быть точно уверенным в том, что мы тестируем и разворачиваем одну и ту же версию приложения.

Контейнеры также изолируют приложения друг от друга в общей операционной системе, при этом, в сравнении с виртуальными машинами, они гораздо менее требовательны к ресурсам.

Image2

Docker

Docker — это проект с открытым исходным кодом, который позволяет автоматизировать деплой ПО в виде специальных контейнеров. Эти контейнеры могут выполняться в разных средах — как на Linux, так на Windows или Mac. В целом, контейнеры Docker можно сравнить с виртуальными машинами, однако контейнеры используют ядро операционной системы хоста (сервера, где мы разворачиваем приложение) совместно. Виртуальные машины используют собственное ядро ОС, поэтому они требуют больше ресурсов.

Image15

Основная цель создания образов — привести среду вместе с зависимостями вашего приложения к единообразию. Это означает, что вы можете отладить образ на одном компьютере, а затем развернуть его на другом компьютере и получить ту же среду.

Основные термины Docker:

  • Образы (Image) — некоторый пакет, который содержит все зависимости и сведения, необходимые для создания контейнера.
  • Докерфайл (Dockerfile) — специальный текстовый файл, который содержит некоторые инструкции для сборки образа Docker.
  • Контейнер (Container) — экземпляр конкретного образа Docker, созданного на основе Dockerfile. Контейнер отвечает за выполнение приложения и является основной единицей развёртывания — именно контейнеры мы запускаем на сервере или локально.
  • Docker Registry — некоторое хранилище образов docker. Очень похоже на github, только вместо кода тут образы контейнеров.

У Docker есть отличная документация, и для большего погружения рекомендуем с ней ознакомиться.

Пишем приложение

Мы будем разворачивать шаблонное web API на ASP.NET Core. Для этого добавим новую папку и в терминале выполним команду:

dotnet new webapi

Image8

Теперь у нас есть шаблонное приложение. Его можно запустить, выполнив команду:

dotnet run

Image1

Перейдя на http://localhost:5167/swagger/index.html (порт может отличаться), мы увидим сгенерированную документацию Swagger к нашему API и сможем попробовать выполнить запрос:

Image9

Упаковываем приложение в Docker

Итак, приложение работает, теперь его надо добавить в 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 ., чтобы собрать наше приложение:

Image5

С помощью параметра -t dotnet-app мы даём название образу, а с помощью параметра . (точка в конце — текущая директория) указываем контекст, в котором docker будет искать Dockerfile и собирать его.

Используя команду docker images, мы можем посмотреть список существующих образов и информацию о них:

Image3

Теперь мы можем запустить контейнер с помощью команды:

docker run -p 5000:80 dotnet-app

С помощью параметра -p 5000:80 мы говорим докеру, чтобы порт 80 из контейнера был открыт на 5000 порту нашей ОС. 

Image4

По адресу 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:

Image13

Публикация в docker registry

Итак, у нас есть образ контейнера, и мы хотим его использовать для развёртывания на сервере. Для этого нам необходимо этот образ как-то отправить на сервер. Для этих целей подойдёт docker registry. Можно развернуть свой, а можно использовать https://hub.docker.com.

После прохождения авторизации необходимо нажать на кнопку «Create Repository», дать название нашему репозиторию и сохранить его:

Image11

Теперь вернёмся в терминал и выполним команду:

docker login

Image12

Чтобы отправить образ контейнера в репозиторий, сначала соберём образ, указав в названии ваш логин:

docker build -t [ваш логин]/dotnet-app .

А затем выполним команду:

docker push [ваш логин]/dotnet-app:latest

Image7

Разворачиваем приложение на сервере

Для начала арендуем выделенный сервер. Я использую Timeweb Cloud.

Для приложения вполне хватит минимальной конфигурации. Готовый сервер с Docker можно выбрать из маркетплейса, а если будете ставить Docker сами — есть инструкция.

Image6

С помощью SSH можно авторизоваться на вашем сервере. В консоли выполним команду docker login, чтобы авторизоваться в registry, а затем выполним команду:

docker pull [ваш логин]/dotnet-app

Image16

И запустим наше приложение:

docker run -p 5000:80 [ваш логин]/dotnet-app -d

Image10

Параметр -d используется для запуска контейнера в фоновом режиме.

Теперь мы можем использовать наше API по IP-адресу сервера, где мы его развернули:

Image14

Заключение

Мы научились упаковывать приложение ASP.NET Core в Docker, публиковать его в docker registry и запускать на VPS. Для более полного погружения советую вам почитать документацию Microsoft: Образы Docker для ASP.NET Core | Microsoft Learn

До скорых встреч!

Зарегистрируйтесь и начните пользоваться
сервисами Timeweb Cloud прямо сейчас

15 лет опыта
Сосредоточьтесь на своей работе: об остальном позаботимся мы
165 000 клиентов
Нам доверяют частные лица и компании, от небольших фирм до корпораций
Поддержка 24/7
100+ специалистов поддержки, готовых помочь в чате, тикете и по телефону