网络第一次课实验
docker网络第一节课实验
一、Docker 中的网络功能介绍(原理)
检查是否开启路由转发
[root@daring ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
[root@daring ~]# docker run -d -P docker.io/jasonperma/centos6_http_ssh
18a82f52edfbf05db01c7dceea723d74fd047176912a4420d9d8e3f40bda1d60
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
18a82f52edfb docker.io/jasonperma/centos6_http_ssh "/bin/bash /run.sh" 10 seconds ago Up 3 seconds 0.0.0.0:32769->22/tcp, 0.0.0.0:32768->80/tcp sharp_ramanujan
此时访问本机的 32769端口即可访问容器内 ssh 应用。
[root@daring ~]# ssh [email protected] -p 32769
The authenticity of host '[192.168.142.165]:32769 ([192.168.142.165]:32769)' can't be established.
RSA key fingerprint is c2:70:72:11:7e:2a:6f:74:f9:88:18:c9:e5:4b:03:84.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[192.168.142.165]:32769' (RSA) to the list of known hosts.
[email protected]'s password:
注:192.168.142.165是宿主主机地址。
查看容器运行的httpd进程
[admin@18a82f52edfb ~]$ pgrep httpd
8
9
10
11
12
13
14
15
16
此时访问本机的 32768端口即可访问容器内 web 应用
-p(小写)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有
ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
注意: •容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量。) • -p 标记可以多次使用来绑定多个端口
映射所有接口地址:
使用 hostPort:containerPort 格式,将本地的10111端口映射到容器的 22 端口,本地的801端口映射到容器的80端口可以执行
[root@daring ~]# docker run -d -p 10111:22 -p 801:80 centos:http
66f19ff7d4f4f449917fa9473b9d1607e5773f7e8d26ea38c960868a2a6d941d
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
66f19ff7d4f4 centos:http "/bin/bash /run.sh" 49 seconds ago Up 20 seconds 443/tcp, 0.0.0.0:10111->22/tcp, 0.0.0.0:801->80/tcp drunk_noether
测试访问:
1) ssh测试: 使用xshell工具:
[admin@66f19ff7d4f4 ~]$ ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:56 errors:0 dropped:0 overruns:0 frame:0
TX packets:39 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:6384 (6.2 KiB) TX bytes:5387 (5.2 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
[admin@66f19ff7d4f4 ~]$ ip r
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2
测试web访问
映射到指定地址的指定端口
可以使用 ip:hostPort:containerPort 格式,指定映射使用一个特定地址,比如宿主机网卡配置的一个地址192.168.1.102
[root@daring ~]# docker run -dit -p 192.168.142.165:10112:22 -p 192.168.142.165:80:80 centos:http
33e8b01c7d3ec212b708eb1b04a3820a015ec055b7adf322969f409068c87145
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
33e8b01c7d3e centos:http "/bin/bash /run.sh" 4 seconds ago Up 3 seconds 192.168.142.165:80->80/tcp, 443/tcp, 192.168.142.165:10112->22/tcp tiny_goldstine
映射到指定地址的任意端口
使用 ip::containerPort 绑定192.168.1.102的任意端口到容器的80端口,本地主机会自动分配一个口。--name为启动的容器指定一个容器名。
[root@daring ~]# docker run -d -p 192.168.142.165::80 --name webserver centos:http
449aa79e8dcba836f42bf1242851f0119eb003bdaa98fa1fca97e37c087f8f0d
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
449aa79e8dcb centos:http "/bin/bash /run.sh" 47 seconds ago Up 46 seconds 22/tcp, 443/tcp, 192.168.142.165:32768->80/tcp webserver
注:还可以使用 udp 标记来指定 udp 端口
# docker run -d -p 127.0.0.1:5000:5000/udp –name db4 commit:v1
[root@daring ~]# docker run -d -p 127.0.0.1:5000:5000/udp --name db4 centos:http
064cd9144bcc4145fc27f1da5afb012df2214fca390536630b30c7842e288119
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
064cd9144bcc centos:http "/bin/bash /run.sh" 2 seconds ago Up 1 seconds 22/tcp, 80/tcp, 443/tcp, 127.0.0.1:5000->5000/udp db4
查看映射端口配置
使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址
[root@daring ~]# docker port webserver
80/tcp -> 192.168.142.165:32768
Docker NAT iptables实现
默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器
1.容器访问外部实现
容器所有到外部网络的连接,源地址都会被 NAT 成本地系统的 IP 地址(即docker0地址)。这是使用 iptables 的源地址伪装操作实现的
查看主机的 NAT 规则
[root@daring ~]# iptables -t nat -vnL
...//省略
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1 72 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
88 6684 POSTROUTING_direct all -- * * 0.0.0.0/0 0.0.0.0/0
88 6684 POSTROUTING_ZONES_SOURCE all -- * * 0.0.0.0/0 0.0.0.0/0
88 6684 POSTROUTING_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0
...//省略
其中,上述规则将所有源地址在 172.17.0.0/16 网段,目标地址为其他网段(外部网络)的流量动态伪装为从系统网卡发出。MASQUERADE 跟传统 SNAT 的好处是它能动态从网卡获取地址。
2.外部访问容器实现
容器允许外部访问,可以在 docker run 时候通过 -p 或 -P 参数来启用,不管用那种办法,其实也是在本地的 iptable 的 nat 表中添加相应的规则
使用 -P 时:
[root@daring ~]# docker run -d -P centos:http
28ec06f8fe3bc93ab42f826c1532327dc44a0030fd3cfa0e7f7dc31433120e6c
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28ec06f8fe3b centos:http "/bin/bash /run.sh" 2 seconds ago Up 1 seconds 0.0.0.0:32770->22/tcp, 0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp sleepy_wozniak
# iptables -t nat –nvL
[root@daring ~]# iptables -t nat -nvL
...//省略
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:32768 to:172.17.0.2:443
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:32769 to:172.17.0.2:80
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:32770 to:172.17.0.2:22
使用 -p 80:80 时:
[root@daring ~]# docker run -d -p 192.168.142.165:80:80 centos:http
331413e4ae7f9d62d34e95876bd8067c0b0e1821a733ce6e18c108f49ae7c864
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
331413e4ae7f centos:http "/bin/bash /run.sh" 2 seconds ago Up 1 seconds 22/tcp, 443/tcp, 192.168.142.165:80->80/tcp hopeful_kowalevski
# iptables -t nat –nvL
[root@daring ~]# iptables -t nat -nvL
...//省略
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 192.168.142.165 tcp dpt:80 to:172.17.0.2:80
...//省略
3.docker0 网桥
Docker服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。
Docker 默认指定了 docker0 接口的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信 由于目前 Docker 网桥是 Linux 网桥,用户可以使用 brctl show 来查看网桥和端口连接信息。
[root@daring ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02427de56e4b no veth24b899a
注:brctl 命令在centos中可以使用yum install bridge-utils 来安装 每次创建一个新容器的时候,Docker 从可用的地址段中选择一个空闲的 IP 地址分配给容器的 eth0端口。使用本地主机上 docker0 接口的 IP 作为所有容器的默认网关。
[root@daring ~]# docker run -d -P centos:http
b5bb1505c35c6f3ec26f14d913a9c57a05f51ea844cbd330734f20d09e957456
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5bb1505c35c centos:http "/bin/bash /run.sh" 3 seconds ago Up 1 seconds 0.0.0.0:32773->22/tcp, 0.0.0.0:32772->80/tcp, 0.0.0.0:32771->443/tcp small_jang
[root@daring ~]# ssh [email protected] -p 32773
The authenticity of host '[192.168.142.165]:32773 ([192.168.142.165]:32773)' can't be established.
RSA key fingerprint is 70:8d:e2:a3:b3:26:b0:91:9c:d0:df:7e:a8:de:8b:91.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[192.168.142.165]:32773' (RSA) to the list of known hosts.
[email protected]'s password:
[admin@b5bb1505c35c ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
[admin@b5bb1505c35c ~]$ ip r
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2
[admin@b5bb1505c35c ~]$
二、Docker 网络配置
Docker 四种网络模式
docker run 创建 Docker 容器时,可以用 --net 选项指定容器的网络模式,Docker 有以下 4 种网络模式:
- host 模式,使用
--net=host
指定。 - container 模式,使用
--net=container:NAMEorID
指定。 - none 模式,使用
--net=none
指定。 - bridge 模式,使用
--net=bridge
指定,默认设置。
1.host 模式
如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。
例如,我们在192.168.1.102/24 的机器上用 host 模式启动一个含有 web 应用的 Docker 容器,监听 tcp 80 端口。当我们在容器中执行任何类似 ifconfig 命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用192.168.1.102:80 即可,不用任何 NAT 转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
启动容器前,执行pgrep http查看宿主机httpd进程
[root@daring ~]# pgrep httpd
[root@daring ~]#
上面显示结果说明宿主机没有httpd进程运行
用 host 模式启动一个含有 web 应用的 Docker 容器
[root@daring ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/jasonperma/centos6_http_ssh latest 2460b63219d7 2 days ago 291.9 MB
centos http b097bfe56b56 6 days ago 291.7 MB
docker.io/centos centos6 cf2c3ece5e41 4 weeks ago 194.6 MB
[root@daring ~]# docker run -dit --net=host centos:http
b6c903551d938f502a2a9d980a534769d0cdd8a9b124190301464411fed7f427
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b6c903551d93 centos:http "/bin/bash /run.sh" 4 seconds ago Up 3 seconds condescending_bose
[root@daring ~]# pgrep httpd
4776
4777
4778
4779
4780
4781
4782
4783
4784
用浏览器访问宿主机地址的80端口
注意防火墙:
[root@daring ~]# firewall-cmd --add-port=80/tcp
Warning: ALREADY_ENABLED
2.container 模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。 运行一个容器:查看容器的IP
[root@daring ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/jasonperma/centos6_http_ssh latest 2460b63219d7 2 days ago 291.9 MB
centos http b097bfe56b56 6 days ago 291.7 MB
docker.io/centos centos6 cf2c3ece5e41 4 weeks ago 194.6 MB
[root@daring ~]# docker run -it docker.io/centos:centos6
[root@1c698500f24b /]# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:508 (508.0 b) TX bytes:508 (508.0 b)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
[root@1c698500f24b /]# [root@daring ~]#
将容器切换到后台运行:ctrl+p ctrl+q
在运行一个容器使用container模式:查看新容器的地址
[root@daring ~]# docker run -it --net=container:1c698500f24b docker.io/centos:centos6
[root@1c698500f24b /]# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 b) TX bytes:648 (648.0 b)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
[root@1c698500f24b /]#
3.none模式
这个模式和前两个不同。在这种模式下,Docker 容器拥有自己的Network Namespace,但是,并不为 Docker容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。
4.bridge模式
当 docker 启动时,会在主机上创建一个 docker0 的虚拟网卡。他随机挑选 RFC1918 私有网络中的一段地址给 docker0 。比如 172.17.0.1/16,16 位掩码的网段可以拥有 65534 个地址可以使用,这对主机和容器来说应该足够了。
docker0 不是普通的网卡,他是桥接到其他网卡的虚拟网卡,容器使用它来和主机相互通信。当创建一个 docker 容器的时候,它就创建了一个对接口,当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包,它们是绑在一起的一对孪生接口。这对接口在容器中那一端的的名字是 eth0 ,宿主主机端的会指定一个唯一的名字,比如 vethAQI2QT 这样的名字。 所有的 veth* 的接口都会桥接到 docker0 ,这样 docker 就创建了在主机和所有容器之间一个虚拟共享网
Docker完成以上网络配置的过程大致是这样的(总结):
1.在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
2.Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以veth65f9这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show命令查看。 注:brctl 工具依赖 bridge-utils 软件包
[root@daring ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02427de56e4b no vethea01325
3.从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。 容器内部访问外网以及容器和主机之间的端口映射都是通过Iptables实现的,可以查看Iptables表分析。
查看当前 docker0地址
[root@daring ~]# ifconfig docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:7dff:fee5:6e4b prefixlen 64 scopeid 0x20<link>
ether 02:42:7d:e5:6e:4b txqueuelen 0 (Ethernet)
RX packets 230 bytes 46455 (45.3 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 205 bytes 23454 (22.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
在容器运行时,每个容器都会分配一个特定的虚拟机口并桥接到 docker0。每个容器都会配置同 docker0 ip 相同网段的专用 ip 地址,docker0 的 IP 地址被用于所有容器的默认网关。 运行一个容器:
[root@daring ~]# docker run -dit centos:http
c6cf0334ea269c41d37cb286cfdeba04268cf16544434a11c1e21c975ae77f41
查看当前运行的容器:
[root@daring ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c6cf0334ea26 centos:http "/bin/bash /run.sh" 4 seconds ago Up 4 seconds 22/tcp, 80/tcp, 443/tcp stoic_hypatia
1c698500f24b docker.io/centos:centos6 "/bin/bash" 3 minutes ago Up 3 minutes cocky_bartik
通过brctl show命令查看
[root@daring ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02427de56e4b no vethb210cab
vethea01325
以上, docker0 扮演着stoic_hypatia和 cocky_bartik这两个容器的虚拟接口 vethxx interface 桥接的角色。
执行docker network inspect bridge查看桥接网络的详细信息
[root@daring ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "e558507c9c2e26602c38d49ef841cf0cf17b8b22edef6b312e8be71ef696f05a",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Containers": {
"1c698500f24ba2043cc13a24b1735913fd4d9954d788f12da3cf3b0251b9e536": {
"Name": "cocky_bartik",
"EndpointID": "2e038ff3e2a670e796309de7e2d71f03d247caec69d7c1bcee19198f342b0266",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"c6cf0334ea269c41d37cb286cfdeba04268cf16544434a11c1e21c975ae77f41": {
"Name": "stoic_hypatia",
"EndpointID": "69d17d62606f50f256be4c28a42621be6d050a83783dfef7191c62d836eb6711",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
}
}
]
三、自定义网桥
除了默认的 docker0 网桥,用户也可以指定网桥来连接各个容器。在启动 Docker 服务的时候,使用 -b BRIDGE 或 --bridge=BRIDGE 来指定使用的网桥。 Docker 允许你管理 docker0 桥接或者通过-b选项自定义桥接网卡,需要安装bridge-utils软件包。
基本步骤如下:
1.确保docker的进程是停止的
2.创建自定义网桥
3.给网桥分配特定的 ip
4.以 -b 的方式指定网桥
具体操作步骤:
1.如果服务已经运行,那需要先停止服务,并删除旧的网桥
[root@daring ~]# systemctl stop docker
[root@daring ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Tue 2016-08-02 11:39:04 CST; 4s ago
Docs: http://docs.docker.com
Process: 1518 ExecStart=/bin/sh -c /usr/bin/docker-current daemon
...//省略
[root@daring ~]# ip link set dev docker0 down
[root@daring ~]# brctl delbr docker0
[root@daring ~]# brctl show
bridge name bridge id STP enabled interfaces
2.然后创建一个网桥 bridge0,
[root@daring ~]# brctl addbr bridge0
3.给网桥分配特定的 ip
[root@daring ~]# ip addr add 192.168.10.1/24 dev bridge0
[root@daring ~]# ip link set dev bridge0 up
4.查看确认网桥创建并启动
[root@daring ~]# brctl show
bridge name bridge id STP enabled interfaces
bridge0 8000.000000000000 no
或
[root@daring ~]# ip addr show bridge0
26: bridge0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
link/ether ce:b8:f9:37:75:d3 brd ff:ff:ff:ff:ff:ff
inet 192.168.10.1/24 scope global bridge0
valid_lft forever preferred_lft forever
inet6 fe80::ccb8:f9ff:fe37:75d3/64 scope link
valid_lft forever preferred_lft forever
修改/etc/sysconfig/docker文件
修改前:
OPTIONS='--selinux-enabled --log-driver=journald'
修改后:添加前面所新建的网桥
[root@daring ~]# vim /etc/sysconfig/docker
[root@daring ~]# cat /etc/sysconfig/docker | grep -v "#" | grep -v "^$"
OPTIONS='--selinux-enabled --log-driver=journald -b=bridge0'
DOCKER_CERT_PATH=/etc/docker
[root@daring ~]#
启动 Docker 服务。
[root@daring ~]# systemctl start docker
[root@daring ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2016-08-02 11:43:31 CST; 4s ago
Docs: http://docs.docker.com
Main PID: 5532 (sh)
...//省略
新建一个容器,可以看到它已经桥接到了 bridge0 上。
[root@daring ~]# docker run -dit docker.io/centos:centos6
4ce36687d391c107edd824c5d7bf56491ea4cda607c211313b9efcfb6036e463
[root@daring ~]# brctl show
bridge name bridge id STP enabled interfaces
bridge0 8000.46345a536e04 no veth46c9c2b
进入容器,查看容器的IP
[root@daring ~]# docker attach 4ce36687d391c107edd824c5d7bf56491ea4cda607c211313b9efcfb6036e463
[root@4ce36687d391 /]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:0A:02
inet addr:192.168.10.2 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::42:c0ff:fea8:a02/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 b) TX bytes:648 (648.0 b)
docker 服务启动成功并绑定容器到新的网桥,新建一个容器,你会看到它的 ip 是我们的设置的新 ip段, docker 会自动检测到它。用 brctl show 可以看到容器启动或则停止后网桥的配置变化,在容器中使用 ip a 和 ip r 来查看 ip 地址配置和路由信息。
下面通过配置一个以 --net=none 启动的容器,使他达到跟平常一样具有访问网络的权限。来介绍docker 是如何连接到容器中的。
启动一个运行 /bin/bash的容器,并指定 --net=none
[root@daring ~]# docker run -it --net=none docker.io/centos:centos6 /bin/bash
[root@18a82f52edfb /]# ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
[root@18a82f52edfb /]#
再开启一个新的终端,查找这个容器的进程 id ,然后创建它的命名空间,后面的 ip netns 会用到
[root@daring ~]# docker inspect -f '{{.State.Pid}}' 18a82f52edfb
3574
[root@daring ~]# mkdir -p /var/run/netns
[root@daring ~]# ln -s /proc/3574/ns/net /var/run/netns/3574
[root@daring ~]# ls /var/run/netns/3574
/var/run/netns/3574
[root@daring ~]# ls -l /var/run/netns/3574
lrwxrwxrwx 1 root root 17 Aug 1 21:57 /var/run/netns/3574 -> /proc/3574/ns/net
查看桥接网卡的ip和子网掩码
[root@daring ~]# ip addr show docker0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:7d:c6:fb:fc brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
创建一对"peer"接口A和B,编订A到网桥,并启用它
[root@daring ~]# ip link add A type veth peer name B [root@daring ~]# brctl addif docker0 A [root@daring ~]# ip link set A up [root@daring ~]# ifconfig A: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 ether 66:e0:50:69:10:b4 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ...//省略
将B放到容器的网络命名空间,命名为eth0,配置一个空闲的ip
[root@daring ~]# ip link set B netns 3574
[root@daring ~]# ip netns exec 3574 ip link set dev B name eth0
[root@daring ~]# ip netns exec 3574 ip link set eth0 up
[root@daring ~]# ip netns exec 3574 ip addr add 172.17.0.100/16 dev eth0
[root@daring ~]# ip netns exec 3574 ip route add default via 172.17.0.1
到此为止,容器可以正常使用网络了
[root@18a82f52edfb /]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 3A:FE:DC:90:B3:61
inet addr:172.17.0.100 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::38fe:dcff:fe90:b361/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:16 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1296 (1.2 KiB) TX bytes:648 (648.0 b)
[root@18a82f52edfb /]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
[root@18a82f52edfb /]# nslookup www.baidu.com
Server: 192.168.142.2
Address: 192.168.142.2#53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name: www.a.shifen.com
Address: 61.135.169.125
Name: www.a.shifen.com
Address: 61.135.169.121