Как вылечить 503 Служба недоступна в Apache, работающем в контейнере Docker?

Я пытаюсь создать прокси-сервер виртуального хоста Apache в контейнере Docker (у меня Docker 1.6), поэтому я сделал следующее:

Сначала настройте два контейнера Docker, каждый из которых запускает собственное веб-приложение:

docker run -it -p 8001:80 -p 4431:443 --name build ubuntu:latest

apt-get update
apt-get install apache2 libapache2-mod-php -y
echo “<?php phpinfo(); ?>” >> /var/www/html/info.php
service apache2 restart

потом

docker run -it -p 8002:80 -p 4432:443 --name cicd ubuntu:latest

apt-get update
apt-get install apache2 libapache2-mod-php -y
echo “<?php phpinfo(); ?>” >> /var/www/html/info.php
service apache2 restart

Каждый из них отлично работает на своих соответствующих портах. Итак, затем я создаю контейнер с Apache:

docker run -it -p 8000:80 -p 4430:443 --name apache_proxy ubuntu:latest

apt-get update
apt-get install apache2 -y
a2enmod proxy
a2enmod proxy_http
service apache2 restart

Это отлично работает само по себе на порту 8000.

Затем я создал файл виртуального хоста для каждого из других контейнеров Docker:

<VirtualHost *:80>
    ServerName build.example.com
    <Proxy *>
        Allow from localhost
    </Proxy>
    ProxyPass / http://localhost:8001/
</VirtualHost>

и

<VirtualHost *:80>
    ServerName cicd.example.com
    <Proxy *>
        Allow from localhost
    </Proxy>
    ProxyPass / http://localhost:8002/
</VirtualHost>

Затем поместил оба в /etc/apache2/sites-available/ контейнера apache_proxy.

Теперь я вернулся в контейнер apache_proxy и выполнил следующее:

a2ensite build.example.conf
a2ensite cicd.example.conf
service apache2 restart

Запустив apachectl -S из командной строки контейнера apache_proxy, я вижу, что действует следующее:

VirtualHost configuration:
*:80 is a NameVirtualHost
     default server 172.17.0.17 (/etc/apache2/sites-enabled/000-default.conf:1)
     port 80 namevhost 172.17.0.17 (/etc/apache2/sites-enabled/000-default.conf:1)
     port 80 namevhost build.example.com (/etc/apache2/sites-enabled/build.example.conf:1)
     port 80 namevhost cicd.example.com (/etc/apache2/sites-enabled/cicd.example.conf:1)

Вот как выглядит установка: Пример виртуального хоста Docker

Я могу получить доступ к каждому отдельному контейнеру через соответствующий порт, и я должен иметь возможность перейти по следующим URL-адресам, чтобы перейти на соответствующие сайты:

build.example.com:8000 должен проксировать контейнер/веб-сайт через порт 8001 cicd.example.com:8000 должен проксировать контейнер/веб-сайт через порт 8002

Вместо этого я получаю следующую ошибку:

503 Сервис недоступен

Проверяю логи, получаю следующее:

[Mon Oct 16 21:17:32.510127 2017] [proxy:error] [pid 165:tid 140552167175936] (111)Connection refused: AH00957: HTTP: attempt to connect to 127.0.0.1:8001 (localhost) failed
[Mon Oct 16 21:17:32.510278 2017] [proxy:error] [pid 165:tid 140552167175936] AH00959: ap_proxy_connect_backend disabling worker for (localhost) for 0s
[Mon Oct 16 21:17:32.510302 2017] [proxy_http:error] [pid 165:tid 140552167175936] [client 172.26.16.120:61391] AH01114: HTTP: failed to make connection to backend: localhost
[Mon Oct 16 21:17:32.799053 2017] [proxy:error] [pid 166:tid 140552217532160] (111)Connection refused: AH00957: HTTP: attempt to connect to 127.0.0.1:8001 (localhost) failed
[Mon Oct 16 21:17:32.799232 2017] [proxy:error] [pid 166:tid 140552217532160] AH00959: ap_proxy_connect_backend disabling worker for (localhost) for 0s
[Mon Oct 16 21:17:32.799256 2017] [proxy_http:error] [pid 166:tid 140552217532160] [client 172.26.16.120:61392] AH01114: HTTP: failed to make connection to backend: localhost, referer: http://build.example.com:8000/info.php

