环境说明

root@EQ12-Debian:~# ip address show enp2s0 
3: enp2s0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 7c:83:34:bc:e0:c3 brd ff:ff:ff:ff:ff:ff
    inet 10.5.2.132/24 brd 10.5.2.255 scope global dynamic enp2s0
       valid_lft 41328sec preferred_lft 41328sec
    inet6 fe80::7e83:34ff:febc:e0c3/64 scope link 
       valid_lft forever preferred_lft forever
root@EQ12-Debian:~# 

先别急着复制粘贴,请先看完所有内容先
先别急着复制粘贴,请先看完所有内容先

只需要IPV4的话看这篇即可Docker Macvlan网络创建及通信配置

宿主机配置

变量配置

# 宿主机网卡名称
eth=enp2s0
# 宿主机IP网段
subnet=10.5.2.0/24
# 宿主机IP地址(MACVLAN地址,非当前地址)
host_ip=10.5.2.222
# 宿主机网关
gateway=10.5.2.1
# 容器1 IP
container_ip1=10.5.2.202
# 容器名称
container_name=debian
# 镜像名称
container_images=debian:10
# Docker新建MacVlan网络名称
docker_macvlan_name=macvlan2
host_macvlan_name=${eth}-macvlan
# 设置IPV6子网网段(可以并建议照抄)
subnet6=fd1e:6551:6c39::/64
 # IPV6网关(也就是在网段后面加上`1`, 可以并建议照抄)
 gateway_v6=fd1e:6551:6c39::1

下面命令均通过变量实现,方便理解语法
推荐提前通过变量设置好,后面直接复制粘贴,不需要修改任何内容

开启混杂模式

首先执行下面的命令查看网卡是否开启混杂模式

ip address show ${eth} | grep PROMISC

如果有输出就是开启了,例如

gxxc@gxxc-CE3000F:~$ ip address show ${eth} | grep PROMISC
2: enaftgm1i0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
gxxc@gxxc-CE3000F:~$ 

如果没有开启,可以使用下面的命令打开

ip link set ${eth} promisc on

开启路由转发

echo -e "net.ipv4.ip_forward=1\nvm.max_map_count=655360" > /etc/sysctl.conf;sysctl -p

Docker配置

网络创建

docker network create --driver macvlan --subnet=${subnet} --gateway=${gateway} --ipv6 --subnet=${subnet6} --gateway=${gateway_v6} -o parent=${eth} ${docker_macvlan_name}

创建容器

docker run -tid --name ${container_name} --net=${docker_macvlan_name} --ip=${container_ip1} ${container_images} /bin/bash

进入容器

docker  exec -ti ${container_name} bash

路由配置

ip link add ${host_macvlan_name} link ${eth} type macvlan mode bridge
ip addr add ${host_ip} dev ${name}
ip link set ${host_macvlan_name} up
ip route add ${container_ip1} dev ${host_macvlan_name}

实践操作

设置配置参数

将变量信息写入一个文件,然后source一下就好了

root@EQ12-Debian:~# cat vlan.sh 
# 宿主机网卡名称
eth=enp2s0
# 宿主机IP网段
subnet=10.5.2.0/24
# 宿主机IP地址(MACVLAN地址,非当前地址)
host_ip=10.5.2.222
# 宿主机网关
gateway=10.5.2.1
# 容器1 IP
container_ip1=10.5.2.202
# 容器名称
container_name=debian
# 镜像名称
container_images=debian:10
# Docker新建MacVlan网络名称
docker_macvlan_name=macvlan2
host_macvlan_name=${eth}-macvlan
# 设置IPV6子网网段(可以并建议照抄)
subnet6=fd1e:6551:6c39::/64
 # IPV6网关(也就是在网段后面加上`1`, 可以并建议照抄)
 gateway_v6=fd1e:6551:6c39::1
root@EQ12-Debian:~# source vlan.sh 
root@EQ12-Debian:~# echo $container_name # 验证环境变量
debian
root@EQ12-Debian:~# 

开启混杂并配置转发

root@EQ12-Debian:~# ip link set ${eth} promisc on
root@EQ12-Debian:~#  echo -e "net.ipv4.ip_forward=1\nvm.max_map_count=655360" > /etc/sysctl.conf;sysctl -p
net.ipv4.ip_forward = 1
vm.max_map_count = 655360
root@EQ12-Debian:~# 

创建网络

root@EQ12-Debian:~# echo "docker network create --driver macvlan --subnet=${subnet} --gateway=${gateway} --ipv6 --subnet=${subnet6} --gateway=${gateway_v6} -o parent=${eth} ${docker_macvlan_name}"
docker network create --driver macvlan --subnet=10.5.2.0/24 --gateway=10.5.2.1 --ipv6 --subnet=fd1e:6551:6c39::/64 --gateway=fd1e:6551:6c39::1 -o parent=enp2s0 macvlan2
root@EQ12-Debian:~# docker network create --driver macvlan --subnet=10.5.2.0/24 --gateway=10.5.2.1 --ipv6 --subnet=fd1e:6551:6c39::/64 --gateway=fd1e:6551:6c39::1 -o parent=enp2s0 macvlan2
a37881aa39a6c17fc91159526f1ec645797067e4518862cfc829b030739c1261
root@EQ12-Debian:~# docker network ls
NETWORK ID     NAME                DRIVER    SCOPE
95ed1a44e1a9   bridge              bridge    local
91c66270dbaf   data_halo_network   bridge    local
1f6d72d10049   host                host      local
a37881aa39a6   macvlan2            macvlan   local
d5efc9813726   none                null      local
root@EQ12-Debian:~# 

