Использование Docker для настройки обратного прокси Nginx с автоматической генерацией SSL

Что такое обратный прокси? Обратный прокси-сервер – это своего рода сервер, который находится перед многими другими серверами и перенаправляет клиентские запросы на соответствующие серверы. Затем ответ от сервера также принимается и пересылается прокси-сервером клиенту.

Зачем вам такая установка? Для этого есть несколько веских причин. Эту настройку можно использовать для настройки балансировщика нагрузки, кэширования или для защиты от атак.

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

Возьмите то же изображение, что вы видели выше. Что вы можете сделать, так это запустить сервер Ngnix в Docker контейнере в режиме обратного прокси. Другие веб-службы также могут запускаться в своих собственных контейнерах.

Контейнер Nginx будет настроен таким образом, чтобы он знал, какая веб-служба в каком контейнере работает.

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

 

Настройка Nginx в качестве обратного прокси-сервера для развертывания нескольких сервисов на одном сервере с помощью Docker

Позвольте нам показать вам, как приступить к настройке вышеупомянутой установки.

С помощью этих шагов вы можете установить несколько контейнеров веб-приложений, работающих под Nginx, причем каждый автономный контейнер соответствует своему собственному домену или субдомену.

Во-первых, давайте посмотрим, что вам нужно, чтобы следовать этой статьи.

 

Предпосылки

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

  • Система/сервер Linux.
  • Знакомство с командами и терминалом Linux.
  • Базовые знания Docker.
  • На вашем сервере Linux должны быть установлены Docker и Docker Compose. Прочтите нашу статью по установке Docker и Docker Compose на CentOS.
  • Вы также должны владеть доменом (чтобы вы могли настраивать службы на поддоменах).

Мы использовали domain.ru в качестве примера доменного имени в статье. Убедитесь, что вы изменили его в соответствии с вашими собственными доменами или субдоменами.

Кроме вышеперечисленного, убедитесь также в следующем:

Измените записи DNS вашего домена

На панели записи A/AAAA или CNAME вашего поставщика доменного имени убедитесь, что и домен, и субдомены (включая www) указывают на IP-адрес вашего сервера.

Это пример для справки:

Имя хоста
IP адрес
TTL
domain.ru172.173.32.178По умолчанию
*172.173.32.178По умолчанию
sub0.domain.ru172.173.32.178По умолчанию
sub1.domain.ru172.173.32.178По умолчанию

 

Своп

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

Вы всегда можете настроить подкачку в соответствии с доступной оперативной памятью в вашей системе. Вы можете выбрать пространство подкачки на основе набора контейнеров приложений на одном сервере и оценки их совокупного использования ОЗУ.

 

Шаг 1. Настройте контейнер обратного прокси Nginx

Начните с настройки обратного прокси-сервера nginx. Создайте каталог с именем “reverse-proxy” и переключитесь в него:

mkdir reverse-proxy && cd reverse-proxy

 

Создайте файл с именем docker-compose.yml, откройте его в своем любимом текстовом редакторе на базе терминала, таком как Vim или Nano.

Для обратного прокси-сервера nginx мы будем использовать образ jwilder/nginx-proxy. Скопируйте и вставьте в файл docker-compose.yml следующее:

version: "3.7"

services:

    reverse-proxy:
        image: "jwilder/nginx-proxy:latest"
        container_name: "reverse-proxy"
        volumes:
            - "html:/usr/share/nginx/html"
            - "dhparam:/etc/nginx/dhparam"
            - "vhost:/etc/nginx/vhost.d"
            - "certs:/etc/nginx/certs"
            - "/run/docker.sock:/tmp/docker.sock:ro"
        restart: "always"
        networks: 
            - "net"
        ports:
            - "80:80"
            - "443:443"

 

