模拟Docker为容器建立bridge网络
- 1. 安装docker
- 2. 创建Nginx容器
- 3. 手动为容器设置网络
- 4. 验证网络
在阅读本文之前,请先了解一下linux的namespace机制
1. 安装docker
- Centos下安装,执行
yum install docker-ce -y
- Ubuntu下安装,执行
apt install docker.io
2. 创建Nginx容器
我们首先先执行docker run -d nginx
正常创建一个nginx容器
可以看到,此时的容器是已经建立了网络的,并且主机能正常ping通容器
$ docker ps|grep nginx
a532088aa958 nginx "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 80/tcp youthful_chaplygin
$ docker inspect a532088aa958 | grep -i pid
"Pid": 4078,
"PidMode": "",
"PidsLimit": null,
$ nsenter -t 4078 -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
$ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.073 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.069 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.059 ms
接下来我们将创建一个未设置网络的容器
$ docker run --network=none -d nginx
接下来先获取该容器在主机中的pid
$ docker ps|grep nginx
5684405f85b7 nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes nostalgic_lamarr
a532088aa958 nginx "/docker-entrypoint.…" 12 minutes ago Up 12 minutes 80/tcp youthful_chaplygin
$ docker inspect 5684405f85b7 | grep -i pid
"Pid": 4267,
"PidMode": "",
"PidsLimit": null,
我们可以先查看下该容器的网络,可以看到此时容器内的网络是没有经过配置的
$ nsenter -t 4267 -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
3. 手动为容器设置网络
首先,我们为容器创建它的network namespace
$ mkdir -p /var/run/netns
然后我们将/proc/$pid/ns/net
的network namespace和/var/run/netns/$pid
的namespace链接起来,这样做的好处的可以通过执行ip netns list
就可以看到netns的namespace
$ ip netns list
$ export pid=4267
$ ln -s /proc/$pid/ns/net /var/run/netns/$pid
$ ip netns list
4267
查看docker默认网桥的信息,一会为容器设置网络信息的时候要用到
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02422d2cb61b no veth19222f6
$ ip addr show docker0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:2d:2c:b6:1b brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:2dff:fe2c:b61b/64 scope link
valid_lft forever preferred_lft forever
接下来创建一个veth peer,这个相当于一根网线,有A和B两头,我们把A查到docker0的网桥上,然后把B插到容器上,并将两端点亮
$ ip link add A type veth peer name B
$ brctl addif docker0 A
$ ip link set A up
$ ip link set B netns $pid
接下来,为容器配置网络信息
$ SETIP=172.17.0.10
$ SETMASK=16
$ GATEWAY=172.17.0.1
$ ip netns exec $pid ip link set dev B name eth0
$ ip netns exec $pid ip link set eth0 up
$ ip netns exec $pid ip addr add $SETIP/$SETMASK dev eth0
$ ip netns exec $pid ip route add default via $GATEWAY
4. 验证网络
最后我们执行curl 172.17.0.10
访问容器,能访问到nginx,证明主机和容器间的网络已经通了
$ curl 172.17.0.10
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)