Docker 포트에 가상 호스트 할당


83

사용자 지정 도메인 (* .foo)에 대한 모든 웹 요청이 Docker 호스트의 IP 주소에 매핑되도록 와일드 카드 DNS가 설정되어 있습니다. Apache (또는 Nginx) 인스턴스를 실행하는 여러 컨테이너가있는 경우 각 컨테이너는 Apache 포트 (80)를 일부 외부 인바운드 포트에 매핑합니다.

내가 원하는 것은 내 사용자 지정 DNS 서버를 통해 이미 올바른 IP 주소 (Docker 호스트의)에 매핑 된 container-1.foo에 대한 요청을 만들고 기본 포트 80 요청을 올바른 Docker 외부에 프록시하는 것입니다. 지정된 컨테이너의 올바른 Apache 인스턴스가 사용자 지정 도메인을 기반으로 응답 할 수 있도록 포트. 마찬가지로 container-2.foo는 두 번째 컨테이너의 아파치로 프록시되는 식입니다.

이에 대한 사전 구축 된 솔루션이 있습니까, Docker 호스트에서 Nginx 프록시를 실행하는 것이 가장 좋은 방법입니까, 아니면 Docker 컨테이너를 관리 할 수있는 가능성이있는 node.js 프록시를 작성해야합니까 (웹을 통해 시작 / 중지 / 다시 시작해야 하는가). ) 또는 ...? Docker 컨테이너를 외부 포트 및 컨테이너 저글링이 아닌 자연스러운 이벤트처럼 사용할 수있는 옵션은 무엇입니까?


이 질문도 있습니다. 제가 말할 수있는 한 Docker 컨테이너에서 각 앱을 실행 한 다음 nginx 서버 (아마도 자체 컨테이너에서)를 사용하여 호스트에서 라우팅을 수행하는 것이 그 방법입니다. 앱 서버를 독립 실행 형으로 실행해야하는지 (예 : php-fpm, puma 등 서버 노출) 아니면 (무의미한?) nginx 인스턴스도 포함해야하는지 궁금합니다.
Ross

redis를 통해 구성 할 수있는 리버스 프록시 인 github.com/dotcloud/hipache를 살펴보세요 .
ZeissS

답변:


81

이 답변은 약간 늦을 수 있지만 필요한 것은 자동 리버스 프록시입니다. 이를 위해 두 가지 솔루션을 사용했습니다.

  • jwilder / nginx-proxy
  • Traefik

