Опубликовано:

Несколько доменов (хостов) в Docker на одном сервере и IP-адресе

Привет!

В процессе разработки может возникать необходимость развернуть несколько сайтов в Docker со своим доменом. То есть несколько доменов на одном IP адресе или на одном сервере (локальной машине). Эту задачу достаточно легко решить, если внедрить в свою схему Docker контейнеров промежуточный этап — проксирование с помощью Nginx.

Nginx проксирование в Docker можно выполнить вручную, прописывая перенаправление трафика для каждого хоста. Однако мне этот подход не очень нравится, и поэтому я использую очень полезный Docker Image “jwilder/nginx-proxy“.

Структура размещения файлов на локальном сервере и Docker

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

На моей машине с Ubuntu в домашней папке существует директория server. То есть путь выглядит следующим образом:

/home/UserName/serverCode language: PHP (php)

В этой директории я храню все содержимое, что касается моих локальных сайтов. Для каждого сайта внутри директории server у меня имеются соответствующие директории.

/home/UserName/server/example_gs_site.docker
/home/UserName/server/subdomen.siteForImportantClient.docker
/home/UserName/server/subdomen2.siteForImportantClient.docker
/home/UserName/server/subdomen.myPetProject.local

Полагаю тут нечего дополнительно объяснять.

Запускаем Reverse Proxy на базе jwilder/nginx-proxy для проксирования запросов

Также внутри директории Server у меня хранится еще одна папочка, которая называется proxy, внутри этой папки хранится только один документ:

/home/UserName/server/proxy/docker-compose.yml

Содержимое файла docker-compose.yml следующее:

version: '3.0'

services:

  proxy:
    image: jwilder/nginx-proxy  # используем внешний image
    container_name: proxy_proxy # задаем конкретное имя контейнеру
    restart: always             # всегда перезапускаем контейнер
    privileged: true
    ports:
      - 80:80                   # прокидываем порт 80 для обработки http запросов
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
    networks:
      - proxy                   # указываем, с какой внутренней сетью будет работать контейнер


networks:                       # конфигурируем сеть
  proxy:                        # указываем имя сети
    driver: bridge              # указываем драйверCode language: PHP (php)

Запускаем локальный сайт в Docker на своем домене

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

version: '3.0'

services:

  gs_nginx:
    image: nginx
    container_name: gs_docker_nginx
#    restart: always
    environment:
      - VIRTUAL_HOST=example_gs_site.docker # указываю виртуальный хост (домен)
    depends_on:
      - gs_php
    volumes:
      - ./nginx/conf.d/default.nginx:/etc/nginx/conf.d/default.conf
      - ./../:/var/www/     # прокидываем рабочие файлы внутрь контейнера
      - ./nginx/logs:/var/log/nginx/
      - ./nginx/ssl:/etc/nginx/ssl
    networks:
      - frontend        # самый важный момент - указываем сеть для проксирования
      - backend         # указываем сеть для связи с другими контейнерами

  gs_php:
    container_name: gs_docker_php
    build:
      args:
        user: wwwdata
        uid: 1000
      context: ./php
    volumes:
      - ./php/local.ini:/usr/local/etc/php/php.ini
      - ./../:/var/www/
    networks:
      - frontend    # (important №1) указываем сеть для проксирования
      - backend     # указываем сеть для связи с другими контейнерами

  gs_mysql:
    image: mysql:5.7
    container_name: gs_docker_mysql
    volumes:
      - ./mysql/my.cnf:/etc/my.cnf
      - ./mysql/data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: example_dbusr
      MYSQL_PASSWORD: example_dbpsswd
      MYSQL_DATABASE: example_dbname
    networks:
      - backend   # указываем сеть для связи с другими контейнерами
    command: --sql_mode=""

  gs_phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    container_name: gs_docker_phpmyadmin
    environment:
      - VIRTUAL_HOST=phpmyadmin.example_gs_site.docker  # указываю виртуальный хост (домен)
      - PMA_HOST=gs_mysql
      - PMA_USER=root
      - PMA_PASSWORD=root
    networks:
      - frontend    # (important №2) указываем сеть для проксирования
      - backend     # указываем сеть для связи с другими контейнерами

networks:
  frontend:
    external:
      name: proxy_proxy # (important №3) указываем имя сети для проксирования
  backend:              # создаем сеть для связки текущих контейнеров
 Code language: PHP (php)

Комментарии по поводу пунктов important :

  • important №1 — обязательно необходима сеть, которая сконфигурирована как внешняя, для работы нескольких доменов
  • important №2 — обязательно необходима сеть, которая сконфигурирована как внешняя, для работы нескольких доменов
  • important №3 — конфигурируем внутреннюю и внешнюю сеть. Внешняя необходима для проксирования. Задаем ей имя того контейнера, который указан в файле server/proxy/docker-compose.yml

Запускаем в работу все сервисы Docker

И теперь, чтобы заставить это все работать, выполняем следующие команды.

Запускаем контейнер для нашего Nginx Proxy:

cd ~/server/proxy
docker-compose up -dCode language: JavaScript (javascript)

Запускаем контейнеры для обслуживания наших сайтов. В данном случае будут запущены сайты example_gs_site.docker и phpmyadmin.example_gs_site.docker

cd ~/server/example_gs_site.docker/docker
docker-compose up -dCode language: JavaScript (javascript)

Важно! Чтобы все используемые домены работали на вашей локальной машине необходимо добавить эти домены example_gs_site.docker и phpmyadmin.example_gs_site.docker в файл /etc/hosts

127.0.0.1 phpmyadmin.example_gs_site.docker
127.0.0.1 example_gs_site.docker

Безусловно, в текущей статье я не описывал детально сборку контейнеров, которые обслуживают работу сайтов. К примеру, контейнер с именем gs_docker_php собирается с помощью Dockerfile, содержимое которого отсутствует в статье. Это было сделано умышленно, поскольку детализация сборки подобных контейнеров сугубо индивидуальна и зависит от того, какие именно сайты запускаются. В данном конкретном случае я привел пример реального кода который используется для локального запуска сайтов на laravel. Если необходимы конкретные детали, читайте статью Как запустить Laravel в Docker (вскоре появится ссылка на статью).

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

Вопросы, баги, дополнения и все остальное прошу писать в комментариях!

Опубликовано:
Присоединяйся!

Подписывайся на блог и развивайся вместе со мной.

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

Ваши комментарии