Ответ @T0xicCode правильный, но я подумал, что расскажу подробнее, поскольку на самом деле мне потребовалось около 20 часов, чтобы наконец реализовать рабочее решение.
Если вы хотите запустить Nginx в собственном контейнере и использовать его в качестве обратного прокси для балансировки нагрузки нескольких приложений на одном экземпляре сервера, вам необходимо выполнить следующие шаги:
Свяжите свои контейнеры
Когда вы используете docker run
свои контейнеры, обычно путем ввода сценария оболочки User Data
, вы можете объявлять ссылки на любые другие запущенные контейнеры. Это означает, что вам нужно запускать свои контейнеры по порядку, и только последние контейнеры могут связываться с первыми. Вот так:
#!/bin/bash
sudo docker run -p 3000:3000 --name API mydockerhub/api
sudo docker run -p 3001:3001 --link API:API --name App mydockerhub/app
sudo docker run -p 80:80 -p 443:443 --link API:API --link App:App --name Nginx mydockerhub/nginx
Таким образом , в этом примере, API
контейнер не связан ни с какими другими, но
App
контейнер связан API
и Nginx
связан с как API
и App
.
Результатом этого является изменения в env
Варс и /etc/hosts
файлы , которые находятся в пределах API
и App
контейнеров. Результаты выглядят так:
/ etc / hosts
Запуск cat /etc/hosts
в вашем Nginx
контейнере приведет к следующему:
172.17.0.5 0fd9a40ab5ec
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 App
172.17.0.2 API
ENV Vars
Запуск env
в вашем Nginx
контейнере приведет к следующему:
API_PORT=tcp://172.17.0.2:3000
API_PORT_3000_TCP_PROTO=tcp
API_PORT_3000_TCP_PORT=3000
API_PORT_3000_TCP_ADDR=172.17.0.2
APP_PORT=tcp://172.17.0.3:3001
APP_PORT_3001_TCP_PROTO=tcp
APP_PORT_3001_TCP_PORT=3001
APP_PORT_3001_TCP_ADDR=172.17.0.3
Я усек многие фактические вары, но это ключевые значения, необходимые для прокси-трафика в ваши контейнеры.
Чтобы получить оболочку для выполнения вышеуказанных команд в работающем контейнере, используйте следующее:
sudo docker exec -i -t Nginx bash
Вы можете видеть, что теперь у вас есть как /etc/hosts
записи файлов, так и env
вары, содержащие локальный IP-адрес для любого из связанных контейнеров. Насколько я могу судить, это все, что происходит, когда вы запускаете контейнеры с объявленными параметрами ссылки. Но теперь вы можете использовать эту информацию для настройки nginx
в своем Nginx
контейнере.
Настройка Nginx
Здесь все становится немного сложнее, и есть несколько вариантов. Вы можете настроить свои сайты так, чтобы они указывали на запись в созданном /etc/hosts
файле docker
, или вы можете использовать ENV
vars и запустить замену строки (я использовал sed
) в вашем nginx.conf
и любых других файлах conf, которые могут быть в вашей /etc/nginx/sites-enabled
папке, чтобы вставить IP ценности.
ВАРИАНТ А. Настройка Nginx с использованием переменных ENV
Это вариант, который я выбрал, потому что я не мог заставить
/etc/hosts
работать параметр файла. Вскоре я попробую вариант Б и дополню этот пост любыми выводами.
Ключевое различие между этой опцией и использованием /etc/hosts
опции файла заключается в том, как вы пишете, Dockerfile
чтобы использовать сценарий оболочки в качестве CMD
аргумента, который, в свою очередь, обрабатывает замену строки для копирования значений IP ENV
в ваш файл (ы) conf.
Вот набор файлов конфигурации, которые у меня остались:
Dockerfile
FROM ubuntu:14.04
MAINTAINER Your Name <you@myapp.com>
RUN apt-get update && apt-get install -y nano htop git nginx
ADD nginx.conf /etc/nginx/nginx.conf
ADD api.myapp.conf /etc/nginx/sites-enabled/api.myapp.conf
ADD app.myapp.conf /etc/nginx/sites-enabled/app.myapp.conf
ADD Nginx-Startup.sh /etc/nginx/Nginx-Startup.sh
EXPOSE 80 443
CMD ["/bin/bash","/etc/nginx/Nginx-Startup.sh"]
nginx.conf
daemon off;
user www-data;
pid /var/run/nginx.pid;
worker_processes 1;
events {
worker_connections 1024;
}
http {
# Basic Settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 33;
types_hash_max_size 2048;
server_tokens off;
server_names_hash_bucket_size 64;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging Settings
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Gzip Settings
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 3;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/xml text/css application/x-javascript application/json;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
# Virtual Host Configs
include /etc/nginx/sites-enabled/*;
# Error Page Config
#error_page 403 404 500 502 /srv/Splash;
}
ПРИМЕЧАНИЕ. Важно включить его daemon off;
в nginx.conf
файл, чтобы убедиться, что ваш контейнер не выйдет сразу после запуска.
api.myapp.conf
upstream api_upstream{
server APP_IP:3000;
}
server {
listen 80;
server_name api.myapp.com;
return 301 https://api.myapp.com/$request_uri;
}
server {
listen 443;
server_name api.myapp.com;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_pass http://api_upstream;
}
}
Nginx-Startup.sh
#!/bin/bash
sed -i 's/APP_IP/'"$API_PORT_3000_TCP_ADDR"'/g' /etc/nginx/sites-enabled/api.myapp.com
sed -i 's/APP_IP/'"$APP_PORT_3001_TCP_ADDR"'/g' /etc/nginx/sites-enabled/app.myapp.com
service nginx start
Я оставлю вам делать домашнюю работу по большей части содержимого nginx.conf
и api.myapp.conf
.
Магия происходит в Nginx-Startup.sh
которой мы используем , sed
чтобы сделать замену строки на APP_IP
заполнитель , который мы написали в upstream
блок наших api.myapp.conf
и app.myapp.conf
файлов.
Этот вопрос на ask.ubuntu.com очень хорошо объясняет:
поиск и замена текста в файле с помощью команд
GOTCHA
В OSX sed
параметры обрабатываются по-другому, особенно -i
флаг. В Ubuntu -i
флаг будет обрабатывать замену «на месте»; он откроет файл, изменит текст, а затем «сохранит» тот же файл. В OSX для -i
флага требуется расширение файла, который должен иметь полученный файл. Если вы работаете с файлом без расширения, вы должны ввести '' в качестве значения -i
флага.
GOTCHA
Чтобы использовать переменные ENV в регулярном выражении, которое sed
используется для поиска строки, которую вы хотите заменить, вам необходимо заключить переменную в двойные кавычки. Таким образом, правильный, хотя и нечеткий синтаксис такой, как указано выше.
Итак, докер запустил наш контейнер и запустил Nginx-Startup.sh
скрипт для запуска, который использовался sed
для изменения значения APP_IP
соответствующей ENV
переменной, которую мы указали в sed
команде. Теперь у нас есть файлы conf в нашем /etc/nginx/sites-enabled
каталоге, которые имеют IP-адреса из ENV
переменных, которые докер установил при запуске контейнера. В вашем api.myapp.conf
файле вы увидите, что upstream
блок изменился на этот:
upstream api_upstream{
server 172.0.0.2:3000;
}
Видимый вами IP-адрес может быть другим, но я заметил, что это обычно 172.0.0.x
.
Теперь у вас должна быть правильная маршрутизация.
GOTCHA
Вы не можете перезапустить / повторно запустить какие-либо контейнеры после запуска первого экземпляра. Docker предоставляет каждому контейнеру новый IP-адрес при запуске и, похоже, не использует повторно тот, который использовался ранее. Таким api.myapp.com
образом, в первый раз будет получено 172.0.0.2, а в следующий раз - 172.0.0.4. Но Nginx
он уже установил первый IP-адрес в своих файлах conf или в своем /etc/hosts
файле, поэтому он не сможет определить новый IP-адрес для api.myapp.com
. Решение этой проблемы, скорее всего, будет использовать CoreOS
и его etcd
сервис, который, в моем ограниченном понимании, действует как общий ENV
для всех машин, зарегистрированных в одном CoreOS
кластере. Это следующая игрушка, с которой я собираюсь поиграться.
ВАРИАНТ Б: Использование /etc/hosts
файловых записей
Это должен быть более быстрый и простой способ сделать это, но я не мог заставить его работать. Якобы вы просто ввести значение /etc/hosts
вступления в ваших api.myapp.conf
и app.myapp.conf
файлов, но я не мог получить этот метод работы.
ОБНОВЛЕНИЕ:
см. Ответ @Wes Tod, чтобы узнать, как заставить этот метод работать.
Вот попытка, которую я предпринял api.myapp.conf
:
upstream api_upstream{
server API:3000;
}
Учитывая, что в моем /etc/hosts
файле есть такая запись : 172.0.0.2 API
я подумал, что она просто получит значение, но, похоже, это не так.
У меня также была пара дополнительных проблем с моими Elastic Load Balancer
источниками из всех АЗ, так что это могло быть проблемой, когда я пробовал этот маршрут. Вместо этого мне пришлось научиться обрабатывать замену строк в Linux, так что это было весело. Я попробую через некоторое время и посмотрю, как это пойдет.