Docker nginx-proxy: прокси между контейнерами
В настоящее время я работаю над стеком разработки с использованием Docker-Compose в своей компании, чтобы предоставить разработчикам все, что им нужно для кодирования наших приложений.
Это включает, в частности:
- контейнер Gitlab ( sameersbn / gitlab) для управления частными репозиториями GIT,
- контейнер Jenkins ( библиотека / jenkins) для построения и непрерывной интеграции,
- контейнер Archiva ( https://hub.docker.com/r/ninjaben/archiva-docker/) для управления репозиториями Maven.
Чтобы защитить сервисы через HTTPS и показать их внешнему миру, я установил превосходный контейнер nginx-proxy ( https://github.com/jwilder/nginx-proxy), который позволяет автоматическую настройку прокси-сервера nginx с использованием переменных среды в контейнерах и автоматическое перенаправление HTTP на HTTPS.,
DNS настроен для сопоставления каждого общедоступного URL-адреса докеризованных сервисов с IP-адресом хоста.
Наконец, используя Docker-Compose, мой файл docker-compose.yml выглядит так:
version: '2'
services:
nginx-proxy:
image: jwilder/nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /var/config/nginx-proxy/certs:/etc/nginx/certs:ro
postgresql:
# Configuration of postgresql container ...
gitlab:
image: sameersbn/gitlab
ports:
- "10022:22"
volumes:
- /var/data/gitlab:/home/git/data
environment:
# Bunch of environment variables ...
- VIRTUAL_HOST=gitlab.my-domain.com
- VIRTUAL_PORT=80
- CERT_NAME=star.my-domain.com
archiva:
image: ninjaben/archiva-docker
volumes:
- /var/data/archiva:/var/archiva
environment:
- VIRTUAL_HOST=archiva.my-domain.com
- VIRTUAL_PORT=8080
- CERT_NAME=star.my-domain.com
jenkins:
image: jenkins
volumes:
- /var/data/jenkins:/var/jenkins_home
environment:
- VIRTUAL_HOST=jenkins.my-domain.com
- VIRTUAL_PORT=8080
- CERT_NAME=star.my-domain.com
Для рабочей станции разработчика все работает как положено. Можно получить доступ к услугам разницы через https://gitlab.my-domain.com
, https://repo.my-domain.com
а также https://jenkins.my-domain.com
,
Проблема возникает, когда одна из служб Dockerized получает доступ к другой службе Dockerized. Например, если я пытаюсь получить доступ https://archiva.my-domain.com
от Дженкинса Докера, я получу ошибку тайм-аута от прокси.
Кажется, что даже если archiva.my-domain.com
разрешается как общедоступный IP-адрес хоста из контейнера Docker,запросы, поступающие от сервисов Dockerized, не передаются через прокси-сервер nginx.
Насколько я понял, docker-nginx обрабатывает запросы, поступающие из хост-сети, но не заботится о запросах, поступающих из внутренней контейнерной сети (_dockerconfig_default_ для стека Docker-Compose).
Вы могли бы сказать, зачем мне использовать прокси из контейнера? Конечно, я мог бы использовать URLhttp://archiva:8080
из контейнера Дженкинс, и это будет работать. Но такая конфигурация не масштабируется.
Например, используя сборку Gradle для компиляции одного приложения, build.gradle должен объявить мой частный репозиторий черезhttps://archiva.my-domain.com
, Это будет работать, если сборка запускается с рабочей станции разработчика, но не через контейнер jenkins...
Другим примером является аутентификация в Jenkins с помощью службы OAuth GitLab, где один и тот же URL-аутентификация GitLab должна быть доступна как снаружи, так и внутри контейнера Jenkins.
Мой вопрос здесь заключается в следующем: как настроить nginx-proxy для прокси запроса от контейнера к другому контейнеру?
Я не видел ни одной темы, обсуждающей эту проблему, и я недостаточно понимаю проблему, чтобы построить решение на конфигурации nginx.
Любая помощь могла бы быть полезна.
1 ответ
BMitch, шансы были хорошими, это действительно была проблема с правилами iptables, а не неправильная конфигурация nginx-proxy.
Политика по умолчанию цепочки INPUT для таблицы filter
было DROP
и не было сделано никаких правил для ACCEPT
запросы от IP-адресов контейнера (127.20.XX).
Для справки, я приведу некоторые подробности ситуации, если другие люди столкнутся с той же проблемой.
Чтобы получить доступ к контейнерам из внешнего мира, Docker установил правила для правил PREROUTING и FORWARD, чтобы разрешить DNAT внешних IP-адресов с IP-адреса хоста на IP-адреса контейнера. Эти правила по умолчанию разрешают любые внешние IP-адреса, и поэтому ограничение доступа к контейнерам требует некоторых расширенных настроек iptables.
Смотрите эту ссылку для примера: http://rudijs.github.io/2015-07/docker-restricting-container-access-with-iptables/
Но если вашим контейнерам требуется доступ к ресурсам хоста (сервисы, запущенные на хосте, или, в моем случае, контейнер nginx-прокси, прослушивающий порт хоста HTTP/HTTPS и проксирующий к контейнерам), вам необходимо позаботиться о правилах iptables Входная цепь.
Фактически, запрос, поступающий из контейнера и адресованный хосту, будет перенаправлен в сетевой стек хоста демоном Docker, но затем должен будет пройти цепочку INPUT (как запрос src
IP - хост один). Поэтому, если вы хотите защитить ресурсы хоста и позволить контейнерам получать к ним доступ, не забудьте добавить что-то вроде этого:
iptables -A INPUT -s 127.20.X.X/24 -j ACCEPT
Где 127.20.XX/24 - это виртуальная сеть, в которой работают ваши контейнеры.
Большое спасибо за вашу помощь.