คำตอบของ @ T0xicCodeนั้นถูกต้อง แต่ฉันคิดว่าฉันจะขยายรายละเอียดเนื่องจากฉันใช้เวลาประมาณ 20 ชั่วโมงในที่สุดในการแก้ปัญหาที่ใช้งานได้
หากคุณต้องการเรียกใช้ Nginx ในคอนเทนเนอร์ของตัวเองและใช้เป็น reverse proxy เพื่อโหลดแอปพลิเคชันหลายตัวบนอินสแตนซ์เซิร์ฟเวอร์เดียวกันขั้นตอนที่คุณต้องปฏิบัติตามมีดังนี้:
เชื่อมโยงคอนเทนเนอร์ของคุณ
เมื่อคุณใช้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
และApp
container ผลลัพธ์มีลักษณะดังนี้:
/ 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
ฉันได้ตัด vars จริงหลายรายการออกไปแล้ว แต่ข้างต้นเป็นค่าหลักที่คุณต้องใช้ในการรับส่งข้อมูลพร็อกซีไปยังคอนเทนเนอร์ของคุณ
ในการรับเชลล์เพื่อรันคำสั่งข้างต้นภายในคอนเทนเนอร์ที่กำลังรันอยู่ให้ใช้สิ่งต่อไปนี้:
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 ค่า
ตัวเลือก A: กำหนดค่า Nginx โดยใช้ ENV Vars
นี่เป็นตัวเลือกที่ฉันใช้เพราะฉันไม่สามารถรับ
/etc/hosts
ตัวเลือกไฟล์ให้ทำงานได้ ฉันจะลองใช้ตัวเลือก B เร็วพอและอัปเดตโพสต์นี้พร้อมสิ่งที่ค้นพบ
ความแตกต่างที่สำคัญระหว่างอ็อพชันนี้และการใช้/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 ภายใน regex ที่sed
ใช้ค้นหาสตริงที่คุณต้องการแทนที่คุณต้องตัด var ภายในเครื่องหมายคำพูดคู่ ดังนั้นไวยากรณ์ที่ถูกต้องแม้ว่าจะดูว่องไว แต่ก็เป็นไปตามด้านบน
ดังนั้นนักเทียบท่าจึงได้เปิดใช้งานคอนเทนเนอร์ของเราและทริกเกอร์Nginx-Startup.sh
สคริปต์ให้ทำงานซึ่งใช้sed
เพื่อเปลี่ยนค่าAPP_IP
เป็นENV
ตัวแปรที่เกี่ยวข้องที่เราระบุไว้ในsed
คำสั่ง ตอนนี้เรามีไฟล์ conf ภายใน/etc/nginx/sites-enabled
ไดเร็กทอรีของเราซึ่งมีที่อยู่ IP จากENV
vars ที่ docker ตั้งไว้เมื่อเริ่มต้นคอนเทนเนอร์ ภายใน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
ไฟล์ของคุณอย่างชัดเจนแต่ฉันไม่สามารถใช้วิธีนี้ได้
UPDATE:
ดูคำตอบของ @Wes Todสำหรับคำแนะนำในการทำให้วิธีนี้ได้ผล
นี่คือความพยายามที่ฉันทำในapi.myapp.conf
:
upstream api_upstream{
server API:3000;
}
เมื่อพิจารณาว่ามีรายการใน/etc/hosts
ไฟล์ของฉันเป็นดังนี้: 172.0.0.2 API
ฉันคิดว่ามันจะดึงค่าเข้ามา แต่ดูเหมือนจะไม่เป็นเช่นนั้น
ฉันยังมีปัญหาเสริมอีกสองสามประการเกี่ยวกับการElastic Load Balancer
จัดหาจาก AZ ทั้งหมดซึ่งอาจเป็นปัญหาเมื่อฉันลองใช้เส้นทางนี้ แต่ฉันต้องเรียนรู้วิธีจัดการการเปลี่ยนสตริงใน Linux ดังนั้นมันจึงเป็นเรื่องสนุก เดี๋ยวจะลองดูว่าจะเป็นยังไง