Назначение vhosts для портов Docker
У меня настроен DNS-шаблон, чтобы все веб-запросы к настраиваемому домену (*.foo) отображались на IP-адрес хоста Docker. Если у меня несколько контейнеров с экземплярами Apache (или Nginx), каждый контейнер сопоставляет порт Apache (80) с каким-либо внешним входящим портом.
То, что я хотел бы сделать, это сделать запрос к контейнеру-1.foo, который уже сопоставлен с правильным IP-адресом (хостом Docker) через мой собственный DNS-сервер, но прокси-запрос по умолчанию 80-го запроса правильный внешний порт Docker, так что правильный экземпляр Apache из указанного контейнера может отвечать на основе настраиваемого домена. Аналогично, container-2.foo будет прокси-сервером для второго контейнера apache и т.д.
Есть ли предварительно построенное решение для этого, лучше всего запустить прокси-сервер Nginx на хосте Docker, или мне нужно написать прокси-сервер node.js с возможностью управления контейнерами Docker (запуск/остановка/reuild через Интернет), или...? Какие у меня варианты, которые будут использовать контейнеры Docker больше как естественное событие, а не что-то с посторонними портами и жонглированием контейнеров?
Ответы
Ответ 1
Этот ответ может быть немного запоздалым, но взгляните на изображение Joker Wilder nginx-proxy Docker. При запуске контейнера Docker этого изображения вы получаете сервер nginx, настроенный как обратный прокси для других контейнеров без поддержки конфигурации.
Просто запустите другие контейнеры с переменной среды VIRTUAL_HOST
, а nginx-proxy откроет свой ip: порт и обновит конфигурацию nginx для вас.
Предположим, что ваш DNS настроен так, что *.test.local
сопоставляется с IP-адресом вашего узла Docker, а затем просто запускайте следующие контейнеры, чтобы быстро запустить демонстрацию:
# start the reverse proxy
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy
# start a first container for http://tutum.test.local
docker run -d -e "VIRTUAL_HOST=tutum.test.local" tutum/hello-world
# start a second container for http://deis.test.local
docker run -d -e "VIRTUAL_HOST=deis.test.local" deis/helloworld
Ответ 2
Вот два возможных ответа: (1) установить порты непосредственно с Docker и использовать Nginx/Apache для прокси-сервера vhosts или (2) использовать Dokku для управления портами и vhosts для вас (так я научился делать метод 1).
Способ 1a (напрямую назначить порты с докером)
Шаг 1: Настройте nginx.conf или Apache на хосте с заданными номерами портов. Этот веб-сервер, работающий на хосте, будет выполнять проксирование vhost. Там нет ничего особенного в отношении Docker - это обычный хостинг vhost. На шаге 2 специальная часть появится, чтобы сделать Docker правильным номером порта хоста.
Шаг 2. Назначьте номера портов в Docker с помощью "-p" для установки сопоставлений портов Docker и "-e" для установки пользовательских переменных среды в Docker следующим образом:
port=12345 # <-- the vhost port setting used in nginx/apache
IMAGE=myapps/container-1
id=$(docker run -d -p :$port -e PORT=$port $IMAGE)
# -p :$port will establish a mapping of 12345->12345 from outside docker to
# inside of docker.
# Then, the application must observe the PORT environment variable
# to launch itself on that port; This is set by -e PORT=$port.
# Additional goodies:
echo $id # <-- the running id of your container
echo $id > /app/files/CONTAINER # <-- remember Docker id for this instance
docker ps # <-- check that the app is running
docker logs $id # <-- look at the output of the running instance
docker kill $id # <-- to kill the app
Способ 1b Порт жесткого кода
... если вы используете приложение с жестким кодом, например, порт 5000 (т.е. не может быть настроен через переменную окружения PORT, как в методе 1a), тогда он может быть жестко запрограммирован через Docker следующим образом:
publicPort=12345
id=$(docker run -d -p $publicPort:5000 $IMAGE)
# -p $publicPort:5000 will map port 12345 outside of Docker to port 5000 inside
# of Docker. Therefore, nginx/apache must be configured to vhost proxy to 12345,
# and the application within Docker must be listening on 5000.
Способ 2 (пусть Dokku выяснит порты)
В настоящий момент довольно хороший вариант для управления Docker vhosts - Dokku. Предстоящим вариантом может быть использование Flynn, но на данный момент Flynn только начинает работу и не совсем готов. Поэтому мы идем с Dokku: После выполнения инструкций по установке Dokku для одного домена включите vhosts, создав файл "VHOST":
echo yourdomain.com > /home/git/VHOST
# in your case: echo foo > /home/git/VHOST
Теперь, когда приложение передается через SSH на Dokku (см. Документы Dokku, как это сделать), Dokku будет смотреть файл VHOST и для конкретного приложения, нажатого (скажем, вы нажали "контейнер-1" ) он сгенерирует следующий файл:
/home/git/container-1/nginx.conf
И он будет иметь следующее содержимое:
upstream container-1 { server 127.0.0.1:49162; }
server {
listen 80;
server_name container-1.yourdomain.com;
location / {
proxy_pass http://container-1;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
Когда сервер перезагружается, Dokku гарантирует, что Docker запустит приложение с портом, сопоставленным с его первоначально развернутым портом (49162 здесь), вместо того, чтобы случайно назначать другой порт. Для достижения этого детерминированного назначения Dokku сохраняет первоначально назначенный порт в /home/git/container-1/PORT
, а на следующем запуске он устанавливает среду PORT
к этому значению, а также сопоставляет назначения порта Docker этим портом как на стороне хоста, так и на приложение на стороне. Это противоречит первому запуску, когда Dokku установит PORT=5000
, а затем выяснит, какой случайный порт Dokku отображает на стороне VPS 5000 на стороне приложения. Он вокруг (и может даже измениться в будущем), но он работает!
Как работает VHOST, под капотом: при выполнении git нажатия приложения через SSH, Dokku выполнит перехваты, которые живут в /var/lib/dokku/plugins/nginx-vhosts
. Эти крючки также находятся в исходном коде Dokku здесь и отвечают за запись файлов nginx.conf
с правильными настройками vhost. Если у вас нет этого каталога в /var/lib/dokku
, попробуйте запустить dokku plugins-install
.
Ответ 3
С докере вы хотите, чтобы внутренние ips оставались нормальными (например, 80) и выясняли, как подключить случайные порты.
Один из способов обращения с ними - с обратным прокси-сервером, таким как hipache. Направьте свои DNS на него, а затем вы можете перенастроить прокси-сервер, когда ваши контейнеры появятся вверх и вниз. Посмотрите http://txt.fliglio.com/2013/09/protyping-web-stuff-with-docker/, чтобы увидеть, как это может работать.
Если вы ищете что-то более надежное, вы можете взглянуть на "обнаружение службы". (посмотрите на обнаружение службы с помощью докера: http://txt.fliglio.com/2013/12/service-discovery-with-docker-docker-links-and-beyond/)