Теперь давайте пройдемся по важным частям файла создания:

  • Вы объявили четыре тома: html, dhparam, vhost и certs. Это постоянные данные, которые вы определенно захотите сохранить даже после того, как контейнер вышел из строя. html и vhost будут очень важны в следующем развертывании контейнера Let’s Encrypt. Они созданы для совместной работы.
  • Сокет docker монтируется внутри контейнера только для чтения. Это необходимо для обратного прокси-контейнера для создания файлов конфигурации nginx, обнаружения других контейнеров с определенной переменной среды.
  • Для политики перезапуска установлено значение always. Другие варианты включают on-failure и unless-stopped. В этом случае всегда казалось более подходящим.
  • Порты 80 и 443 привязаны к хосту для http и https соответственно.
  • Наконец, он использует другую сеть, а не мостовую сеть по умолчанию.

Использование сети, определяемой пользователем, очень важно. Это поможет изолировать все контейнеры, которые должны быть проксированы, а также позволит обратному прокси-контейнеру перенаправлять клиентов в их желаемые/предполагаемые контейнеры, а также позволит контейнерам взаимодействовать друг с другом (что невозможно с сетью моста по умолчанию. если iccне установлено значение trueдля демона).

Имейте в виду, что YML очень требователен к табуляциям и отступам.

 

Шаг 2. Настройте контейнер для автоматического создания сертификата SSL

Для этого вы можете использовать образ контейнера jrcs/letsencrypt-nginx-proxy-companion.

В том же файле docker-compose.yml, который вы использовали ранее, добавьте следующие строки:

    letsencrypt:
        image: "jrcs/letsencrypt-nginx-proxy-companion:latest"
        container_name: "letsencrypt-helper"
        volumes:
            - "html:/usr/share/nginx/html"
            - "dhparam:/etc/nginx/dhparam"
            - "vhost:/etc/nginx/vhost.d"
            - "certs:/etc/nginx/certs"
            - "/run/docker.sock:/var/run/docker.sock:ro"
        environment:
            NGINX_PROXY_CONTAINER: "reverse-proxy"
            DEFAULT_EMAIL: "[email protected]"
        restart: "always"
        depends_on:
            - "reverse-proxy"
        networks: 
            - "net"

 

В этом определении услуги:

  • Вы используете те же самые тома, что и для контейнера обратного прокси. html и vhost – совместное использование томов необходимы для ACME Challenge of letsencrypt. Этот контейнер будет генерировать сертификаты внутри /etc/nginx/certs, в контейнере. Вот почему вы разделяете этот том со своим обратным прокси-контейнером. Том dhparam будет содержать файл dhparam. Сокет монтируется для обнаружения других контейнеров с определенной переменной среды.
  • Здесь вы определили две переменные среды. В точки переменной NGINX_PROXY_CONTAINER для обратного прокси – контейнера. Задайте его имя контейнера. DEFAULT_EMAIL – это адрес электронной почты, который будет использоваться при создании сертификатов для каждого домена/поддомена.
  • Параметр depends_on установлен таким образом, что эта служба сначала ожидает запуска обратного прокси-сервера, а затем и только тогда он запускается.
  • Наконец, этот контейнер также находится в одной сети. Это необходимо для связи двух контейнеров.

 

Шаг 3. Завершите создание файла для докеров

После того, как определения сервисов созданы, заполните файл docker-compose следующими строками:

volumes:
  certs:
  html:
  vhost:
  dhparam:

networks:
  net:
    external: true

 

Сеть net настроена на внешнюю, потому что прокси-контейнеры также должны будут использовать эту сеть. И если мы оставим сеть для создания docker-comspose, имя сети будет зависеть от текущего каталога. Это создаст сеть со странным названием.

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

Поэтому создайте сеть, используя

 docker network create net

 

Ниже приводится все содержимое файла docker-compose.yml.

version: "3.7"