创建容器

root@EQ12-Debian:~# docker run -tid --name ${container_name} --net=${docker_macvlan_name} --ip=${container_ip1} ${container_images} /bin/bash
e900aef9e6bbc20f1f71a34cc4319ecce07673dce142588e731124883bc40822
root@EQ12-Debian:~# 

验证

root@EQ12-Debian:~# docker exec -ti  ${container_name} /bin/bash
root@e900aef9e6bb:~# apt install net-tools -q -y
Reading package lists...
Building dependency tree...
Reading state information...
The following NEW packages will be installed:
  net-tools
0 upgraded, 1 newly installed, 0 to remove and 3 not upgraded.
Need to get 204 kB of archives.
After this operation, 819 kB of additional disk space will be used.
Get:1 http://mirrors.tencent.com/ubuntu jammy/main amd64 net-tools amd64 1.60+git20181103.0eebece-1ubuntu5 [204 kB]
Fetched 204 kB in 5s (37.6 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package net-tools.
(Reading database ... 18038 files and directories currently installed.)
Preparing to unpack .../net-tools_1.60+git20181103.0eebece-1ubuntu5_amd64.deb ...
Unpacking net-tools (1.60+git20181103.0eebece-1ubuntu5) ...
Setting up net-tools (1.60+git20181103.0eebece-1ubuntu5) ...
root@e900aef9e6bb:~# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.5.2.202  netmask 255.255.255.0  broadcast 10.5.2.255
        inet6 fd1e:6551:6c39::2  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::42:aff:fe05:2ca  prefixlen 64  scopeid 0x20<link>
        ether 02:42:0a:05:02:ca  txqueuelen 0  (Ethernet)
        RX packets 81  bytes 211193 (211.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 75  bytes 4705 (4.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 9  bytes 1082 (1.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 9  bytes 1082 (1.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

root@e900aef9e6bb:~# 

此时可以看到,容器已经有了IPV6了,不过目前还是私有的,目前没有环境,后面再完善公网V6,具体可以直接先看后面的参考资料

IPV4路由配置

root@EQ12-Debian:~# ip link add ${host_macvlan_name} link ${eth} type macvlan mode bridge
root@EQ12-Debian:~# ip addr add ${host_ip} dev ${host_macvlan_name}
root@EQ12-Debian:~# ip link set ${host_macvlan_name} up
root@EQ12-Debian:~# ip route add ${container_ip1} dev ${host_macvlan_name}
root@EQ12-Debian:~# ping -c 5 ${container_ip1}
PING 10.5.2.202 (10.5.2.202) 56(84) bytes of data.
64 bytes from 10.5.2.202: icmp_seq=1 ttl=64 time=0.108 ms
64 bytes from 10.5.2.202: icmp_seq=2 ttl=64 time=0.056 ms
64 bytes from 10.5.2.202: icmp_seq=3 ttl=64 time=0.056 ms
64 bytes from 10.5.2.202: icmp_seq=4 ttl=64 time=0.066 ms
64 bytes from 10.5.2.202: icmp_seq=5 ttl=64 time=0.052 ms

--- 10.5.2.202 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4002ms
rtt min/avg/max/mdev = 0.052/0.067/0.108/0.020 ms
root@EQ12-Debian:~# 

IPV6路由配置

root@EQ12-Debian:~# ping6 fe80::42:aff:fe05:2ca
PING fe80::42:aff:fe05:2ca(fe80::42:aff:fe05:2ca) 56 data bytes
From fe80::7e83:34ff:febc:e0c3%enp2s0 icmp_seq=1 Destination unreachable: Address unreachable
From fe80::7e83:34ff:febc:e0c3%enp2s0 icmp_seq=2 Destination unreachable: Address unreachable
From fe80::7e83:34ff:febc:e0c3%enp2s0 icmp_seq=3 Destination unreachable: Address unreachable
root@EQ12-Debian:~# ip -6 route add fe80::42:aff:fe05:2ca dev ${host_macvlan_name}
root@EQ12-Debian:~# ping6 fe80::42:aff:fe05:2ca
PING fe80::42:aff:fe05:2ca(fe80::42:aff:fe05:2ca) 56 data bytes
64 bytes from fe80::42:aff:fe05:2ca%enp2s0-macvlan: icmp_seq=1 ttl=64 time=0.126 ms
64 bytes from fe80::42:aff:fe05:2ca%enp2s0-macvlan: icmp_seq=2 ttl=64 time=0.057 ms
64 bytes from fe80::42:aff:fe05:2ca%enp2s0-macvlan: icmp_seq=3 ttl=64 time=0.057 ms
64 bytes from fe80::42:aff:fe05:2ca%enp2s0-macvlan: icmp_seq=4 ttl=64 time=0.042 ms
^C
--- fe80::42:aff:fe05:2ca ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3055ms
rtt min/avg/max/mdev = 0.042/0.070/0.126/0.032 ms
root@EQ12-Debian:~# 

端口转发

懂的都懂

ncat -l -p 18080 --sh-exec "nc ${container_ip1} 18888"

然后访问宿主机的18080端口即可访问到容器的18888

资料参考docker妙用 篇十四:docker的macvlan网络不会搞?它其实很简单