Последние несколько часов я копался в кроличьих норах, пытаясь заставить это работать, и я уверен, что теперь мне не хватает чего-то довольно простого. Может ли кто-нибудь пролить свет на ошибочность моего пути?

ПРИМЕЧАНИЕ

Я следил за огромной кроличьей норой, касающейся SELinux, который не включен или даже не установлен в прокси-контейнере Ubuntu/Apache.

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

РЕДАКТИРОВАТЬ

Основываясь на предложениях, я пробовал следующее:

ProxyPass / http://cicd:80/ вызывает ошибку 502
ProxyPass / http://ip.address.of.server:8002/ время ожидания истекло
ProxyPass / http://ip.address.of.container:8002/ вызывает ошибку 503
ProxyPass / http://127.0.0.1:8002/ retry=0 вызывает ошибку 503 (предложено в других ответах)


person Jay Blanchard    schedule 16.10.2017    source источник
comment
ты пробовал echo net.ipv4.ip_forward=1?   -  person guido    schedule 17.10.2017
comment
Неважно, прочитал еще раз вашу настройку, и она вам не нужна; почему вы меняете прокси на localhost:8001? 8001 — это порт, экспортированный на хост, в то время как httpd работает в другом контейнере.   -  person guido    schedule 17.10.2017
comment
@ᴳᵁᴵᴰᴼ Да, 8001 доступен хосту для порта 80 внутри контейнера. Посмотрите на добавленную схему.   -  person Jay Blanchard    schedule 17.10.2017


Ответы (2)


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

  • сборка:80
  • код:80

Отразите это в своем прокси-сервере Apache, и все будет хорошо.

person β.εηοιτ.βε    schedule 16.10.2017
comment
Итак, я должен изменить ProxyPass на / http://build.example.com:8001 и / http://cicd.example.com:8002? - person Jay Blanchard; 17.10.2017
comment
скорее всего build:80 и cicd:80 - person guido; 17.10.2017
comment
@ᴳᵁᴵᴰᴼ правильно. Имена, которые вы даете контейнеру, в конечном итоге становятся именем хоста, известным в сети докеров между контейнерами. - person β.εηοιτ.βε; 17.10.2017
comment
Так что просто build:8001 и build:8002, потому что это порты. Они запускаются с -p 8001:80 и -p 8002:80 соответственно. - person Jay Blanchard; 17.10.2017
comment
Не могу проверить это сейчас, но я думаю, вы бы использовали порт 80, так как это порт, открытый в контейнере; не 80XX, который является портом, переадресованным на хост - person guido; 17.10.2017
comment
@JayBlanchard нет, порт перед точкой с запятой на самом деле является портом, открытым для вашего хоста, а не портом, доступным внутри сети. - person β.εηοιτ.βε; 17.10.2017
comment
Хорошо, позвольте мне попробовать это. Я не уверен, что у меня правильный синтаксис ProxyPass. Просто делаю ProxyPass / cicd:80 - person Jay Blanchard; 17.10.2017
comment
С ProxyPass / http://cicd:80/ я получаю в журнале следующее сообщение об ошибке 502: AH00898 DNS lookup failure for: cicd returned by info.php - person Jay Blanchard; 17.10.2017
comment
Сделал это @ᴳᵁᴵᴰᴼ Получается, что DNS не находит контейнер Docker на основе этого. :-/ Позвольте мне попробовать полное доменное имя. РЕДАКТИРОВАТЬ: это не работает. - person Jay Blanchard; 17.10.2017
comment
docs.docker.com/engine/userguide/networking/default_network/ Возможно, вам стоит перейти по ссылке. Или даже лучше, если ваши контейнеры предназначены для совместного существования, объедините их вместе с помощью docker-compose. - person β.εηοιτ.βε; 17.10.2017
comment
Один предназначен для использования в качестве прокси для двух полностью независимых микросервисов @b.enoit.be. Связывание не будет выполнять эту задачу. - person Jay Blanchard; 17.10.2017
comment
Посмотрите обновленный вопрос и диаграмму, чтобы понять, что я пытаюсь сделать. - person Jay Blanchard; 17.10.2017
comment
Ваш ответ в сочетании с другой информацией дал мне несколько хороших подсказок, что было не так. - person Jay Blanchard; 17.10.2017

