Câu trả lời của @ T0xicCode là đúng, nhưng tôi nghĩ rằng tôi sẽ mở rộng chi tiết vì thực sự tôi mất khoảng 20 giờ để cuối cùng có được một giải pháp hoạt động.
Nếu bạn đang tìm cách chạy Nginx trong vùng chứa của riêng nó và sử dụng nó làm proxy ngược để cân bằng tải nhiều ứng dụng trên cùng một phiên bản máy chủ thì các bước bạn cần làm như sau:
Liên kết các vùng chứa của bạn
Khi bạn docker run
các vùng chứa của bạn, thường bằng cách nhập một tập lệnh shell vào User Data
, bạn có thể khai báo các liên kết đến bất kỳ vùng chứa nào đang chạy khác . Điều này có nghĩa là bạn cần khởi động các vùng chứa của mình theo thứ tự và chỉ những vùng chứa sau mới có thể liên kết với những vùng chứa trước đó. Như vậy:
#!/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
Vì vậy, trong ví dụ này, vùng API
chứa không được liên kết với bất kỳ người nào khác, nhưng vùng
App
chứa được liên kết với API
và Nginx
được liên kết với cả API
và App
.
Kết quả của việc này là các thay đổi đối với các env
vars và các /etc/hosts
tệp nằm trong vùng chứa API
và App
. Kết quả trông như vậy:
/ etc / hosts
Chạy cat /etc/hosts
trong vùng Nginx
chứa của bạn sẽ tạo ra những thứ sau:
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
Chạy env
trong vùng Nginx
chứa của bạn sẽ tạo ra những thứ sau:
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
Tôi đã cắt ngắn nhiều vars thực tế, nhưng ở trên là các giá trị chính mà bạn cần để ủy quyền lưu lượng truy cập vào vùng chứa của mình.
Để có được một trình bao để chạy các lệnh trên trong một vùng chứa đang chạy, hãy sử dụng như sau:
sudo docker exec -i -t Nginx bash
Bạn có thể thấy rằng bây giờ bạn có cả /etc/hosts
mục nhập tệp và env
vars chứa địa chỉ IP cục bộ cho bất kỳ vùng chứa nào được liên kết. Theo như tôi có thể nói, đây là tất cả những gì xảy ra khi bạn chạy các vùng chứa với các tùy chọn liên kết được khai báo. Nhưng bây giờ bạn có thể sử dụng thông tin này để định cấu hình nginx
trong vùng Nginx
chứa của mình .
Định cấu hình Nginx
Đây là nơi mà nó có một chút khó khăn và có một vài lựa chọn. Bạn có thể chọn định cấu hình các trang web của mình để trỏ đến một mục nhập trong /etc/hosts
tệp đã docker
tạo hoặc bạn có thể sử dụng các ENV
vars và chạy chuỗi thay thế (tôi đã sử dụng sed
) trên nginx.conf
tệp conf của bạn và bất kỳ tệp nào khác có thể nằm trong /etc/nginx/sites-enabled
thư mục của bạn để chèn IP các giá trị.
TÙY CHỌN A: Định cấu hình Nginx bằng ENV Vars
Đây là tùy chọn mà tôi đã sử dụng vì tôi không thể làm cho
/etc/hosts
tùy chọn tệp hoạt động. Tôi sẽ sớm thử Tùy chọn B và cập nhật bài đăng này với bất kỳ phát hiện nào.
Sự khác biệt chính giữa tùy chọn này và sử dụng /etc/hosts
tùy chọn tệp là cách bạn viết Dockerfile
để sử dụng tập lệnh shell làm CMD
đối số, từ đó xử lý việc thay thế chuỗi để sao chép các giá trị IP từ ENV
(các) tệp conf của bạn.
Đây là tập hợp các tệp cấu hình mà tôi đã kết thúc:
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;
}
LƯU Ý: Điều quan trọng là phải đưa daemon off;
vào nginx.conf
tệp của bạn để đảm bảo rằng vùng chứa của bạn không thoát ngay sau khi khởi chạy.
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
Tôi sẽ để bạn làm bài tập về hầu hết các nội dung của nginx.conf
và api.myapp.conf
.
Điều kỳ diệu xảy ra trong Nginx-Startup.sh
nơi chúng tôi sử dụng sed
để thay thế chuỗi trên APP_IP
trình giữ chỗ mà chúng tôi đã ghi vào upstream
khối tệp api.myapp.conf
và app.myapp.conf
tệp của chúng tôi .
Câu hỏi ask.ubuntu.com này giải thích nó rất hay:
Tìm và thay thế văn bản trong tệp bằng lệnh
GOTCHA
Trên OSX, sed
xử lý các tùy chọn khác nhau, -i
cờ cụ thể. Trên Ubuntu, -i
cờ sẽ xử lý thay thế 'tại chỗ'; nó sẽ mở tệp, thay đổi văn bản và sau đó 'lưu trên' cùng một tệp. Trên OSX, -i
cờ yêu cầu phần mở rộng tệp mà bạn muốn tệp kết quả có. Nếu bạn đang làm việc với tệp không có phần mở rộng, bạn phải nhập '' làm giá trị cho -i
cờ.
GOTCHA
Để sử dụng các ENV vars trong regex sed
dùng để tìm chuỗi bạn muốn thay thế, bạn cần đặt var trong dấu ngoặc kép. Vì vậy, cú pháp chính xác, mặc dù trông có vẻ khó hiểu, là như trên.
Do đó, docker đã khởi chạy vùng chứa của chúng tôi và kích hoạt Nginx-Startup.sh
tập lệnh chạy, tập lệnh này được sử dụng sed
để thay đổi giá trị APP_IP
thành ENV
biến tương ứng mà chúng tôi đã cung cấp trong sed
lệnh. Bây giờ chúng tôi có các tệp conf trong /etc/nginx/sites-enabled
thư mục của chúng tôi có địa chỉ IP từ các ENV
vars mà docker đặt khi khởi động vùng chứa. Trong api.myapp.conf
tệp của bạn, bạn sẽ thấy upstream
khối đã được thay đổi thành:
upstream api_upstream{
server 172.0.0.2:3000;
}
Địa chỉ IP bạn thấy có thể khác, nhưng tôi nhận thấy rằng đó là địa chỉ thường 172.0.0.x
.
Bây giờ bạn sẽ có mọi thứ định tuyến thích hợp.
GOTCHA
Bạn không thể khởi động lại / chạy lại bất kỳ vùng chứa nào khi bạn đã chạy khởi chạy phiên bản đầu tiên. Docker cung cấp cho mỗi vùng chứa một IP mới khi khởi chạy và dường như không sử dụng lại bất kỳ IP nào mà nó đã sử dụng trước đây. Vì vậy, api.myapp.com
sẽ nhận được 172.0.0.2 trong lần đầu tiên, nhưng sau đó nhận được 172.0.0.4 vào lần tiếp theo. Nhưng Nginx
sẽ đã đặt IP đầu tiên vào các tệp conf của nó hoặc trong /etc/hosts
tệp của nó , vì vậy nó sẽ không thể xác định IP mới cho api.myapp.com
. Giải pháp cho điều này có khả năng sử dụng CoreOS
và etcd
dịch vụ của nó , theo sự hiểu biết hạn chế của tôi, hoạt động giống như một dịch vụ dùng chung ENV
cho tất cả các máy được đăng ký vào cùng một CoreOS
cụm. Đây là món đồ chơi tiếp theo mà tôi sẽ chơi với việc sắp đặt.
LỰA CHỌN B: Sử dụng mục nhập /etc/hosts
tệp
Đây hẳn là cách nhanh hơn, dễ dàng hơn để làm điều này, nhưng tôi không thể làm cho nó hoạt động. Rõ ràng là bạn chỉ cần nhập giá trị của /etc/hosts
mục nhập vào tệp api.myapp.conf
và của bạn app.myapp.conf
, nhưng tôi không thể làm cho phương pháp này hoạt động.
CẬP NHẬT:
Xem câu trả lời của @Wes Tod để biết hướng dẫn về cách làm cho phương pháp này hoạt động.
Đây là nỗ lực mà tôi đã thực hiện api.myapp.conf
:
upstream api_upstream{
server API:3000;
}
Xem xét rằng có một mục nhập trong /etc/hosts
tệp của tôi như vậy: 172.0.0.2 API
Tôi đã nghĩ rằng nó sẽ chỉ kéo giá trị vào, nhưng dường như không phải vậy.
Tôi cũng gặp một số vấn đề phụ trợ với việc Elastic Load Balancer
tìm nguồn cung ứng của tôi từ tất cả các AZ nên đó có thể là vấn đề khi tôi thử con đường này. Thay vào đó, tôi phải học cách xử lý việc thay thế các chuỗi trong Linux, điều đó thật thú vị. Tôi sẽ thử cái này trong một thời gian và xem nó diễn ra như thế nào.