将主机端口转发到Docker容器

是否有可能有一个由主机打开的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 

我不得不这样做,以获得与容器的任何互联网连接: 我的防火墙阻止从docker集装箱到外部的networking连接

编辑 :最后我去创build一个自定义的桥梁使用pipe道,并有服务在网桥IP侦听。 我采用这种方法,而不是让MongoDB和RabbitMQ在Docker桥上侦听,因为它提供了更多的灵活性。

您的docker主机将适配器公开给所有的容器。 假设你在最近的Ubuntu上,你可以运行

 ip addr 

这将给你一个networking适配器的列表,其中之一将看起来像

 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 

您需要告诉rabbit / mongo绑定到该IP(172.17.42.1)。 之后,你应该可以在你的容器内打开172.17.42.1的连接。

一个简单但相对不安全的方法是使用--net=host选项来docker run --net=host

该选项使得容器使用主机的networking堆栈。 然后,只需使用“localhost”作为主机名即可连接到在主机上运行的服务。

这样更容易configuration,因为您不必将服务configuration为接受来自Docker容器的IP地址的连接,而且您不必告诉Docker容器特定的IP地址或主机名来连接,只需一个港口。

例如,您可以通过运行以下命令来进行testing,该命令假定您的映像称为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跳过将容器放置在单独的networking堆栈中。 本质上,这个select告诉Docker不要容器的容器联网! 尽pipe容器进程仍然限于自己的文件系统和进程列表以及资源限制,但是一个快速的ip addr命令将向您显示,在networking方面,它们活在Docker主机主机的“外部”,并且完全访问其networking接口。 请注意,这不会让容器重新configuration主机networking堆栈 – 这将需要–privileged = true – 但它确实让容器进程像任何其他根进程一样打开低编号的端口。 它还允许容器访问D-bus等本地networking服务。 这可能导致容器中的进程能够执行意想不到的事情,如重新启动计算机。 您应谨慎使用此选项。

如果MongoDB和RabbitMQ在主机上运行,​​那么端口应该已经暴露,因为它不在Docker中。

您不需要'-p'选项来将端口从容器公开到主机。 默认情况下,所有端口都是暴露的。 “-p”选项允许您将容器中的端口暴露给主机外部。

所以,我的猜测是,你根本不需要'-p',它应该工作正常:)

你也可以创build一个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)与服务器build立隧道,并使用该服务公开端口9200。

从Docker容器访问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