Docker – отличный инструмент для запуска нескольких сервисов на одном VPS без их взаимодействия друг с другом – например, один веб-сайт построен на WordPress, а другой – на Ghost или какой-либо другой CMS.
Но контейнеризация программного обеспечения приводит к другой проблеме: как разместить несколько сайтов, каждый в отдельном контейнере Docker, на одном VDS сервере? К счастью, с небольшим предвидением и настройкой вы можете использовать Docker и Nginx для размещения нескольких веб-сайтов с одного VPS.
По умолчанию все службы Docker прослушивают порт 80, что создает конфликты для входящего трафика. Конечно, вы можете изменить порт прослушивания, но никто не хочет вводить andreyex.ru:27364 для доступа к своему любимому сайту.
Что, если вместо этого вы могли бы использовать nginx для маршрутизации трафика, поступающего с andreyex.ru к уникальному контейнеру, прослушивающему порт 27364, и для маршрутизации трафика, поступающего в anotherandreyex.ru второй контейнер, прослушивающий 43567?
Это именно то, что nginx-proxy делает: он слушает порт 80 (стандартный порт HTTP) и перенаправляет входящие запросы в соответствующий контейнер. Это часто называют обратным прокси-сервером и использует переменную VIRTUAL_HOST в Docker.
В этой статье мы настроим nginx-proxy и научимся использовать Docker и Nginx для маршрутизации трафика в разные контейнеры, что позволит вам размещать несколько сайтов в разных доменах с одного сайта.
Предпосылки
- Сервер Ubuntu/Debian/CentOS с установленным Docker – для начала ознакомьтесь со статьей по установке Docker.
- Некорневой пользователь с sudo привилегиями.
- Полное доменное имя от регистратора доменов.
- Возможность изменять настройки DNS через регистратора вашего домена.
Шаг 1. Запуск nginx-proxy для соединения Docker и Nginx
Для начала давайте запустим nginx-proxy контейнер. Это может быть выполнено либо одной docker командой, либо с помощью docker-compose. Давайте рассмотрим оба.
Но прежде чем мы это сделаем, давайте создадим сеть Docker. Сеть позволит нашим контейнерам «общаться» между собой.
$ docker network create nginx-proxy
Теперь нам нужно добавить новые контейнеры в эту nginx-proxy сеть Docker.
Установка nginx-прокси с помощью Docker
$ docker run -d -p 80:80 --name nginx-proxy --net nginx-proxy -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy
Установка nginx-прокси с помощью docker-compose
Сначала создайте новый файл docker-compose.yml в выбранном вами каталоге (один с именем nginx-proxy) и скопируйте следующий текст:
version: "3" services: nginx-proxy: image: jwilder/nginx-proxy container_name: nginx-proxy ports: - "80:80" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro networks: default: external: name: nginx-proxy
А затем выполните следующую команду docker-compose, чтобы начать.
$ docker-compose up -d
Как nginx-proxy использует Docker и Nginx для размещения нескольких сайтов на одном VPS
Сначала контейнер nginx-proxy прослушивает порт 80. Весь трафик, поступающий на VPS через порт 80, будет проходить через него nginx-proxy. Это хороший первый шаг. Но как он узнает, отправлять ли человека А на blog.example.com и человека Б на app.example.com?
Это то, что выполняет строка /var/run/docker.sock:/tmp/docker.sock. По сути, это дает любому контейнеру доступ к сокету Docker хоста, который содержит информацию о различных событиях Docker, таких как создание нового контейнера или его закрытие.
Каждый раз, когда вы добавляете новый контейнер Docker в свою сеть, nginx-proxy просматриваете событие через сокет, автоматически создают файл конфигурации, необходимый для маршрутизации трафика, и перезагружаются, nginx чтобы изменения немедленно стали доступны.
Прокси ищет контейнеры с включенной переменной VIRTUAL_HOST. В этой переменной можно указать место назначения, нравится blog.example.com или app.example.com. Прокси-сервер увидит, что человек А запросил blog.example.com и направит (или прокси-сервер!) свой запрос в правильный контейнер. То же самое касается app.example.com или любых других контейнеров, которые вы хотите запустить.
Также обратите внимание на строку –net nginx-proxy в команде Docker и блок networks: default: external: name: nginx-proxy в файле docker-compose.yml. Таким образом вы указываете, какую сеть Docker вы хотите использовать в новом контейнере.
Шаг 2. Добавление вашего первого контейнера Docker в прокси Nginx
Теперь, когда мы nginx-proxy запустили, мы можем начать добавлять новые контейнеры, которые будут автоматически подбираться и настраиваться. Поскольку мы рассмотрели это в статье по установке Docker, и, поскольку это простая реализация, попробуйте использовать WordPress в качестве примера.
Использование Docker
Запуск контейнера WordPress с базовой конфигурацией довольно прост.
$ docker run -d --name blog --expose 80 --net nginx-proxy -e VIRTUAL_HOST=blog.DOMAIN.TLD wordpress
Обратите внимание на несколько элементов здесь. –expose 80 позволит трафику поступать в контейнер через порт 80. –net nginx-proxy гарантирует, что мы используем созданную ранее сеть Docker. Наконец, флаги -e VIRTUAL_HOST=blog.DOMAIN.TLD для создания прокси nginx-proxy и направления любого трафика, запрашивающего этот домен, в этот новый контейнер Docker. Замените домен DOMAIN.TLD по вашему выбору.
Использование docker-compose
Начните с создания файла ‘docker-compose.yml’ в пустой директории и скопируйте его следующим образом.
version: "3" services: db_node_domain: image: mysql:5.7 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: PASS123 MYSQL_DATABASE: DBNAME MYSQL_USER: USER MYSQL_PASSWORD: PASS123 container_name: wordpress_db wordpress: depends_on: - db_node_domain image: wordpress:latest expose: - 80 restart: always environment: VIRTUAL_HOST: blog.DOMAIN.TLD WORDPRESS_DB_HOST: db_node_domain:3306 WORDPRESS_DB_USER: andreyex WORDPRESS_DB_PASSWORD: PASS123 container_name: wordpress volumes: db_data: networks: default: external: name: nginx-proxy
Опять же, принять к сведению параметры expose и environment: в файле VIRTUAL_HOST. Кроме того, опция networks внизу необходима, чтобы позволить этому контейнеру «говорить» с nginx-proxy.
Вы также захотите изменить пароли для самой базы данных MySQL и для пользователя WordPress, который обращается к указанной базе данных. WordPress автоматически создаст новый пароль для вашей учетной записи администратора WordPress в процессе установки.
Как только файл конфигурации будет завершен, вы можете запустить команду docker-compose up -d.
Шаг 3. Посещение вашего нового сайта WordPress и добавление еще
На этом этапе вам необходимо настроить параметры DNS вашего домена так, чтобы они указывали на IP-адрес вашего VPS. Если вы настроили свой блог blog.DOMAIN.TLD, создайте запись A для этого субдомена и укажите на тот же IP-адрес.
При правильной настройке DNS вы сможете посетить и увидеть знаменитую 5-минутную установку WordPress! Поздравляем!
Теперь вы можете загрузить любые другие контейнеры Docker, такие как другой сайт WordPress или любой другой тип приложения/службы, и nginx-proxy позаботятся обо всем остальном.
Одна оговорка для нескольких установок WordPress
Если вы собираетесь разместить несколько блогов WordPress с помощью этого метода, вам необходимо создать уникальное имя базы данных для каждого экземпляра. Тем самым вы подключаете WordPress A к MySQL A, а WordPress B подключается к MySQL B и так далее.
Видите линию чуть ниже services? Тот, который читает db_node_domain? Это название вашего контейнера. Вы можете выбрать любую схему именования, которую хотите, но у каждого экземпляра должно быть свое имя.
После того как вы выбрали имя, вам нужно обновить два других поля.
Первое:
depends_on:
– db_node_domain
И второе:
WORDPRESS_DB_HOST: db_node_domain:3306
Дополнительные ресурсы для размещения нескольких сайтов
Конечно, не забудьте проверить обширную документацию для nginx-proxy чтобы узнать больше о том, как вы можете настроить некоторые более сложные прокси между Docker и Nginx, например, с использованием протокола SSL, с несколькими портами или нескольких сетей.
Мы не тестировали его еще, но есть «спутник», для nginx-proxy, вызов letsencrypt-nginx-proxy-companion, который позволяет создавать/обновления сертификатов Let’s Encrypt автоматически непосредственно вместе с самим прокси.