Gán vhosts cho các cổng Docker


83

Tôi đã thiết lập DNS ký tự đại diện để tất cả các yêu cầu web đến miền tùy chỉnh (* .foo) ánh xạ tới địa chỉ IP của máy chủ lưu trữ Docker. Nếu tôi có nhiều vùng chứa đang chạy các phiên bản Apache (hoặc Nginx), mỗi vùng chứa sẽ ánh xạ cổng Apache (80) tới một số cổng đến bên ngoài.

Những gì tôi muốn làm là thực hiện một yêu cầu tới container-1.foo, địa chỉ này đã được ánh xạ tới địa chỉ IP chính xác (của máy chủ Docker) thông qua máy chủ DNS tùy chỉnh của tôi, nhưng ủy quyền yêu cầu cổng mặc định 80 tới đúng Docker bên ngoài cổng sao cho phiên bản Apache chính xác từ vùng chứa được chỉ định có thể phản hồi dựa trên miền tùy chỉnh. Tương tự như vậy, container-2.foo sẽ ủy quyền cho apache của vùng chứa thứ hai, v.v.

Có giải pháp nào được tạo sẵn cho việc này không, tốt nhất là tôi nên chạy proxy Nginx trên máy chủ Docker hay tôi nên viết proxy node.js với khả năng quản lý vùng chứa Docker (bắt đầu / dừng / tái hợp qua web ), hoặc là...? Tôi có những lựa chọn nào để làm cho việc sử dụng các container Docker giống như một sự kiện tự nhiên hơn chứ không phải là một thứ gì đó với các cổng không liên quan và việc tung hứng container?


Tôi cũng có câu hỏi này - theo như tôi có thể nói, chạy từng ứng dụng trong vùng chứa Docker và sau đó thực hiện định tuyến tại máy chủ lưu trữ bằng máy chủ nginx (có lẽ trong vùng chứa của chính nó) là cách để làm điều đó. Tôi đang tự hỏi liệu mình nên chạy máy chủ ứng dụng độc lập (tức là hiển thị máy chủ php-fpm, puma, v.v.) hay bao gồm cả phiên bản nginx (vô nghĩa?).
Ross

Hãy xem github.com/dotcloud/hipache , đây là một proxy ngược có thể định cấu hình thông qua redis.
ZeissS

Câu trả lời:


81

Câu trả lời này có thể hơi muộn, nhưng những gì bạn cần là một proxy ngược tự động. Tôi đã sử dụng hai giải pháp cho điều đó:

  • jwilder / nginx-proxy
  • Traefik

