Сегодня я хочу поделиться своим опытом развёртывания образовательной платформы — проекта, который я делаю с нуля.
У меня уже есть готовый минимум работающего продукта (MVP): сервер, написанный на популярном языке программирования C# с использованием технологии ASP.NET Core, и клиентская часть — современное веб-приложение на React с использованием TypeScript.
В этой статье я расскажу не столько о том, как я писал код, а больше о том, как развернул всю эту систему на реальном сервере — о технических деталях, с которыми столкнулся, решениях и сложностях, а главное — о том, как сделать так, чтобы твой проект работал стабильно и был доступен пользователям.
Постараюсь объяснять всё простым и понятным языком, чтобы материал был полезен не только разработчикам, но и тем, кто только интересуется, как устроены современные веб-сервисы.
Почему просто написать код — недостаточно
Когда ты создаёшь собственный проект, особенно онлайн-платформу, легко зациклиться на функционале, дизайне, фичах. Кажется, что как только всё написано — можно выдохнуть. Но на самом деле всё только начинается.
Пока твой код живёт у тебя на компьютере — им никто не может воспользоваться. А как только ты решаешь "показать миру", возникает масса новых задач: где это всё будет работать? как сделать так, чтобы оно не падало? как защититься от сбоев и взломов? как обновлять проект без боли?
Именно поэтому я сразу подошёл к развёртыванию с инженерной стороны — продумал, как организовать инфраструктуру, выбрал VPS, настроил контейнеры, домен, базу и веб-сервер. Всё это позволяет мне быть уверенным: платформа работает, её легко обновлять, и она готова к росту.
Мой выбор инфраструктуры и почему
На самом старте я задался вопросом: «как это всё показать миру?» Это было ещё несколько лет назад, когда только зарождалась идея платформы. Я понимал, что просто написать код — недостаточно. Нужно было место, где он будет жить и работать.
Первым логичным шагом стало приобретение облачного VPS-сервера — виртуальной машины, на которой я получаю полный контроль над системой. Это позволяет устанавливать любые инструменты, конфигурировать окружение под себя, экспериментировать без ограничений и быть уверенным в предсказуемости работы проекта.
Встал вопрос: где покупать VPS? Тут сыграл роль прошлый опыт — для дипломной работы я уже использовал VPS, купленный на Reg.ru, и тогда он отлично себя показал. У них удобная панель, быстрое развёртывание, понятные тарифы и, что немаловажно, отзывчивая поддержка. Поэтому выбор был очевиден — я снова воспользовался их сервисом, и это сэкономило мне время и нервы.
Следующий важный выбор — в чём и как разворачивать саму платформу. Я сразу решил использовать Docker. Это инструмент, который позволяет упаковать каждую часть системы в отдельный изолированный контейнер, со своими зависимостями и настройками. Это удобно, надёжно и очень гибко.
Моя инфраструктура состоит из следующих контейнеров:
- nginx — в роли обратного прокси. Он принимает все внешние запросы и перенаправляет их во внутренние сервисы: фронтенд, бэкенд и статические страницы.
- backend — серверная часть, написанная на ASP.NET Core. Именно здесь работает WebSocket-сервер и бизнес-логика платформы.
- frontend — клиентское приложение на React + TypeScript. Собранный SPA, который nginx отдает пользователям.
- static — простой контейнер со статичными HTML-страницами: главная, информация о курсах, система поощрений, блок об авторстве.
- postgres — база данных, где хранятся все ключевые данные: пользователи, курсы, прогресс, метаданные.
Контейнеры связаны между собой внутренней сетью Docker — своего рода “мостом”, который позволяет им безопасно и быстро общаться. Такой подход даёт максимум контроля: можно развивать каждый компонент отдельно, перезапускать его без влияния на остальные, обновлять по частям.
Как происходил процесс развертывания
Когда код платформы был готов, настало время превратить его в живой сервис — доступный из браузера, надёжный и управляемый. Ниже — путь, по которому я шёл, с примечаниями и парой граблей, на которые наступил.
1. Подготовка VPS: установка Docker и Docker Compose
Сначала я настроил сам VPS. Установил:
- Docker — основа всей контейнерной инфраструктуры;
- nano — текстовый редактор, с помощью которого легко управлять конфигурационными файлами, к примеру обновить пароль на БД, обновить настройки nginx;
- certbot — бесплатная программа с открытым исходным кодом, разработанная для автоматизации получения и установки SSL/TLS-сертификатов Let's Encrypt на веб-сайты
Это заняло немного времени, особенно учитывая, что Reg.ru предоставляет «чистую» машину, и всё нужно делать вручную. Но в этом есть плюс — полное понимание, что и где установлено.
2. Сборка и настройка контейнеров
Каждую часть платформы я завернул в отдельный контейнер:
- Backend (ASP.NET Core)
- Frontend (React)
- Статические страницы (HTML + CSS)
- Postgres — база данных
- nginx — проксирует и отдаёт всё наружу
В docker-compose.yaml я описал, как они собираются, в какой последовательности запускаются и как связаны между собой.
3. Связывание контейнеров через мост (nginx как обратный прокси)
Все контейнеры объединены внутренней сетью Docker. Nginx играет роль «диспетчера» — принимает внешние запросы и направляет их:
- на фронт — если пользователь открывает платформу;
- на backend — если идёт API-запрос или WebSocket;
- на статику — если нужен HTML;
- ничего наружу не пускает, кроме того, что нужно.
Это позволяет скрыть внутренние порты и повысить безопасность.
4. Размещение статических страниц
Отдельный контейнер обслуживает простой HTML: главную, страницы о курсах, системе поощрений и авторстве. Они почти не меняются, зато быстро загружаются и хорошо индексируются поисковиками. Простое решение, которое работает.
5. Публикация frontend (React)
Фронтенд — собранный SPA на React. Я подключил его как отдельный сервис и nginx отдаёт его пользователям, когда они заходят на формы регистрации/логина и далее после этого при дальнейшей работе всей платформы, за исключением конечно статических страниц которые работают в отдельном контейнере.
6. Запуск backend (ASP.NET Core WebSocket сервер)
Backend написан на ASP.NET Core и обрабатывает:
- REST-запросы — сюда входит один get-запрос по которому пользователи получают файлы из локальной файловой системы сервера, такие как изображения курсов, профиля и прочее;
- аутентификацию — основанную на токенах сессии, при первом входе в аккаунт у пользователя создается токен который хранится локально у пользователя и на сервере, чтобы в дальнейшем проверять пропускать ли пользователя в систему без ввода логина и пароля. Таким образом пользователь всегда остается в системе;
- WebSocket-соединения — основная функциональная часть это WebSocket API, клиентское приложение один раз подключается и отправляет запросы, такие как: получение списка курсов, логин, выход из аккаунта, создание курса и прочие.
Также настроен докер-том — это специальная папка, связанная с локальной файловой системой сервера (VPS), в которой хранятся файлы пользователей: изображения профиля, изображения курсов и прочее. Благодаря тому, что том "привязан" к контейнеру, приложение может стабильно получать доступ к этим файлам даже при перезапуске или обновлении сервера. Это важно для надежного хранения изображений и других пользовательских данных.
Домены и HTTPS
Когда платформа уже работала на сервере, пришло время сделать её доступной по читаемому и узнаваемому адресу — без IP и портов. Такой адрес помогает не только в восприятии, но и в индексации сайта поисковиками, а также повышает доверие у пользователей.
Я выбрал короткий, говорящий домен — codeengine.org, и зарегистрировал его у знакомого мне регистратора — regru, с которым уже имел опыт работы. После регистрации я получил доступ к DNS-записям, с помощью которых и «привязал» домен к IP-адресу своего сервера.
Позже я также приобрёл codeengine.ru, чтобы обеспечить присутствие в национальной доменной зоне. Для удобства пользователей настроил переадресацию с .ru на .org — чтобы все заходили на основной домен, независимо от того, какой они набирают.
Настройка nginx
Nginx я использую как обратный прокси — он принимает все внешние запросы и перенаправляет их внутрь Docker-сети:
- на frontend (/login, /courses, /profile, и другие),
- на backend (/websocket),
- на статику (/, /course.html, /awards.html, /authorship.html, /terms.html, /privacy.html),
- и на поддомен API (api.codeengine.ru).
Конфигурация nginx включает также автоматическую переадресацию с http:// на https:// чтобы пользователь всегда оказывался на защищённой версии сайта.
SSL и HTTPS
После того как домен был настроен, сайт стал доступен по http://, но это не является безопасным соединением. Такие страницы:
- хуже индексируются;
- не поддерживают многие современные технологии (например, WebSocket);
- и вызывают недоверие у пользователей (браузер показывает предупреждение).
Чтобы решить эту проблему, я подключил SSL-сертификат. Сначала я купил платный сертификат через регистратора — чисто по инерции. Но позднее, когда понадобилось настраивать поддомен для серверного API (api.codeengine.ru), я уже использовал Let's Encrypt — это полностью бесплатное и надёжное решение с автоматическим обновлением сертификатов.
На этом поддомене крутится WebSocket-сервер, и SSL был критически важен для его корректной работы, особенно в браузерах, которые блокируют небезопасные соединения.
Основные сложности и уроки
Развёртывание даже небольшого продукта — это не просто "выложил на сервер и заработало". Почти на каждом этапе всплывали свои трудности, особенно если делаешь всё сам: и разработку, и настройку, и инфраструктуру.
Что вызвало сложности и как решил:
- Сетевые настройки и маршрутизация в Docker: правильно связать контейнеры между собой, особенно с nginx в роли прокси, заняло время. Сначала не было доступа к API, frontend не мог обратиться к backend. Помог мой опыт работы с docker и документации по nginx.
- CORS и безопасность: некоторые запросы блокировались браузером. Пришлось разобраться с заголовками, методами и разрешениями между поддоменами.
- Настройка HTTPS и сертификатов: банально — первый раз делал это вручную, купил сертификат за деньги, хотя Let's Encrypt уже тогда был логичным выбором. На поддомене уже пошёл по правильному пути.
- Права доступа в Docker и Volume'ы: иногда backend просто не мог читать нужные файлы или соединяться с базой. Эти ошибки не всегда очевидны, и на их отладку уходило много времени.
Что бы сделал по-другому
Важно понимать — это MVP, минимально жизнеспособный продукт, чтобы проверить концепцию и начать привлекать пользователей. Но с технической точки зрения:
- Я бы сразу внедрил CI/CD — автоматическую сборку и деплой. Сейчас всё заливается руками, что неудобно и чревато ошибками.
- Подумал бы о контейнерном оркестраторе вроде Kubernetes, особенно если проект будет масштабироваться. Сейчас всё управляется вручную через docker-compose.
- Использовал бы более надёжное решение, чем просто VPS — например, облачные платформы типа AWS, Яндекс.Cloud, Hetzner, где проще масштабировать проект, подключать резервные копии, мониторинг и отказоустойчивость.
- Архитектура сейчас монолитная, и это нормально для MVP, но при росте проекта стоит перейти на микросервисный подход и даже микрофронтенд, чтобы команды могли независимо развивать разные части платформы.
- Отказался бы от "ручной" статики в Docker и перешёл бы на CDN или отдельный хостинг для статики — это упростит обновление, улучшит скорость и масштабируемость.
Ещё один момент, который я бы пересмотрел — это локальное хранение файлов пользователей. Сейчас файлы (например, аватары, изображения курсов) хранятся прямо на VPS в папке, привязанной к Docker-контейнеру. Для MVP это приемлемо, но у такого подхода есть серьёзные минусы:
- Сложность масштабирования — если нужно будет развернуть второй сервер, файлы не будут автоматически доступны на нём.
- Риск потери данных — если VPS сломается и нет резервных копий, файлы пропадут.
- Ограниченные возможности хранения — место на VPS может быстро закончиться.
Более правильный подход — использовать облачное хранилище, например, Amazon S3, Яндекс Object Storage или аналог. Это:
- Надёжнее (данные реплицируются),
- Гибко масштабируется,
- Даёт быстрый доступ к файлам из любого сервера или региона,
- Упрощает резервное копирование и защиту данных.
Советы тем, кто начинает
- Не стремитесь к идеалу с первой попытки. Главное — рабочий результат. MVP должен заработать и показать ценность.
- Делайте поэтапно. Нет смысла с первых дней внедрять микросервисы и балансировщики нагрузки — сначала нужна рабочая база.
- Разбирайтесь в инструментах, которые используете. Даже nginx и Docker могут подкинуть сюрпризов, если не понимать, как они работают.
- Не бойтесь менять подход по мере роста. То, что сработало на старте, может стать узким горлышком при масштабировании.
- Не забывайте о безопасности. Даже на MVP этапе стоит настроить хотя бы базовую защиту: HTTPS, fail2ban, firewall и ограниченные права доступа.
- Разделяйте окружения. Даже если вы один разработчик — заведите себе минимум два стенда:
1. beta — для тестов, отладки, экспериментов
2. prod — для финального, стабильного, боевого варианта. Это избавит от случайных сбоев на живом проекте, позволит безопасно выкатывать обновления и упрощает отладку.
Заключение
Текущая версия платформы — это результат множества проб, ошибок и импровизаций. Это живой проект, созданный ради проверки идеи и поиска рабочего пути, а не ради идеальной реализации с первого дня.
На данном этапе платформа не приносит ощутимой пользы, и это нормально для MVP. Главное — она уже работает, и на её основе можно двигаться дальше: улучшать архитектуру, внедрять CI/CD, переходить на надёжный хостинг и строить масштабируемую систему.
Всё великое начинается с малого. Важно, что фундамент заложен — дальше всё зависит от развития, обратной связи и последовательных шагов вперёд.
Мой канал
Также сообщаю, что у меня есть Telegram канал, куда я публикую обновления о ходе разработки образовательной платформы, делюсь своими мыслями и промежуточными результатами - https://t.me/+9NhB_D91XblkNjcy
Почитать более подробно откуда произошла идея можно тут - https://dzen.ru/a/aB4a1yZRiHl3K9L3
Контактные данные
Почта: codeengine.official@gmail.com
Telegram: @Claymore23