Назначение 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/)