Apache прокси не может достучаться до контейнера Docker, несмотря на то что порт открыт и доступен.

Вопрос или проблема

У меня есть самая простая настройка Apache-прокси, которую я не могу заставить работать.

На сервере CentOS я запускаю обычную настройку Apache/httpd, которая обслуживает несколько веб-сайтов. Apache слушает на портах 80 и 443.

SELinux отключен, и порты 80 и 8080 разрешены на всех интерфейсах в файерволе iptables.

Мне было поручено настроить дополнительный веб-сайт, но этот веб-сайт упакован как приложение LAMP с использованием Docker Compose, которое также использует Apache внутри.

Это должно быть просто, верно? Все, что мне нужно сделать, это использовать внешний Apache для проксирования входящего трафика с порта 80 на любой порт, который открывает Docker (например, 8080):

[Интернет] -> Внешний Apache (:80) -> ProxyPass -> Docker (:8080) -> Внутренний Apache (:80) -> [Контент]

Но что бы я ни делал, это просто не работает. Внешний Apache-прокси слушает на порту 80 нормально, и я вижу входящие запросы к нему. Но проксируемые запросы просто не могут достичь сервера, открытого Docker.

Ошибка, которую я вижу в логах внешнего Apache:

[proxy_http:error] [pid 11669] (70007)Время ожидания истекло: [client xxx:59517] AH01102: ошибка чтения строки статуса с удаленного сервера localhost:8080

В логах внутреннего Apache Docker ничего нет.

Примечание: Я пытался временно остановить мой внешний экземпляр Apache и позволить стеку Docker выходить напрямую на сервер с использованием ports: 80:80, и он был доступен – так что я знаю, что стек Docker работает. Это связано что-то с сопоставлением портов и/или прокси, что вызывает проблему.

Странно то, что я знаю, что Docker правильно открывает порт, потому что он отвечает на запросы:

# nc -zv localhost 8080
Ncat: Версия 7.50 ( https://nmap.org/ncat )
Ncat: Подключено к 127.0.0.1:8080.
Ncat: 0 байт отправлено, 0 байт получено за 0.01 секунд.

Я полагаю, это исключает файервол как причину, потому что если бы он был заблокирован, я ожидал бы, что Ncat будет отклонен.

Вот как выглядит мой файл docker-compose.yml:

# docker-compose.yml
version: '3'

services:
  php:
    image: php:7.2-apache
    ports:
      - 8080:80
    volumes:
      - ./html:/var/www/html # Содержит index.php

Вот файл конфигурации внешнего Apache-прокси:

# apache2 работающий вне Docker
# test.local-vhost.conf
LoadModule proxy_module      modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

<VirtualHost *:80>

    ServerName example.com

    ProxyPreserveHost On
    ProxyPass         / http://localhost:8080
    ProxyPassReverse  / http://localhost:8080

</VirtualHost>

Интересно, когда я обращаюсь к порту 8080 со своего домашнего компьютера, все работает отлично. Но когда я обращаюсь к порту 80, это не работает. Возможно, что-то связано с тем, что прокси не может достичь порта 8080 на той же машине.

Оказалось, что это происходило из-за внутреннего трафика, заблокированного слишком строгим набором правил.

Вот что потребовалось, чтобы решить проблему:

iptables -A INPUT -p tcp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Ответ или решение

Вопрос: Apache Proxy не может достучаться до Docker-контейнера, несмотря на то, что порт открыт и доступен

Введение

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

Текущая конфигурация

Вы настроили Apache на CentOS для проксирования запросов на Docker-контейнер, использующий LAMP-стек. Ваша конфигурация включает следующие ключевые моменты:

  1. Apache на CentOS прослушивает порты 80 и 443.
  2. SELinux отключен, что исключает влияние политик безопасности.
  3. iptables настроен для разрешения трафика на портах 80 и 8080.
  4. docker-compose.yml файл корректно указывает на проброс порта 8080.

Проблема

Несмотря на правильную настройку, Apache не может достать до контейнера на порту 8080, что приводит к ошибке:

[proxy_http:error] [pid 11669] (70007)The timeout specified has expired: [client xxx:59517] AH01102: error reading status line from remote server localhost:8080

Анализ

Исходя из вашего описание, вы можете исключить следующие возможные причины проблемы:

  1. Работа Docker: Как Вы отметили, удаление Apache из цепочки и доступ к контейнеру через порт 8080 работает без каких-либо ошибок. Это подтверждает правильную работу самого контейнера.

  2. Проброс портов: Тестирование с использованием nc -zv localhost 8080 показывает, что порт открыт. Это также указывает на то, что iptables не блокируют подключения.

  3. Ошибка в конфигурации Apache: Конфигурация Apache кажется корректной и также исключена как источник проблемы.

Решение

При более детальном взгляде на вашу конфигурацию и логирование становится ясным, что вероятная причина заключается в правилах iptables, которые могут блокировать внутренние соединения.

Вы обнаружили, что необходимо добавить следующее правило в iptables:

iptables -A INPUT -p tcp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Это правило позволяет внутреннему трафику, связанному с установленными соединениями, проходить, что и решает вашу проблему.

Заключение

Ваш случай демонстрирует важность понимания взаимодействия между разными уровнями сети и программного обеспечения. Несмотря на корректные настройки и открытые порты, изголодавшаяся блокировка может оставить нас в недоумении. Использование правильных правил в iptables обеспечит стабильную работу прокси. В будущем рекомендуется также мониторить логи как Apache, так и Docker для быстрого выявления и устранения проблем.

Оцените материал
Добавить комментарий

Капча загружается...