Docker 1.10容器在局域网中的IP地址

23

自 Docker 1.10(和 libnetwork 更新)以来,我们可以在用户定义的网络内手动为容器分配 IP,这很酷!

我想在我的局域网中为容器分配一个 IP 地址(就像我们可以在“桥接”模式下使用虚拟机一样)。我的局域网是 192.168.1.0/24,所有计算机都有其中的 IP 地址。我希望我的容器具有此范围内的 IP,以便可以从我的 LAN 中的任何地方访问它们(无需 NAT/PAT 等)。

我显然读过 Jessie Frazelle 的博客文章和其他很多类似的文章,如:

等等,但没有什么效果;我的容器仍然具有位于我的 Docker 主机“内部”的 IP 地址,并且不能被我的局域网中的其他计算机访问。

阅读 Jessie Frazelle 的博客文章后,我认为(因为她使用公共 IP)我们可以做到我想要做的事情?

编辑:确实,如果我做类似于:

network create --subnet 192.168.1.0/24 --gateway 192.168.1.1 homenet
docker run --rm -it --net homenet --ip 192.168.1.100 nginx
新的docker主机界面(br-[a-z0-9]+)采用“--gateway”IP,它是我的路由器IP。在网络上两台计算机使用相同的IP......崩溃了。
提前致谢。

1
你是在Linux上,还是通过boot2docker虚拟机使用Docker? - VonC
1
真是个傻瓜!我忘了最重要的事情了!我正在使用Linux(Debian 8)。 - Jérôme Pin
1
感谢您发布这篇文章,我在过去几周中遇到了许多与此相关的复杂问题,特别是从子网之外访问容器。由于我的问题,我已经放弃了这种方法,但我很高兴在需要再次这样做时能够找到这篇文章。 - enderland
6个回答

20

编辑: 此解决方案现已无效。自版本1.12以来,Docker提供了两个网络驱动程序:macvlan和ipvlan。它们允许从LAN网络分配静态IP。请参见下面的答案


在寻找遇到相同问题的人后,我们采用了一个解决方法:

总结:

  • (V)LAN为192.168.1.0/24
  • 默认网关(=路由器)为192.168.1.1
  • 多个Docker主机
  • 注:我们有两个NIC:eth0和专用于Docker的eth1

我们想要什么:

我们希望容器拥有192.168.1.0/24网络中的ip(就像计算机一样),没有任何NAT/PAT/翻译/端口转发等...

问题:

进行以下操作时:

network create --subnet 192.168.1.0/24 --gateway 192.168.1.1 homenet

我们可以为容器分配所需的IP地址,但是 Docker 创建的桥接网络(br-[a-z0-9]+)将使用我们的路由器IP地址192.168.1.1。

解决方案

1. 配置Docker网络

使用DefaultGatewayIPv4参数:

docker network create --subnet 192.168.1.0/24 --aux-address "DefaultGatewayIPv4=192.168.1.1" homenet

默认情况下,Docker 将给桥接接口 (br-[a-z0-9]+) 分配第一个 IP,这可能已被另一台机器占用。解决方案是使用 --gateway 参数告诉 Docker 分配一个可用的任意 IP:

docker network create --subnet 192.168.1.0/24 --aux-address "DefaultGatewayIPv4=192.168.1.1" --gateway=192.168.1.200 homenet

我们可以通过在之前的命令中添加-o com.docker.network.bridge.name=br-home-net来指定桥的名称。

2. 搭建桥接网络!

现在我们有了由Docker创建的桥(br-[a-z0-9]+)。我们需要将它桥接到物理接口上(在我的情况下,我有两个网卡,所以我使用eth1):

brctl addif br-home-net eth1

3. 删除桥接IP

我们现在可以从桥接中删除IP地址,因为我们不需要它:

ip a del 192.168.1.200/24 dev br-home-net

IP地址192.168.1.200可以在多个Docker主机上用作桥接器,但由于我们不使用它,因此我们已将其移除。


我该如何撤销 brctl addif br-home-net eth1 命令?我自己无法通过 SSH 进入系统,需要请别人帮忙修复 :) - Duplexia
2
@Duplexia:你可以执行 brctl delif br-home-net eth1 - Jérôme Pin
谢谢,这非常有用。我只想指出,如果您失去了互联网连接,您必须手动将默认网关添加到路由表中:sudo route add default gw 192.168.1.1。 - Mohammed Noureldin
有没有使用DHCP实现这个的方法?我正在尝试为容器分配ISP的DHCP IP地址。 - ssut
自 Docker 1.12 版本开始,macvlan 和 ipvlan 驱动程序都可用。它们使得这个解决方案变得无用。而且自 Docker 17.06 版本开始,我认为你可以使用 macvlan 驱动程序从 DHCP 池中分配 IP 地址。 - Jérôme Pin

