Инструкция: хостим сайты

Image for post
Image for post
Photo by Alex Blăjan on Unsplash

Я плох в настройке nginx и certbot. В этом процессе куча мелких деталей, я постоянно что-то забываю. Одно время я писал себе максимально подробные инструкции — по шагам записывал что нужно сделать для достижения того или иного результата. Но потом я открыл для себя docker-gen и letsencrypt-nginx-proxy-companion. С тех пор я совсем не страдаю.

Дисклеймер

Сложность бывает двух типов — сложность в деталях и сложность в структуре. Запомнить как пользоваться утилитой с плохим API — сложность в деталях. Найти (написать) удобную обертку — сложность в структуре. На мой взгляд, одна из задач программиста — найти баланс между этими двумя типами сложности. Конечное решение на длинной дистанции должно экономить время или деньги.

Например, настройка nginx каждый раз требует от меня полчаса. Настраиваю я его раз в два месяца, то есть за год трачу 6 часов. После открытия docker-gen стал тратить 5 минут, но на изучение технологии ушло 5 часов. Получается, за первый год это новое знание окупилось и дальше будет приносить пользу.

Хорошая практика — стремиться к снижению любой сложности. Поэтому для двух классов приложений я вообще не использую свою инфраструктуру. Дальше об этих двух вариантах в статье я говорить не буду.

Статические сайты, то есть набор HTML, CSS, JS файлов для браузера, можно выложить на netlify. Это дешевый (почти всегда бесплатный) и удобный сервис. Внутри CDN, превью пул-реквестов, быстрые сборки и автоматические SSL сертификаты.

Приложения с бекендом, но без внешних сервисов (база-данных, s3-like хранилище) и внутреннего состояния, можно хостить на Now. Отлично подходит для SPA-приложений с серверным рендерингом.

Инструкция

Я хочу на одном сервере запускать несколько приложений (каждое из которых представляет собой Docker-контейнер). Каждый контейнер слушает свой порт, а nginx бы распределяет запросы на разные хосты на эти порты. Звучит просто, но нужно руками писать конфиги nginx, работать с certbot.

Для того, чтобы автоматизировать все это достаточно развернуть на сервере три контейнера. Создаем docker-compose.yml с описанием этих контейнров. Рядом с ним кладем файл nginx.tmpl — это шаблон по которому будут генерироваться конфиги для каждого хоста.

Посмотрите гист с этими файлами.

nginx — сервер, который будет делать всю работу по определению куда какой запрос отправить, docker-gen на основании конфигурации контейнеров генерирует для них nginx-конфиги, letsencrypt-nginx-proxy-companion автоматически выпускает сертификаты для всех хостов.

Я не буду подробно описывать, что написано внутри этих файлов. Работать они будут и так, а если захочется понять — проще будет разобраться почитав документацию nginx и тех контейнеров, что я использую.

Теперь нужно добавить в любой контейнер 4 переменные окружения и они автоматически станут доступны из интернета.

  • VIRTUAL_HOST — хост, по которому контейнер должен быть доступен. Обратите внимание, что этот хост должен указывать на ваше сервер (А-запись).
  • VIRTUAL_PORT — порт, на котором приложение слушает внутри контейнера. То есть идентичный порту в EXPOSE из Dockerfile.
  • LETSENCRYPT_HOST — хост, на который следует выпускать сертификат. Обычно совпадает с VIRTUAL_HOST.
  • LETSENCRYPT_EMAIL — адрес электронной почты хозяина сайта. Нужен для выпуска сертификата.

Плюс, контейнер приложения должен находиться в одной сети с docker-gen. Ниже пример docker-compose.yml.

И это все. Теперь можно легко разворачивать любое количество контейнеров, не заботиться о сертификатах и конфигурациях.

Резюме

Docker — не только для нагруженных, масштабируемых микросервисов, но и для простых приложений, где важна простота доставки и настройки. Docker позволяет прятать конфиги чего угодно, и не заботиться о внутреннем устройстве сервисов. Ищите баланс между структурной сложностью и сложностью в деталях, упрощайте себе жизнь.

Written by

Software Engineer. Disciplined thinker with battle-tested focus.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store