Відповідь @ 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.
Результатом цього є зміни до файлів envvars та /etc/hostsфайлів, що знаходяться в контейнерах APIand 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, або ви можете використовувати ENVvars та запустити заміну рядка (я використовував sed) на вашому nginx.confта будь-яких інших конфігураційних файлах, які можуть бути у вашій /etc/nginx/sites-enabledпапці, щоб вставити IP значення.
ВАРІАНТ A: Налаштуйте Nginx, використовуючи ENV Vars
Це варіант, з яким я пішов, оскільки не зміг змусити
/etc/hostsфайл працювати. Я спробую варіант В досить скоро і оновлю цю публікацію з будь-якими висновками.
Ключова різниця між цією опцією та опцією /etc/hostsфайлу полягає в тому, як ви пишете свій Dockerfileсценарій оболонки як CMDаргумент, який, у свою чергу, обробляє заміну рядка для копіювання значень IP ENVу ваші файли конф.
Ось набір файлів конфігурації, з якими я опинився:
Докерфайл
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 vars у регулярному виразі, який sedвикористовує для пошуку рядка, який потрібно замінити, потрібно обернути var у подвійні лапки. Тож правильний, хоч і хиткий на вигляд, синтаксис такий, як вище.
Отже, докер запустив наш контейнер і запустив Nginx-Startup.shсценарій для запуску, який використав sedдля зміни значення APP_IPна відповідну ENVзмінну, яку ми вказали в sedкоманді. Тепер у нашому /etc/nginx/sites-enabledкаталозі є файли конф., Які мають IP-адреси з файлів ENVvars, встановлених при запуску контейнера. У вашому 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кластері. Це наступна іграшка, в яку я збираюся пограти.
ВАРІАНТ B: Використовуйте /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джерелами з усіх AZ, так що, можливо, це було проблемою, коли я пробував цей маршрут. Натомість мені довелося навчитися керувати заміною рядків у Linux, так що це було цікаво. Я спробую це через деякий час і подивлюсь, як це буде.