首页 文章

将主机端口转发到docker容器

提问于
浏览
111

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

我知道我可以从容器转发到主机(通过-p选项),我可以从Docker容器中连接到外部世界(即Internet),但我不想公开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

我不得不这样做,以获得容器的任何互联网连接:My firewall is blocking network connections from the docker container to outside

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

5 回答

  • 2

    您的docker主机向所有容器公开适配器 . 假设你是最近的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
    

    你需要告诉rabbit / mongo绑定到那个IP(172.17.42.1) . 之后,您应该能够从容器中打开到172.17.42.1的连接 .

  • 75

    一种简单但相对不安全的方法是使用 --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-bus等本地网络服务 . 这可能导致容器中的进程能够执行意外操作,例如重新启动计算机 . 您应该谨慎使用此选项 .

  • 3

    您还可以创建一个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 .

  • 7

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

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

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

  • 40

    我有一个类似的问题从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

相关问题