Với thời gian, sở thích của tôi là sử dụng Traefik. Chủ yếu là vì nó được ghi chép và bảo trì tốt, đồng thời đi kèm với nhiều tính năng hơn (cân bằng tải với các chiến lược và ưu tiên khác nhau, kiểm tra sức khỏe, ngắt mạch, chứng chỉ SSL tự động với ACME / Let's Encrypt, ...).


Sử dụng jwilder / nginx-proxy

Khi chạy hình ảnh Docker nginx-proxy vùng chứa Docker của Jason Wilder , bạn nhận được một máy chủ nginx được thiết lập làm proxy ngược cho các vùng chứa khác của bạn mà không cần cấu hình để duy trì.

Chỉ cần chạy các vùng chứa khác của bạn với VIRTUAL_HOSTbiến môi trường và nginx-proxy sẽ phát hiện ra ip: port của chúng và cập nhật cấu hình nginx cho bạn.

Giả sử DNS của bạn được thiết lập để *.test.localánh xạ tới địa chỉ IP của máy chủ lưu trữ Docker của bạn, sau đó chỉ cần khởi động các vùng chứa sau để chạy bản demo nhanh:

# start the reverse proxy
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy

# start a first container for http://tutum.test.local
docker run -d -e "VIRTUAL_HOST=tutum.test.local" tutum/hello-world

# start a second container for http://deis.test.local
docker run -d -e "VIRTUAL_HOST=deis.test.local" deis/helloworld

Sử dụng Traefik

Khi chạy vùng chứa Traefik , bạn sẽ được thiết lập máy chủ proxy ngược, máy chủ này sẽ định cấu hình lại các quy tắc chuyển tiếp của nó với các nhãn docker được tìm thấy trên vùng chứa của bạn.

Giả sử DNS của bạn được thiết lập để *.test.localánh xạ tới địa chỉ IP của máy chủ lưu trữ Docker của bạn, sau đó chỉ cần khởi động các vùng chứa sau để chạy bản demo nhanh:

# start the reverse proxy
docker run --rm -it -p 80:80 -v /var/run/docker.sock:/var/run/docker.sock traefik:1.7 --docker

# start a first container for http://tutum.test.local
docker run -d -l "traefik.frontend.rule=Host:tutum.test.local" tutum/hello-world

# start a second container for http://deis.test.local
docker run -d -l "traefik.frontend.rule=Host:deis.test.local" deis/helloworld

-v /var/run/docker.sock:/tmp/docker.sockNó là giải pháp nguy hiểm? Vùng chứa proxy nginx này có quyền truy cập vào daemon máy chủ docker? Đây có thể là lỗ hổng bảo mật?
Mikl

có khả năng. Cũng lưu ý rằng việc không chia sẻ /var/run/docker.sockcũng không phải là một bảo đảm rằng máy chủ docker không thể được khai thác từ vùng chứa. Bảo mật Docker là một chủ đề riêng của nó.
Thomasleveil

Có bất kỳ vấn đề bảo mật đã biết nào không? Khi bạn có thể tiếp cận máy chủ docker từ vùng chứa.
Mikl

Trước đây đã có một lần khai thác và sự cố hiện đã được khắc phục nhưng có thể tìm thấy các lần khai thác mới trong tương lai. Docker không phải là về việc thêm an ninh, đó là về dễ triển khai
Thomasleveil

5
Bạn cũng có thể chạy nginx-proxy và docker-gen riêng biệt để ổ cắm docker không được gắn trên vùng chứa nginx.
Jason Wilder

42

Đây là hai câu trả lời có thể có: (1) thiết lập các cổng trực tiếp với Docker và sử dụng Nginx / Apache để ủy quyền cho các vhosts hoặc (2) sử dụng Dokku để quản lý các cổng và vhosts cho bạn (đó là cách tôi đã học cách làm Phương pháp 1).

Phương pháp 1a (chỉ định trực tiếp các cổng với docker)

Bước 1: Thiết lập nginx.conf hoặc Apache trên máy chủ, với việc gán số cổng mong muốn. Máy chủ web này, chạy trên máy chủ lưu trữ, sẽ thực hiện ủy quyền vhost. Không có gì đặc biệt về điều này đối với Docker - nó là dịch vụ lưu trữ vhost bình thường. Phần đặc biệt xuất hiện tiếp theo, trong Bước 2, để làm cho Docker sử dụng số cổng máy chủ chính xác.

Bước 2: Buộc gán số cổng trong Docker bằng "-p" để đặt ánh xạ cổng của Docker và "-e" để đặt các biến môi trường tùy chỉnh trong Docker, như sau:

port=12345 # <-- the vhost port setting used in nginx/apache
IMAGE=myapps/container-1
id=$(docker run -d -p :$port -e PORT=$port $IMAGE)
# -p :$port will establish a mapping of 12345->12345 from outside docker to
# inside of docker.
# Then, the application must observe the PORT environment variable
# to launch itself on that port; This is set by -e PORT=$port.

# Additional goodies:
echo $id # <-- the running id of your container
echo $id > /app/files/CONTAINER # <-- remember Docker id for this instance
docker ps # <-- check that the app is running
docker logs $id # <-- look at the output of the running instance
docker kill $id # <-- to kill the app

Phương pháp 1b Cổng ứng dụng được mã hóa cứng

... nếu ứng dụng của bạn sử dụng cổng được mã hóa cứng, ví dụ như cổng 5000 (tức là không thể định cấu hình thông qua biến môi trường PORT, như trong Phương pháp 1a), thì nó có thể được mã hóa cứng thông qua Docker như thế này:

publicPort=12345
id=$(docker run -d -p $publicPort:5000 $IMAGE)
# -p $publicPort:5000 will map port 12345 outside of Docker to port 5000 inside
# of Docker. Therefore, nginx/apache must be configured to vhost proxy to 12345,
# and the application within Docker must be listening on 5000.

Phương pháp 2 (để Dokku tìm ra các cổng)

Hiện tại, một lựa chọn khá tốt để quản lý vhosts Docker là Dokku . Một lựa chọn sắp tới có thể là sử dụng Flynn , nhưng hiện tại Flynn chỉ mới bắt đầu và chưa sẵn sàng. Do đó, chúng tôi sẽ sử dụng Dokku ngay bây giờ: Sau khi làm theo hướng dẫn cài đặt Dokku, đối với một miền, hãy bật vhosts bằng cách tạo tệp "VHOST":

echo yourdomain.com > /home/git/VHOST
# in your case: echo foo > /home/git/VHOST

Bây giờ, khi một ứng dụng được đẩy qua SSH đến Dokku (xem tài liệu Dokku để biết cách thực hiện việc này), Dokku sẽ xem xét tệp VHOST và đối với ứng dụng cụ thể được đẩy (giả sử bạn đã đẩy "container-1"), nó sẽ tạo tệp sau:

/home/git/container-1/nginx.conf

Và nó sẽ có các nội dung sau:

upstream container-1 { server 127.0.0.1:49162; }
server {
  listen      80;
  server_name container-1.yourdomain.com;
  location    / {
    proxy_pass  http://container-1;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

Khi máy chủ được khởi động lại, Dokku sẽ đảm bảo rằng Docker khởi động ứng dụng với cổng được ánh xạ tới cổng được triển khai ban đầu của nó (49162 ở đây), thay vì được gán ngẫu nhiên một cổng khác. Để đạt được chỉ định xác định này, Dokku lưu cổng được chỉ định ban đầu vào /home/git/container-1/PORTvà trong lần khởi chạy tiếp theo, nó đặt PORTmôi trường thành giá trị này và cũng ánh xạ các nhiệm vụ cổng của Docker thành cổng này ở cả phía máy chủ và phía ứng dụng. Điều này trái ngược với lần khởi chạy đầu tiên, khi Dokku sẽ thiết lập PORT=5000và sau đó tìm ra bất kỳ cổng ngẫu nhiên nào mà Dokku ánh xạ ở phía VPS thành 5000 trên phía ứng dụng. Đó là khoảng thời gian (và thậm chí có thể thay đổi trong tương lai), nhưng nó hoạt động!

Cách thức hoạt động của VHOST là: khi thực hiện thao tác đẩy ứng dụng qua SSH, Dokku sẽ thực thi các hook nằm trong đó /var/lib/dokku/plugins/nginx-vhosts. Các hook này cũng nằm trong mã nguồn Dokku ở đây và chịu trách nhiệm ghi các nginx.conftệp với cài đặt vhost chính xác. Nếu bạn không có thư mục này /var/lib/dokku, hãy thử chạy dokku plugins-install.


3

Với docker, bạn muốn các ips bên trong vẫn bình thường (ví dụ: 80) và tìm cách kết nối các cổng ngẫu nhiên.

Một cách để xử lý chúng là sử dụng proxy ngược như hipache. Hướng dns của bạn vào nó và sau đó bạn có thể định cấu hình lại proxy khi các vùng chứa của bạn lên xuống. Hãy xem http://txt.fliglio.com/2013/09/protyping-web-stuff-with-docker/ để xem cách này có thể hoạt động như thế nào.

Nếu bạn đang tìm kiếm thứ gì đó mạnh mẽ hơn, bạn có thể muốn xem "khám phá dịch vụ". (xem khám phá dịch vụ với docker: http://txt.fliglio.com/2013/12/service-discovery-with-docker-docker-links-and-beyond/ )

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.