7
Docker现在支持MacvlanIPvlan网络驱动程序。有关两个网络驱动程序的Docker文档可以在此处找到。
使用这两种驱动程序,您可以实现所需的场景(将容器配置为桥接模式下的虚拟机):
- Macvlan:允许单个物理网络接口(主设备)具有任意数量的从设备,每个设备都有自己的MAC地址。 需要Linux内核v3.9-3.19或4.0+。
- IPvlan:允许您为主设备创建任意数量的从设备,所有这些设备共享相同的MAC地址。 需要Linux内核v4.2+(支持早期内核的存在,但存在错误)。 有关更多信息,请参见kernel.org IPVLAN Driver HOWTO
容器连接是通过将一个从设备放入要配置的容器的网络命名空间中来实现的。主设备保留在主机操作系统上(默认命名空间)。
作为经验法则,如果连接到外部交换机/路由器的Linux主机已配置了仅允许每个端口一个MAC地址的策略,则应使用IPvlan驱动程序。在VMWare ESXi环境中经常出现这种情况! 另一个重要的事情(Macvlan和IPvlan):主设备和从设备之间的流量不能相互发送。如果需要启用主到从的通信,请参见IPvlan作者之一(Mahesh Bandewar)发表的论文《IPVLAN-The beginning》中的“与主机(默认命名空间)通信”部分。

不错。+1。我得测试一下。 - VonC
你能分享一些关于如何使用Macvlan配置的教程吗?我很想阅读一些文章,因为我自己很难进行配置。在Virtualbox中很容易让它从WiFi路由器获取IP - 只需在虚拟网络卡上进行配置,这样我就可以定义自己的MAC地址。我是Docker的新手,但我无法掌握它。 - Marecky
请查看Docker的Macvlan文档,链接在此处:https://docs.docker.com/engine/userguide/networking/get-started-macvlan/ @Marecky。这个章节应该向您展示如何为每个容器分配唯一的MAC / IP地址,链接在此处:https://docs.docker.com/engine/userguide/networking/get-started-macvlan/#macvlan-bridge-mode-example-usage。 - Christoph Zauner

4

使用官方Docker驱动程序:

截至Docker v1.12.0-rc2,新的MACVLAN驱动程序现在已经在官方Docker发布中可用:

  • MacVlan驱动程序已经不再是实验性的#23524

这些新驱动程序已经被作者(s)充分记录,并提供了使用示例

最终,它应该提供类似的功能,更容易设置,并且具有较少的错误/其他怪癖。

查看Docker主机上的容器:

新的官方macvlan驱动程序唯一的注意事项是,docker主机机器无法看到/与其自己的容器通信。这可能是可取的或不可取的,这取决于您的具体情况。

如果您的docker主机有多个网卡,并且这些网卡都连接到局域网,则可以解决此问题。您可以选择A)将docker主机的两个网卡中的一个专门用于docker,另一个用于主机访问局域网;或者B)为需要通过第二个网卡访问的容器添加特定路由。例如:
sudo route add -host $container_ip gw $lan_router_ip $if_device_nic2

如果您想从docker主机访问所有容器,并且有多个硬连接,则方法A)很有用。

而如果您只需要从docker主机访问几个特定的容器,或者您的第二个网络接口卡是wifi卡,并且处理所有局域网流量速度会慢得多,则方法B)很有用。例如在笔记本电脑上。

安装:

如果您在ubuntu 16.04上看不到预发布的-rc2候选版本,请暂时添加或修改此行以在/etc/apt/sources.list中说:

deb https://apt.dockerproject.org/repo ubuntu-xenial testing

而不是 main(这是稳定版本)。


3

0

这里是使用macvlan的示例。它在http://10.0.2.1/上启动了一个Web服务器。

这些命令和Docker Compose文件适用于QNAP和QNAP的Container Station。请注意,QNAP的网络接口是qvs0

命令:

Lars Kellogg-Stedman的博客文章“使用Docker macvlan网络[1][2]解释了这些命令的含义。

docker network create -d macvlan -o parent=qvs0 --subnet 10.0.0.0/8 --gateway 10.0.0.1 --ip-range 10.0.2.0/24 --aux-address "host=10.0.2.254" macvlan0
ip link del macvlan0-shim link qvs0 type macvlan mode bridge
ip link add macvlan0-shim link qvs0 type macvlan mode bridge
ip addr add 10.0.2.254/32 dev macvlan0-shim
ip link set macvlan0-shim up
ip route add 10.0.2.0/24 dev macvlan0-shim

docker run --network="macvlan0" --ip=10.0.2.1 -p 80:80 nginx

Docker Compose

使用版本2,因为版本3不支持其他网络配置,例如gatewayip_rangeaux_address

version: "2.3"

services:
    HTTPd:
        image: nginx:latest
        ports:
            - "80:80/tcp"
            - "80:80/udp"
        networks:
            macvlan0:
                ipv4_address: "10.0.2.1"

networks:
    macvlan0:
        driver: macvlan
        driver_opts:
            parent: qvs0
        ipam:
            config:
                - subnet: "10.0.0.0/8"
                  gateway: "10.0.0.1"
                  ip_range: "10.0.2.0/24"
                  aux_address: "host=10.0.2.254"

-1

通过pipework,可以将物理接口映射到容器中。

连接容器到本地物理接口

pipework eth2 $(docker run -d hipache /usr/sbin/hipache) 50.19.169.157/24
pipework eth3 $(docker run -d hipache /usr/sbin/hipache) 107.22.140.5/24

现在可能有一种本地方式,但我还没有为1.10版本进行研究。


2
pipework 的缺点是:我们无法在同一主机上看到容器。因此,本地解决方案可能更可取(并且分配 IP 地址更快/更少出错)。 - Dreamcat4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接