Відповідь @ 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
vars та /etc/hosts
файлів, що знаходяться в контейнерах API
and 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
та будь-яких інших конфігураційних файлах, які можуть бути у вашій /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-адреси з файлів ENV
vars, встановлених при запуску контейнера. У вашому 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, так що це було цікаво. Я спробую це через деякий час і подивлюсь, як це буде.