호스트 포트를 도커 컨테이너로 전달


166

호스트가 Docker 컨테이너 액세스 포트를 열 수 있습니까? 구체적으로 MongoDB와 RabbitMQ가 호스트에서 실행 중이며 Docker 컨테이너에서 프로세스를 실행하여 대기열을 듣고 (선택적으로) 데이터베이스에 쓰려고합니다.

컨테이너에서 호스트로 포트를 전달하고 (-p 옵션을 통해) Docker 컨테이너 내에서 외부 세계 (예 : 인터넷)에 연결할 수 있지만 RabbitMQ 및 MongoDB 포트를 노출하고 싶지 않습니다. 호스트에서 외부 세계로.

편집 : 약간의 설명 :

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

joelkuiper@vps20528 ~ % docker run -i -t base /bin/bash
root@f043b4b235a7:/# apt-get install nmap
root@f043b4b235a7:/# 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

컨테이너를 사용하여 인터넷 연결을 얻으려면이 트릭을 수행해야했습니다. 내 방화벽이 도커 컨테이너에서 외부로의 네트워크 연결을 차단하고 있습니다.

편집 : 결국 나는 파이프를 사용하여 사용자 지정 브리지를 만들고 서비스를 브리지 IP에서 수신하도록했습니다. MongoDB와 RabbitMQ가 도커 브리지에서 청취하는 대신이 접근법을 사용하여 유연성을 높였습니다.

답변:


53

도커 호스트는 모든 컨테이너에 어댑터를 노출시킵니다. 최근 우분투를 사용한다고 가정하면 실행할 수 있습니다.

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에 대한 연결을 열 수 있어야합니다.


35
컨테이너는 요청을 보낼 IP를 어떻게 알 수 있습니까? 값을 하드 코딩 할 수 있지만 (여기서는 테스트 장비에서 172.17.42.1이지만 항상 그렇습니까?) 호스트와 작업하는 도커 원칙에 위배되는 것 같습니다!
JP.

2
@Seldo : 해당 인터페이스를 표시하려면 구성이 필요합니까? docker 1.7.1을 사용하고 있으며 loand 만 있습니다 eth0.
mknecht

8
호스트가 127.0.0.1에서만 청취하는 경우 어떻게합니까?
HansHarhoff

5
"토끼 / 몽고에게 해당 IP (172.17.42.1)에 바인딩하도록 지시해야합니다. 그런 다음 컨테이너 내에서 172.17.42.1에 대한 연결을 열 수 있어야합니다." 그렇게하는 방법을 설명하면 좋을 것입니다
Novaterata

1
@Novaterata가 언급했듯이 누군가 그 과정을 설명해 줄 수 있습니까?
keskinsaf

121

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

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

Docker 컨테이너의 IP 주소에서 연결을 수락하도록 서비스를 구성 할 필요가 없으며 Docker 컨테이너에 연결할 특정 IP 주소 또는 호스트 이름을 지정할 필요가 없으므로 구성하기가 더 쉽습니다. 포트.

예를 들어, 이미지가 호출 my_image되고 이미지에 telnet유틸리티가 포함되어 있고 연결하려는 서비스가 포트 25에 있다고 가정 한 다음 명령을 실행하여 테스트 할 수 있습니다 .

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

이 방법으로 작업을 고려하는 경우이 페이지의 보안에 대한주의 사항을 참조하십시오

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

그것은 말한다 :

--net = host-Docker에게 컨테이너를 별도의 네트워크 스택 내에 배치하지 않도록 지시합니다. 본질적 으로이 선택은 Docker에게 컨테이너의 네트워킹을 컨테이너화하지 않도록 지시합니다! 컨테이너 프로세스는 여전히 자체 파일 시스템 및 프로세스 목록 및 리소스 제한에 국한되지만 빠른 ip addr 명령은 네트워크 방식으로 메인 Docker 호스트에서 "외부"에 있으며 네트워크 인터페이스에 완전히 액세스 할 수 있음을 보여줍니다 . 이렇게하면 컨테이너가 호스트 네트워크 스택을 재구성 할 수는 없지만 --privileged = true가 필요하지만 컨테이너 프로세스는 다른 루트 프로세스와 같이 적은 수의 포트를 열 수 있습니다. 또한 컨테이너가 D 버스와 같은 로컬 네트워크 서비스에 액세스 할 수 있도록합니다. 이로 인해 컨테이너의 프로세스가 컴퓨터를 다시 시작하는 등 예기치 않은 작업을 수행 할 수 있습니다.


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

13
특히, MacOS에서는 (일부 해결 방법없이 ) 불가능합니다 . docs.docker.com/docker-for-mac/networking/…
pje

15
MacOS에서는 --net=host을 사용하여 컨테이너 프로세스를 호스트 시스템에 연결할 수 없습니다 localhost. 대신 컨테이너를 docker.for.mac.host.internal대신에 특별한 MacOS 전용 호스트 이름에 연결하십시오 localhost. 이를 docker run위해 추가 매개 변수가 필요하지 않습니다 . -e컨테이너 플랫폼을 무시하고 유지하려는 경우이를 사용하여 환경 변수로 전달할 수 있습니다 . 그렇게하면 env var에 이름이 지정된 호스트에 연결하고 docker.for.mac.host.internalMacOS 및 localhostLinux에서 전달할 수 있습니다.
tul

18
mac의 최신 호스트 이름은 다음 host.docker.internal을 참조하십시오 : doc
xysun

Windows 용 같은 docker run --rm -it --net=host postgres bash다음psql -h host.docker.internal -U postgres
레오 Cavalcante

12

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)로 서버에 터널이 있고 해당 서비스로 포트 9200을 노출합니다.


8
기본적으로 개인 키를 Docker 이미지에 넣습니다. 비밀은 절대 Docker 이미지에 들어가서는 안됩니다.
Teoh Han Hui

2
이것은 지금까지 유일하게 사용할 수있는 제정신 솔루션입니다.
helvete

5

도커 컨테이너에서 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


3

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

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

그래서 내 추측은 당신이 전혀 필요하지 않으며 -p잘 작동해야한다는 것입니다. :)


1
나는 그것을 알고 있었지만 약간의 정보가 누락 된 것 같습니다. 호스트의 포트에 연결할 수 없으므로 최근 편집 내용을 참조하십시오.
JoelKuiper

2
주 네트워크 인터페이스뿐만 아니라 브리지에서도 청취하려면 rabbitmq 및 mongodb를 설정해야합니다.
creack

13
@ creack 어떻게 rabbitmq와 mongodb가 다리에서들을 수 있습니까?
Ryan Walls
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.