시간이 지남에 따라 Traefik을 사용하는 것을 선호합니다. 대부분 잘 문서화되고 유지 관리되고 더 많은 기능이 제공되기 때문입니다 (다양한 전략 및 우선 순위로로드 밸런싱, 상태 확인, 회로 차단기, ACME / Let 's Encrypt를 사용한 자동 SSL 인증서 등).


jwilder / nginx-proxy 사용

Docker 컨테이너 Jason Wilder의 nginx-proxy Docker image 를 실행할 때 유지 관리 할 구성없이 다른 컨테이너에 대한 역방향 프록시로 설정된 nginx 서버를 가져옵니다.

VIRTUAL_HOST환경 변수를 사용하여 다른 컨테이너를 실행하면 nginx-proxy가 해당 ip : port를 검색하고 nginx 구성을 업데이트합니다.

*.test.localDocker 호스트의 IP 주소에 매핑 되도록 DNS가 설정되었다고 가정 하고 다음 컨테이너를 시작하여 빠른 데모를 실행하십시오.

# 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

Traefik 사용

Traefik 컨테이너를 실행할 때 컨테이너에서 찾은 도커 레이블이 지정된 전달 규칙을 재구성하는 역방향 프록시 서버가 설정됩니다 .

*.test.localDocker 호스트의 IP 주소에 매핑 되도록 DNS가 설정되었다고 가정 하고 다음 컨테이너를 시작하여 빠른 데모를 실행하십시오.

# 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.sock위험한 해결책입니까? 이 nginx 프록시가 Docker 호스트 데몬에 액세스 할 수있는 컨테이너? 이것이 가능한 보안 허점 일 수 있습니까?
Mikl 2014

혹시. 또한 공유 /var/run/docker.sock하지 않는다고해서 Docker 호스트가 컨테이너에서 악용 될 수 없다는 보증도 아닙니다. Docker 보안은 그 자체로 주제입니다.
Thomasleveil 2014

알려진 보안 문제가 있습니까? 컨테이너에서 도커 호스트에 도달 할 수있는 경우.
Mikl 2014

과거에 익스플로잇이 존재했으며 이제 문제가 해결되었지만 향후 새로운 익스플로잇이 발견 될 수 있습니다. 고정 표시기가 보안을 추가하는 방법에 대한 것이 아니라, 배포의 용이성에 관한 것입니다
Thomasleveil

5
또한 nginx-proxy 및 docker-gen을 별도로 실행하여 docker 소켓이 nginx 컨테이너에 마운트되지 않도록 할 수 있습니다.
Jason Wilder 2014

42

가능한 대답은 다음 두 가지입니다. (1) Docker로 포트를 직접 설정하고 Nginx / Apache를 사용하여 가상 호스트를 프록시하거나 (2) Dokku 를 사용 하여 포트와 가상 호스트를 관리합니다 (이 방법 1을 수행하는 방법을 배웠습니다).

방법 1a (도커를 사용하여 직접 포트 할당)

1 단계 : 원하는 포트 번호를 할당하여 호스트에 nginx.conf 또는 Apache를 설정합니다. 호스트에서 실행되는이 웹 서버는 가상 호스트 프록시를 수행합니다. Docker와 관련하여 특별한 것은 없습니다. 일반적인 가상 호스트 호스팅입니다. 다음으로 2 단계에서는 Docker가 올바른 호스트 포트 번호를 사용하도록 특수 부분이 제공됩니다.

2 단계 : 다음과 같이 Docker의 포트 매핑을 설정하려면 "-p"를 사용하여 Docker에서 포트 번호를 할당하고 다음과 같이 Docker 내에서 사용자 지정 환경 변수를 설정하려면 "-e"를 사용합니다.

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

방법 1b 하드 코딩 된 애플리케이션 포트

... 애플리케이션이 하드 코딩 된 포트 (예 : 포트 5000)를 사용하는 경우 (즉, 방법 1a에서와 같이 PORT 환경 변수를 통해 구성 할 수 없음) 다음과 같이 Docker를 통해 하드 코딩 할 수 있습니다.

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.

방법 2 (Dokku가 포트를 알아 내도록 함)

현재 Docker 가상 호스트를 관리하기위한 꽤 좋은 옵션은 Dokku 입니다. 다가오는 옵션은 Flynn 을 사용하는 것일 수 있지만 현재 Flynn은 시작 단계에 있으며 아직 준비가되지 않았습니다. 따라서 지금은 Dokku를 사용합니다. Dokku 설치 지침을 따른 후 단일 도메인에 대해 "VHOST"파일을 생성하여 가상 호스트를 활성화합니다.

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

이제 앱이 SSH를 통해 Dokku로 푸시되면 (이 작업을 수행하는 방법은 Dokku 문서 참조), Dokku는 VHOST 파일을보고 푸시 된 특정 앱 ( "container-1"을 푸시했다고 가정 해 보겠습니다)을 생성합니다. 다음 파일 :

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

그리고 다음과 같은 내용이 있습니다.

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;
  }
}

서버가 재부팅되면 Dokku는 Docker가 다른 포트를 임의로 할당하는 대신 처음 배포 된 포트 (여기서는 49162)에 매핑 된 포트로 애플리케이션을 시작하도록합니다. 이 결정 론적 할당을 달성하기 위해 Dokku는 처음 할당 된 포트를 저장하고 /home/git/container-1/PORT다음 실행시 PORT환경을이 값으로 설정하고 Docker의 포트 할당을 호스트 측과 앱 측 모두에서이 포트로 매핑합니다. 이것은 Dokku가 설정 PORT=5000한 다음 VPS 측에서 Dokku가 앱 측에서 5000에 매핑하는 임의의 포트를 파악 하는 첫 번째 출시와 반대 입니다. 그것은 둥글지만 (앞으로 바뀔 수도 있습니다) 작동합니다!

VHOST가 작동하는 방식은 다음과 같습니다. SSH를 통해 앱을 git push 할 때 Dokku는 /var/lib/dokku/plugins/nginx-vhosts. 이러한 후크는 여기 Dokku 소스 코드에도 있으며 nginx.conf올바른 가상 호스트 설정으로 파일 을 작성하는 역할을합니다 . 아래에이 디렉토리가 없으면을 /var/lib/dokku실행 해보십시오 dokku plugins-install.


3

도커를 사용하면 내부 IP가 정상 (예 : 80)으로 유지되고 임의 포트를 연결하는 방법을 파악할 수 있습니다.

이를 처리하는 한 가지 방법은 hipache와 같은 역방향 프록시를 사용하는 것입니다. DNS를 가리키고 컨테이너가 올라오고 내려갈 때 프록시를 재구성 할 수 있습니다. 한 번 봐 가지고 http://txt.fliglio.com/2013/09/protyping-web-stuff-with-docker/을 이 일할 수있는 방법을 볼 수 있습니다.

보다 강력한 것을 찾고 있다면 "서비스 검색"을 살펴볼 수 있습니다. (도커를 사용한 서비스 검색 살펴보기 : http://txt.fliglio.com/2013/12/service-discovery-with-docker-docker-links-and-beyond/ )

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.