Linux 将主机端口转发到 docker 容器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17770902/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:19:49  来源:igfitidea点击:

Forward host port to docker container

linuxnetworkingportdocker

提问by JoelKuiper

Is it possible to have a Docker container access ports opened by the host? Concretely I have MongoDB and RabbitMQ running on the host and I'd like to run a process in a Docker container to listen to the queue and (optionally) write to the database.

是否可以让主机打开 Docker 容器访问端口?具体来说,我在主机上运行了 MongoDB 和 RabbitMQ,我想在 Docker 容器中运行一个进程来侦听队列并(可选)写入数据库。

I know I can forward a port from the container to the host (via the -p option) and have a connection to the outside world (i.e. internet) from within the Docker container but I'd like to not expose the RabbitMQ and MongoDB ports from the host to the outside world.

我知道我可以将端口从容器转发到主机(通过 -p 选项)并从 Docker 容器内连接到外部世界(即互联网),但我不想暴露 RabbitMQ 和 MongoDB 端口从宿主到外部世界。

EDIT: some clarification:

编辑:一些澄清:

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

I had to do this trick to get any internet connection withing the container: My firewall is blocking network connections from the docker container to outside

我必须做这个技巧才能获得与容器的任何互联网连接:我的防火墙阻止了从 docker 容器到外部的网络连接

EDIT: Eventually I went with creating a custom bridge using pipeworkand having the services listen on the bridge IP's. I went with this approach instead of having MongoDB and RabbitMQ listen on the docker bridge because it gives more flexibility.

编辑:最终我使用管道创建了一个自定义网桥,并让服务监听网桥 IP。我采用了这种方法,而不是让 MongoDB 和 RabbitMQ 在 docker 桥上监听,因为它提供了更大的灵活性。

采纳答案by Seldo

Your docker host exposes an adapter to all the containers. Assuming you are on recent ubuntu, you can run

您的 docker 主机向所有容器公开了一个适配器。假设您使用的是最近的 ubuntu,您可以运行

ip addr

This will give you a list of network adapters, one of which will look something like

这会给你一个网络适配器列表,其中一个看起来像

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

You will need to tell rabbit/mongo to bind to that IP (172.17.42.1). After that, you should be able to open connections to 172.17.42.1 from within your containers.

您需要告诉 rabbit/mongo 绑定到该 IP (172.17.42.1)。之后,您应该能够从容器内打开与 172.17.42.1 的连接。

回答by creack

If MongoDB and RabbitMQ are running on the Host, then the port should already exposed as it is not within Docker.

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

You do not need the -poption in order to expose ports from container to host. By default, all port are exposed. The -poption allows you to expose a port from the container to the outside of the host.

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

So, my guess is that you do not need -pat all and it should be working fine :)

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

回答by David Grayson

A simple but relatively insecure way would be to use the --net=hostoption to docker run.

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

This option makes it so that the container uses the networking stack of the host. Then you can connect to services running on the host simply by using "localhost" as the hostname.

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

This is easier to configure because you won't have to configure the service to accept connections from the IP address of your docker container, and you won't have to tell the docker container a specific IP address or host name to connect to, just a port.

这更容易配置,因为您不必将服务配置为接受来自 docker 容器 IP 地址的连接,也不必告诉 docker 容器要连接的特定 IP 地址或主机名,只需一个港口。

For example, you can test it out by running the following command, which assumes your image is called my_image, your image includes the telnetutility, and the service you want to connect to is on port 25:

例如,您可以通过运行以下命令对其进行测试,该命令假设您的映像名为my_image,您的映像包含该telnet实用程序,并且您要连接的服务位于端口 25 上:

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

If you consider doing it this way, please see the caution about security on this page:

如果您考虑这样做,请参阅此页面上的安全警告:

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

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

It says:

它说:

--net=host -- Tells Docker to skip placing the container inside of a separate network stack. In essence, this choice tells Docker to not containerize the container's networking! While container processes will still be confined to their own filesystem and process list and resource limits, a quick ip addr command will show you that, network-wise, they live “outside” in the main Docker host and have full access to its network interfaces. Note that this does not let the container reconfigure the host network stack — that would require --privileged=true — but it does let container processes open low-numbered ports like any other root process. It also allows the container to access local network services like D-bus. This can lead to processes in the container being able to do unexpected things like restart your computer. You should use this option with caution.

--net=host -- 告诉 Docker 跳过将容器放置在单独的网络堆栈中。本质上,这个选择告诉 Docker 不要容器化容器的网络!虽然容器进程仍将受限于它们自己的文件系统和进程列表以及资源限制,但一个快速的 ip addr 命令将向您显示,在网络方面,它们位于主 Docker 主机的“外部”,并可以完全访问其网络接口. 请注意,这不会让容器重新配置主机网络堆栈——这需要 --privileged=true——但它确实让容器进程像任何其他根进程一样打开低编号端口。它还允许容器访问本地网络服务,如 D-bus。这可能导致容器中的进程能够执行意外的操作,例如重新启动计算机。

回答by czerasz

You could also create an ssh tunnel.

您还可以创建 ssh 隧道。

docker-compose.yml:

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:

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:

config/ssh/config

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

This way the elasticsearchhas a tunnel to the server with the running service (Elasticsearch, MongoDB, PostgreSQL) and exposes port 9200 with that service.

通过这种方式,elasticsearch可以通过运行服务(Elasticsearch、MongoDB、PostgreSQL)与服务器建立隧道,并使用该服务公开端口 9200。

回答by Arigion

I had a similar problem accessing a LDAP-Server from a docker container. I set a fixed IP for the container and added a firewall rule.

我在从 docker 容器访问 LDAP 服务器时遇到了类似的问题。我为容器设置了固定 IP 并添加了防火墙规则。

docker-compose.yml:

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 rule:

iptables 规则:

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

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

Inside the container access dockerhost:portnumberOnHost

进入容器内部 dockerhost:portnumberOnHost