Что мне действительно нужно помнить, так это то, что мы работаем в сети Docker, как только мы передаем запрос, поэтому использование таких вещей, как ProxyPass / http://localhost:8002/, не будет работать, потому что «localhost» принадлежит контейнеру Docker, в котором мы сделали запрос.

Итак, я начал искать, так сказать, за пределами окна ошибки и наткнулся на этот ответ Как мне подключиться к локальному хосту машины из контейнера Docker?

Я определил, что нам нужно передать запрос в сеть Docker. Чтобы получить эту информацию, я запустил sudo ip addr show docker0 из командной строки сервера, и он вернул:

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::5484:7aff:fefe:9799/64 scope link
       valid_lft forever preferred_lft forever

Показывается, что внутренняя сеть Docker находится на 172.17.42.1 Изменение прохода на ProxyPass / http://172.17.42.1:8002/ передает запрос в сеть Docker и впоследствии завершается успешно.

<VirtualHost *:80>
    ServerName cicd.example.com
    <Proxy *>
        #Allow from localhost
        Order deny,allow
        Allow from all
    </Proxy>
    ProxyPass / http://172.17.42.1:8002/ retry=0
</VirtualHost>
person Jay Blanchard    schedule 17.10.2017
comment
Хорошо, что вы нашли решение. Возможно, вы захотите исправить IP-адрес другого вашего контейнера (stackoverflow.com/questions/27937185/), поскольку IP-адрес вашего контейнера может меняться от одного запуска к другому. - person β.εηοιτ.βε; 17.10.2017
comment
Исправить IP другого контейнера? Извините, я не слежу за @b.enoit.be — вы имеете в виду build? Если это так, я сделал, просто показав один здесь, например. - person Jay Blanchard; 17.10.2017
comment
Во время выполнения контейнера вы можете указать IP-адрес, который он будет использовать, поэтому у вас не будет неожиданного «это был тот IP-адрес раньше, но теперь я перезапустил его, у него другой». Docker действует как DHCP и просто назначает IP-адрес вашим контейнерам. Таким образом, вы можете получить разные IP-адреса для одного и того же контейнера от одного запуска к другому. - person β.εηοιτ.βε; 17.10.2017
comment
Правильно - о да, в производственной настройке я удостоверяюсь, что IP-адреса назначены и «фиксированы» @b.enoit.be - person Jay Blanchard; 17.10.2017
comment
Я не уверен, что это то, что вы действительно хотите: с вашей текущей конфигурацией шаги, которые следуют после того, как вы откроете localhost:8080: 1. локальный сокет на 8080 подключен к порту 80 прокси-контейнера 2. прокси-контейнер обратно к хосту на порту 8001 (172.17.42.1 является шлюзом сети докеров, т.е. это тот же хост, что и локальный хост) 3. порт 8001 на хосте подключен к порту контейнера cicd 80 4. cicd обслуживает php-страницу. По сути, вы входите в, а прокси-сервер обращается к другому узлу _in_side через _out_side (сам хост). - person guido; 17.10.2017
comment
Учитывая это @ᴳᵁᴵᴰᴼ, что мне делать? - person Jay Blanchard; 17.10.2017
comment
Добавьте --link cicd:cicd в команду docker, запускающую обратный прокси; затем используйте ProxyPass / http://cicd:80/ на виртуальном хосте. Затем сделайте то же самое для другого. Вам вообще не нужно выставлять порты 800X в проксируемых контейнерах (если не для тестирования с браузером против них). Опять же, поскольку это не проверено, я не публикую ответ. - person guido; 18.10.2017