2013-07-21 3 views
92

도커 컨테이너에 호스트에서 열린 포트에 액세스 할 수 있습니까? 구체적으로는 호스트에서 MongoDB와 RabbitMQ를 실행하고 있으며 Docker 컨테이너에서 대기열을 수신하고 (선택적으로) 데이터베이스에 쓸 프로세스를 실행하고 싶습니다.도킹 컨테이너에 호스트 포트 포워드

컨테이너에서 호스트로 (-p 옵션을 통해) 전달할 수 있고 Docker 컨테이너 내에서 외부 세계 (예 : 인터넷)에 연결할 수 있다는 것을 알고 있지만, RabbitMQ 및 MongoDB 포트는 호스트에서 외부로 연결됩니다.

편집 : 몇 가지 설명이 : 결국 내가 pipework를 사용하여 사용자 정의 다리를 만들어 갔다 : My firewall is blocking network connections from the docker container to outside

편집 :

Starting Nmap 5.21 (http://nmap.org) at 2013-07-22 22:39 CEST 
Nmap scan report for localhost (127.0.0.1) 
Host is up (0.00027s latency). 
PORT  STATE SERVICE 
6311/tcp open unknown 

[email protected] ~ % docker run -i -t base /bin/bash 
[email protected]:/# apt-get install nmap 
[email protected]:/# nmap 172.16.42.1 -p 6311 # IP found via docker inspect -> gateway 

Starting Nmap 6.00 (http://nmap.org) at 2013-07-22 20:43 UTC 
Nmap scan report for 172.16.42.1 
Host is up (0.000060s latency). 
PORT  STATE SERVICE 
6311/tcp filtered unknown 
MAC Address: E2:69:9C:11:42:65 (Unknown) 

Nmap done: 1 IP address (1 host up) scanned in 13.31 seconds 

나는 용기 withing에 어떤 인터넷 연결을 얻기 위해이 트릭을해야했다 서비스가 브리지 IP에서 수신하도록하는 것입니다. MongoDB와 RabbitMQ가 더 유연함을 제공하기 때문에 docker bridge에서 수신하는 대신이 방법을 사용했습니다.

답변

35

귀하의 고정 표시기 호스트는 모든 컨테이너 어댑터를 노출하는 것입니다. 당신이 최근 우분투에있는 가정하면,

ip addr 

이 당신에게 당신이 토끼/몽고 말할 필요가

3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
link/ether 22:23:6b:28:6b:e0 brd ff:ff:ff:ff:ff:ff 
inet 172.17.42.1/16 scope global docker0 
inet6 fe80::a402:65ff:fe86:bba6/64 scope link 
    valid_lft forever preferred_lft forever 

처럼 보일 것 중 하나는 네트워크 어댑터의 목록을 줄 것이다 실행할 수 있습니다 해당 IP에 바인딩 (172.17.42.1). 그런 다음 컨테이너에서 172.17.42.1 로의 연결을 열 수 있어야합니다.

+22

컨테이너는 요청을 보낼 IP를 어떻게 알 수 있습니까? 값을 하드 코딩 할 수는 있지만 (172.17.42.1 여기 그리고 내 테스트 장비에서 그렇습니다.하지만 항상 그렇습니다), 그렇다고해서 모든 호스트와 작업하는 docker 원칙에 어긋나는 것 같습니다! –

+0

또 다른 옵션은 호스트 컴퓨터 서비스 (예 : mongodb)를 바인딩하여 모든 네트워크 인터페이스 (예 : 0.0.0.0)에서 수신 대기하고 내부 네트워크의 시스템 만 관련 포트에 연결 한 다음 호스트에 연결할 수 있도록 방화벽을 구성합니다 컨테이너 내에서 컴퓨터의 네트워크 IP 주소. – Josh

+1

@ 셀do : 표시 할 인터페이스가 필요합니까? 나는 docker 1.7.1을 사용하고 있으며, 단지'lo'와'eth0'만을 가지고있다. – mknecht

4

MongoDB 및 RabbitMQ가 호스트에서 실행중인 경우 포트는 Docker 내에 있지 않으므로 이미 노출되어 있어야합니다.

컨테이너에서 호스트로 포트를 노출하기 위해 '-p'옵션이 필요하지 않습니다. 기본적으로 모든 포트가 표시됩니다. '-p'옵션을 사용하면 컨테이너의 포트를 호스트 외부로 노출시킬 수 있습니다.

그래서, 내 생각은 전혀 '-p'를 필요로하지 않고는 잘 작동한다 :

+0

내부가 나는 것을 알고 있지만, 나는 정보의 비트를 누락 것으로 보인다 : 참조 내가 호스트의 포트에 연결할 수 없기 때문에 최근 편집. – JoelKuiper

+1

rabbitmq와 mongodb를 설정하여 메인 네트워크 인터페이스뿐만 아니라 브리지에서도 수신 대기해야합니다. – creack

+7

@creack rabbitmq와 mongodb에게 다리에서 듣기를 어떻게 얻습니까? –

66

간단하지만 비교적 안전하지 않은 방법은 --net=host 옵션을 docker run에 사용하는 것입니다.

이 옵션은 컨테이너가 호스트의 네트워킹 스택을 사용하도록합니다. 그런 다음 "localhost"를 호스트 이름으로 사용하여 호스트에서 실행중인 서비스에 연결할 수 있습니다.

도커 컨테이너의 IP 주소에서 연결을 허용하도록 서비스를 구성 할 필요가 없으며 도커 컨테이너에 특정 IP 주소 나 호스트 이름을 말할 필요가 없으므로 구성이 더 쉽습니다. 포트에 연결하십시오.

docker run --rm -i -t --net=host my_image telnet localhost 25 
:

예를 들어, 당신은 당신의 이미지가 telnet 유틸리티를 포함하고 연결하려는 서비스가 포트 25에, my_image라고 이미지를 가정 다음 명령을 실행하여 테스트 할 수 있습니다 그것은 말한다

https://docs.docker.com/articles/networking/

:

당신이 이런 식으로 일을 고려하면,이 페이지의 보안에 대한주의를 참조하십시오

- net = host - 별도의 네트워크 스택 내부에 컨테이너 배치를 건너 뛰도록 지시합니다. 본질적으로이 선택은 컨테이너의 네트워킹을 컨테이너 화하지 않도록 Docker에 알려줍니다! 컨테이너 프로세스는 여전히 자신의 파일 시스템과 프로세스 목록 및 리소스 제한에 국한되지만 빠른 ip addr 명령을 사용하면 네트워크에 따라 Docker 호스트의 "외부"에 살고 네트워크 인터페이스에 완전히 액세스 할 수 있습니다 . 이 옵션을 사용하면 컨테이너가 호스트 네트워크 스택을 재구성하지 못하게됩니다. 즉, --privileged = true가 필요하지만 컨테이너 프로세스가 다른 루트 프로세스처럼 낮은 번호의 포트를 열도록합니다. 또한 컨테이너가 D 버스와 같은 로컬 네트워크 서비스에 액세스 할 수 있습니다. 이로 인해 컴퓨터를 다시 시작하는 등의 예기치 않은 작업을 수행 할 수있는 컨테이너의 프로세스가 발생할 수 있습니다. 이 옵션은 신중하게 사용해야합니다.

+7

Linux에서 도커를 사용하지 않는 사람 (예 : 일부 가상화 사용)의 경우 호스트가 실제 호스트 OS가 아닌 포함 VM이되므로 작동하지 않습니다. –

+3

특히 MacOS에서는 ** 해결이 불가능합니다 ** (약간의 문제 해결 방법 제외) : https://docs.docker.com/docker-for-mac/networking/#i-want-to-connect-from- 호스트 간 서비스 – pje

4

ssh 터널을 만들 수도 있습니다.

docker-compose.yml :

--- 

version: '2' 

services: 
    kibana: 
    image: "kibana:4.5.1" 
    links: 
     - elasticsearch 
    volumes: 
     - ./config/kibana:/opt/kibana/config:ro 

    elasticsearch: 
    build: 
     context: . 
     dockerfile: ./docker/Dockerfile.tunnel 
    entrypoint: ssh 
    command: "-N elasticsearch -L 0.0.0.0:9200:localhost:9200" 

docker/Dockerfile.tunnel :

FROM buildpack-deps:jessie 

RUN apt-get update && \ 
    DEBIAN_FRONTEND=noninteractive \ 
    apt-get -y install ssh && \ 
    apt-get clean && \ 
    rm -rf /var/lib/apt/lists/* 

COPY ./config/ssh/id_rsa /root/.ssh/id_rsa 
COPY ./config/ssh/config /root/.ssh/config 
COPY ./config/ssh/known_hosts /root/.ssh/known_hosts 
RUN chmod 600 /root/.ssh/id_rsa && \ 
    chmod 600 /root/.ssh/config && \ 
    chown $USER:$USER -R /root/.ssh 

config/ssh/config :

# Elasticsearch Server 
Host elasticsearch 
    HostName jump.host.czerasz.com 
    User czerasz 
    ForwardAgent yes 
    IdentityFile ~/.ssh/id_rsa 

elasticsearch가 실행중인 서비스와 서버 (Elasticsearch, MongoDB를에 터널을 가지고 이런 식으로, PostgreSQL)와 po를 공개합니다 그 서비스와 함께 rt 9200.

+0

기본적으로 개인 키는 Docker 이미지에 넣습니다. 비밀은 Docker 이미지에 들어갈 수 없습니다. –

1

도커 컨테이너에서 LDAP 서버에 액세스하는 것과 비슷한 문제가있었습니다. 컨테이너에 고정 IP를 설정하고 방화벽 규칙을 추가했습니다.

docker-compose.yml:

version: '2' 
services: 
    containerName: 
    image: dockerImageName:latest 
    extra_hosts: 
     - "dockerhost:192.168.50.1" 
    networks: 
     my_net: 
     ipv4_address: 192.168.50.2 
networks: 
    my_net: 
    ipam: 
     config: 
     - subnet: 192.168.50.0/24 

의 iptables 규칙 :

iptables -A INPUT -j ACCEPT -p tcp -s 192.168.50.2 -d $192.168.50.1 --dport portnumberOnHost

컨테이너 액세스 dockerhost:portnumberOnHost

관련 문제