Docker - 给每个容器配置公网IP

  1. 1. pre-post()
  2. 2. subject(‘实现目标’)
  3. 3. solution(‘附加网络到容器’)
    1. 3.1. 弊端
    2. 3.2. 参考来源
  4. 4. solution(‘桥接网络IP’)
    1. 4.1. 其他信息
    2. 4.2. 弊端
    3. 4.3. 参考来源
  5. 5. subject(‘End’)

pre-post()

为了方便部署流量转发服务,采用了Docker来干这个事,一般情况下一台节点只有一个IP,使用端口映射或者用参数 --network host 直接使用主机的网络来监听和转发是没有问题的,但是有一些节点会存在多个或一个段的外部IP,这时候虽然 IN 方向没有问题,但是 OUT 方向只会采用主机设置的默认路由来访问,就导致了转发的流量都使用同一个IP转发出去了,这是不对的,所以接下来就研究如何才能自定义出口流量,这篇文章则采用给容器配置外部IP的方式实现。

此方法适合非NAT主机

subject(‘实现目标’)

给每个 Docker 容器都配置不同的公网IP出口

solution(‘附加网络到容器’)

1
2
3
4
5
6
7
8
# 从 eth1 接口删除IP
$ sudo ip addr del 192.168.33.10/24 dev eth1

# 创建一个桥接名称为 “docker1” 的 shared_nw 网络
$ sudo docker network create --driver bridge --subnet=192.168.33.0/24 --gateway=192.168.33.10 --opt "com.docker.network.bridge.name"="docker1" shared_nw

# 添加 “docker1” 到 eth1
$ sudo brctl addif docker1 eth1

其中 192.168.33.0/24 是子网段, 192.168.33.10 是IP地址

1
2
3
# 通过 curl 容器来验证IP结果
$ docker run -it curlimages/curl --net shared_nw --ip 192.168.33.11 ip.sb
# 输出结果: 192.168.33.11

这样这个容器本身的IP就变成了外部IP

弊端

采用这种方法会把主机的IP剥离,如果你没有其他接入网卡的话会导致断网无法外部进入,只能通过 Console 来调整

参考来源

solution(‘桥接网络IP’)

1
2
# 创建名为 "pnet01" 的 macvlan 网络
$ docker network create -d macvlan --subnet 23.89.4.0/24 --gateway 23.89.4.1 -o parent=ens3 --aux-address="master=23.89.4.205" pnet01

其中 23.89.4.0/24 是子网段, 23.89.4.1 是网关地址, ens3 是网卡接口名称, 23.89.4.205 是外部IP

1
2
3
# 通过 curl 容器来验证IP结果
$ docker run -it curlimages/curl --net pnet01 --ip 23.89.4.207 ip.sb
# 输出结果: 23.89.4.207

其中 23.89.4.207 是要分配给容器的同网段的IP

其他信息

主机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ifconfig
ens3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 23.89.4.205 netmask 255.255.255.0 broadcast 23.89.4.255
inet6 fe80::216:3cff:fe7e:fbeb prefixlen 64 scopeid 0x20<link>
ether 00:16:3c:7e:fb:eb txqueuelen 1000 (Ethernet)
RX packets 96281 bytes 7457992 (7.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 5325 bytes 1603561 (1.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

# route
Destination Gateway Genmask Flags Metric Ref Use Iface
default 1.4-89-23.rdns. 0.0.0.0 UG 0 0 0 ens3
localnet 0.0.0.0 255.255.255.0 U 0 0 0 ens3
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0

容器内

1
2
3
4
5
6
7
8
9
10
11
12
13
# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:17:59:04:CF
inet addr:23.89.4.207 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:27457 errors:0 dropped:0 overruns:0 frame:0
TX packets:579 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1839527 (1.7 MiB) TX bytes:81473 (79.5 KiB)

# route
Destination Gateway Genmask Flags Metric Ref Use Iface
default 1.4-89-23.rdns. 0.0.0.0 UG 0 0 0 eth0
23.89.4.0 * 255.255.255.0 U 0 0 0 eth0

弊端

仅适用于拥有一个段的IP的服务器,采用这种方式的主机会保留一个IP用于通讯和桥接,然后分配同网段的其他IP给容器,如果有不同网段和网关的IP,就需要同样创建第二个网络

参考来源

subject(‘End’)

这篇文章内容是 2018 年写的,一直咕咕到 2021 年才补上,对现在的我来说对容器以及网络方面有了新的理解,所以这篇文章内容其实也算是有点 过时 了,还有一个方法是采用 iptables NAT进行实现,但是人工维护显然有些繁琐,虽然我没有再这个方向继续研究了,但是希望能给有需要的人一个参考。