services:

    reverse-proxy:
        image: "jwilder/nginx-proxy:latest"
        container_name: "reverse-proxy"
        volumes:
            - "html:/usr/share/nginx/html"
            - "dhparam:/etc/nginx/dhparam"
            - "vhost:/etc/nginx/vhost.d"
            - "certs:/etc/nginx/certs"
            - "/run/docker.sock:/tmp/docker.sock:ro"
        restart: "always"
        networks: 
            - "net"
        ports:
            - "80:80"
            - "443:443"
    letsencrypt:
        image: "jrcs/letsencrypt-nginx-proxy-companion:latest"
        container_name: "letsencrypt-helper"
        volumes:
            - "html:/usr/share/nginx/html"
            - "dhparam:/etc/nginx/dhparam"
            - "vhost:/etc/nginx/vhost.d"
            - "certs:/etc/nginx/certs"
            - "/run/docker.sock:/var/run/docker.sock:ro"
        environment:
            NGINX_PROXY_CONTAINER: "reverse-proxy"
            DEFAULT_EMAIL: "[email protected]"
        restart: "always"
        depends_on:
            - "reverse-proxy"
        networks: 
            - "net"
volumes:
  certs:
  html:
  vhost:
  dhparam:

networks:
  net:
    external: true

 

Наконец, вы можете развернуть эти два контейнера (Ngnix и Let’s Encrypt) с помощью следующей команды:

docker-compose up -d

 

Шаг 4. Запустите другие сервисные контейнеры с обратным прокси

Процесс настройки других контейнеров, чтобы их можно было проксировать, ОЧЕНЬ прост.

 

Определите правильные переменные среды

Контейнер, который будет обслуживать интерфейс, должен будет определить две переменные среды.

  • VIRTUAL_HOST: для создания конфигурации обратного прокси
  • LETSENCRYPT_HOST: для создания необходимых сертификатов

 

Вы можете запустить веб-службу через контейнер докеров с обратным прокси следующим образом (не копируйте и вставляйте его):

docker run --name service_container_name --network net -e VIRTUAL_HOST="sub0.domain.ru" -e LETSENCRYPT_HOST="sub0.domain.ru" -d service_image

 

Мы покажем это с двумя экземплярами развертывания Nextcloud через мгновение. Позвольте нам сначала рассказать вам, что вы здесь делаете.

 

Не привязывать ни к какому порту

В контейнере может отсутствовать порт, обслуживающий интерфейс. Контейнер обратного прокси-сервера автоматически обнаружит это.

 

(НЕОБЯЗАТЕЛЬНО) Определить VIRTUAL_PORT

Если обратный прокси-контейнер не может обнаружить порт, вы можете определить другую переменную среды VIRTUAL_PORT с именем порта, обслуживающего интерфейс, или любую другую службу, которую вы хотите проксировать, например «80» или «7765».

 

Установите Let’s Encrypt для конкретного контейнера

Вы можете переопределить переменную DEFAULT_EMAIL и установить конкретный адрес электронной почты для сертификата (ов) домена/поддомена конкретного контейнера/веб-службы, установив идентификатор электронной почты в переменную среды LETSENCRYPT_EMAIL. Это работает для каждого контейнера.

Теперь, когда вы знаете все это, позвольте мне показать вам команду, которая развертывает экземпляр Nextcloud, который будет проксироваться с помощью прокси-контейнера nginx и будет иметь включенный TLS (SSL/HTTPS).

Это НЕ ИДЕАЛЬНОЕ развертывание. Следующая команда используется только в демонстрационных целях.

docker run --name nextcloud --network net -e VIRTUAL_HOST="sub0.domain.ru" -e LETSENCRYPT_HOST="sub0.domain.ru" -d nextcloud:19.0.2

 

В этом примере вы использовали ту же сеть, что и обратные прокси-контейнеры, определили две переменные среды с соответствующими поддоменами (установите свои соответственно). Через пару минут вы должны увидеть, что Nextcloud работает на sub0.domain.ru. Откройте его в браузере, чтобы проверить.

Вы можете развернуть другой экземпляр Nextcloud, как этот, в другом субдомене, например:

docker run --name anothernextcloud --network net -e VIRTUAL_HOST="sub1.domain.ru" -e LETSENCRYPT_HOST="sub1.domain.ru" -d nextcloud:19.0.2

 

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

С помощью этого метода вы можете развертывать разные веб-приложения на одном сервере, обслуживаемом в разных субдоменах, что очень удобно.

Sidebar