2013-07-21 65 views
92

是否有可能讓主機打開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 

[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容器:My firewall is blocking network connections from the docker container to outside

編輯:最後,我創建一個使用pipework定製橋去並讓這些服務在網橋IP上進行監聽。我採用這種方法,而不是讓MongoDB和RabbitMQ在Docker橋上偵聽,因爲它提供了更大的靈活性。

回答

35

你搬運工主機暴露了適配器所有的容器。假設你是在最近的Ubuntu,你可以運行

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這裏和我的測試平臺上,但總是如此),但這似乎違背了與任何主機一起工作的碼頭原則! –

+0

另一種選擇是綁定您的主機服務(例如mongodb)以偵聽所有網絡接口(即0.0.0.0),配置防火牆,以便只有內部網絡上的機器才能連接到相關端口,然後連接到主機機器的網絡IP地址在容器內。 – Josh

+1

@Seldo:該界面是否需要配置才能顯示?我使用的是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地址或主機名以連接到,只是一個端口。

例如,您可以通過運行下面的命令,它假定你的形象測試它被稱爲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-bus等本地網絡服務。這可能會導致容器中的進程能夠執行意外的事情,如重新啓動計算機。您應謹慎使用此選項。

+7

對於任何不在Linux上使用docker的人(例如使用某種虛擬化),這將不起作用,因爲主機將是包含的VM,而不是實際的主機OS。 –

+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

相關問題