Привет!
В процессе разработки может возникать необходимость развернуть несколько сайтов в Docker со своим доменом. То есть несколько доменов на одном IP адресе или на одном сервере (локальной машине). Эту задачу достаточно легко решить, если внедрить в свою схему Docker контейнеров промежуточный этап — проксирование с помощью Nginx.
Nginx проксирование в Docker можно выполнить вручную, прописывая перенаправление трафика для каждого хоста. Однако мне этот подход не очень нравится, и поэтому я использую очень полезный Docker Image “jwilder/nginx-proxy“.
Структура размещения файлов на локальном сервере и Docker
У каждого разработчика по своему устроена локальная машина и каждый по своему организовывает структуру файлов. Поэтому я приведу свой пример, чтобы каждый смог адаптировать его под свой конкретный случай. Ну а начинающие могут просто использовать мою простую схему.
На моей машине с Ubuntu в домашней папке существует директория server. То есть путь выглядит следующим образом:
/home/UserName/server
Code 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 -d
Code language: JavaScript (javascript)
Запускаем контейнеры для обслуживания наших сайтов. В данном случае будут запущены сайты example_gs_site.docker
и phpmyadmin.example_gs_site.docker
cd ~/server/example_gs_site.docker/docker
docker-compose up -d
Code language: JavaScript (javascript)
Важно! Чтобы все используемые домены работали на вашей локальной машине необходимо добавить эти домены
127.0.0.1 phpmyadmin.example_gs_site.docker
иphpmyadmin.example_gs_site.docker
в файл /etc/hostsexample_gs_site
.docker
127.0.0.1example_gs_site
.docker
Безусловно, в текущей статье я не описывал детально сборку контейнеров, которые обслуживают работу сайтов. К примеру, контейнер с именем gs_docker_php собирается с помощью Dockerfile, содержимое которого отсутствует в статье. Это было сделано умышленно, поскольку детализация сборки подобных контейнеров сугубо индивидуальна и зависит от того, какие именно сайты запускаются. В данном конкретном случае я привел пример реального кода который используется для локального запуска сайтов на laravel. Если необходимы конкретные детали, читайте статью Как запустить Laravel в Docker (вскоре появится ссылка на статью).
При необходимости можно запустить еще несколько таких же локальных сайтов. Для этого сервису Nginx необходимо предоставить внешнюю сеть для проксирования.
Вопросы, баги, дополнения и все остальное прошу писать в комментариях!