local dns & reverse proxy
После того как я решил начать экспериментировать с докером количество сервисов увеличилось и теперь помимо роутера или NAS появились и другие. Так что мне надоело каждый раз прописывать разные порты и захотелось ходить по хосту, а не вспоминать что на каком порту висит. Для этого нам нужен локальный днс для доменов по которым мы будем заходить и прокси который будет раскидывать запросы по контейнерам.
Запуск контейнера
С докером можно работать как через сам docker так и через docker-compose.
например так выглядит запуск portainer через cli
docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
А вот так через docker-compose: сначала надо составать docker-compose.yml
services:
portainer:
name: portainer
image: portainer/portainer-ce:latest
volumes:
- portainer_data:/data
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "8000:8000"
- "9443:9443"
а потом запускать
docker compose up -d
Через compose можно запустить сразу несколько контейнеров необходимых для работы сервиса и они все будут видеть друг друга.
Сеть в docker
Немного про сети docker: если в двух словах, то работа сети в docker реализуется за счет сетевых драйверов:
- none: отключение всех сетевых ресурсов.
- bridge: сетевой драйвер по умолчанию. По сути, это мост между контейнером и хостовой машиной.
- host: для автономных контейнеров устраняется сетевая изолированность между контейнером и хостом Docker и напрямую используются сетевые ресурсы хоста.
При создании контейнера мы можем вручную указать к каким сетям подключаться
В противном случае докер сам поместит контейнер в bridge сеть
По умолчанию docker-compose создает единую сеть для контейнеров в отдельно взятом сервисе и называет её по имени контейнера, так что есть несколько вариантов:
- Засунуть все контейнеры в один docker-compose. Это решает задачу, но имеет большой минус: если надо будет поменять что то в одном контейнере то пересобираться будут все контейнеры и это занимает много времени.
- Сделать свою сеть и добавить туда все сервисы. В таком случае каждый отдельный сервис можно будет выключить отдельно, без пересборки всех остальных.
Подключается просто:
Pi-hole
В качестве локального днс был выбран Pi-hole, он не только выполняет функцию днс, но и умеет работать с блоклистами, а значит будет меньше рекламы.
Контейнер при запуске не будет обновлять блоклисты и сразу начнет отвечать на все запросы, вообще по умолчанию dnsmasq отвечает только на локальные запросы, но в таком случае он будет недоступен. Панель управления будет доступна на 9001 порте. По идеи нам остается только добавить домены и направить их на локальные ip.
На этом с настройкой все, по желанию можно подключить различные блоклисты доступные на github. После того как у нас заработает прокси то проброс 80 порта можно убрать т.к. все запросы пойдут через nginx.
Proxy
Вообще в докере для проксирования есть traefik. Traefik это реверс прокси написанный специально для докера, он дискаверит контейнеры и при наличии определенных меток проксирует трафик в нужный контейнер. Работает это так:
В теории он может проксировать и на внешние хосты, но там надо лезть в конфиги. В сумме с проблемами получения сертификата LE я от него отказался в пользу nginx proxy manager. Фактчески это nginx, certbot и удобный gui в одном флаконе, из минусов это необходимость прописывать прокси вручную.
после запуска идем на 81 порт и видим страницу авторизации
После авторизации нам предложат изменить данные и пароль. Идем в Hosts > Proxy Hosts и жмем на кнопку "add proxy host"
Не лишним будет ограничить доступ для локальных ресурсов:
allow 192.168.0.0/16
allow 172.16.0.0/12
allow 10.0.0.8/8
deny all
Бонусом nginx proxy manager является удобная генерация ssl от let's encrypt. Для начала нам нужен домен на который будет выпущен сертификат. Я воспользовался duckdns.org, там можно бесплатно взять домен 3 уровня и добавлять TXT записи через api. Для получения сертификата через dnschallenge нужно будет указать свой ключ api.