一、Docker的原生网络
docker network 子命令
connect 连接容器到指定网络
create 创建网络
disconnect 断开容器与指定网络的连接
inspect 显示指定网络的详细信息
ls 显示所有网络
rm 删除网络
docker-compose up #启动所有服务
docker-compose stop #停止正在运行的容器,可以通过docker-compose start 再次启动
docker-compose down #停止和删除容器、网络、卷、镜像。(#停用移除所有容器以及网络相关)
docker安装后会自动创建3种网络:bridge(桥接)、host(主机网络)、none(禁用)
1、docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口。
[root@server1 ~]# yum install -y bridge-utils 安装网桥管理工具包 (brctl show 查询网桥信息)容器网络以桥接的方式桥接到宿主机上
[root@server1 ~]# docker inspect demo 可以看到容器的网关就是宿主机的桥接 172.17是所有容器的地址 0.1是网关 其他容器ip地址是动态分配以单调递增的方式来进行分配 被占用则不能用 如果容器停止它所占用的ip将释放出来给其他的容器 由于此机制 容器重启之后与原来的ip地址不一样
bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。容器通过虚拟网卡veth数据包到达docker0网桥在由linux内核数据包路由到eth0出去
2、host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。
host网络模式需要在容器创建时指定 --network=host
[root@server1 ~]# docker run -d --name demo --network host nginx
a206df944a2a453a61b447cfb765d5e088f5e2cbfb76c8f6fb788ef8dfee52cc
[root@server1 ~]# brctl show 查询网桥信息 没有桥接
bridge name bridge id STP enabled interfaces
docker0 8000.0242258ffab5 no
[root@server1 ~]# ip addr 没有新建网络
1: lo: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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0:mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:81:ab:94 brd ff:ff:ff:ff:ff:ff
inet 172.25.15.1/24 brd 172.25.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe81:ab94/64 scope link
valid_lft forever preferred_lft forever
3: docker0:mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:25:8f:fa:b5 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:25ff:fe8f:fab5/64 scope link
valid_lft forever preferred_lft forever
[root@server1 ~]# systemctl status nginx 没有开nginx
● nginx.service - The NGINX HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: inactive (dead)
3、none模式是指禁用网络功能,只有lo接口,在容器创建时使用 --network=none指定。
[root@server1 ~]# docker inspect demo | grep Pid 创建容器时容器会有自己的id
"Pid": 16354,
"PidMode": "",
"PidsLimit": null,
/ns/(namespace)目录下有demo容器的6种命名空间 demo容器基本上作为独立的主机存在 容器在运行时通过这6种命名空间相对安全做了隔离 没有完全隔离很多东西和宿主机共享
清理实验环境
[root@server1 ns]# docker network ls
NETWORK ID NAME DRIVER SCOPE
12fd840f32fd bridge bridge local
cec1ef142c8c host host local
4e5caf1b11f4 none null local
[root@server1 ns]# docker rm -f demo
demo
二、Docker自定义网络
自定义网络模式,docker提供了三种自定义网络驱动: bridge overlay macvlan
bridge驱动类似默认的bridge网络模式,但增加了一些新的功能, overlay和macvlan是用于创建跨主机网络。
[root@server1 ns]# docker network create mynet1
95c68a27938578f4a7bb61e0bd4c5e934eb2470b8e317eaa2816d43391dd1f02
[root@server1 ns]# docker network ls
NETWORK ID NAME DRIVER SCOPE
12fd840f32fd bridge bridge local
cec1ef142c8c host host local
95c68a279385 mynet1 bridge local
4e5caf1b11f4 none null local
[root@server1 ns]# docker run -it --rm --network mynet1 busybox
/ # ping demo1
PING demo1 (172.23.0.2): 56 data bytes
64 bytes from 172.23.0.2: seq=0 ttl=64 time=0.112 ms
64 bytes from 172.23.0.2: seq=1 ttl=64 time=0.080 ms
^C
--- demo1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.080/0.096/0.112 ms
/ #
[root@server1 ns]# docker run -it --rm --network mynet1 busybox
/ # ping demo1
PING demo1 (172.23.0.3): 56 data bytes
64 bytes from 172.23.0.3: seq=0 ttl=64 time=0.097 ms
64 bytes from 172.23.0.3: seq=1 ttl=64 time=0.083 ms
64 bytes from 172.23.0.3: seq=2 ttl=64 time=0.082 ms
64 bytes from 172.23.0.3: seq=3 ttl=64 time=0.081 ms
^C
--- demo1 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.081/0.085/0.097 ms
/ # ping demo2
PING demo2 (172.23.0.2): 56 data bytes
64 bytes from 172.23.0.2: seq=0 ttl=64 time=0.132 ms
64 bytes from 172.23.0.2: seq=1 ttl=64 time=0.080 ms
^C
--- demo2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.080/0.106/0.132 ms
/ #
docker自定义网段在创建时指定参数:--subnet 、--gateway
使用--ip参数可以指定容器ip地址,但必须是在自定义网桥上,默认的bridge模式不支持,同一网桥上的容器是可以互通的。
[root@server1 ns]# docker network ls
NETWORK ID NAME DRIVER SCOPE
12fd840f32fd bridge bridge local
cec1ef142c8c host host local
95c68a279385 mynet1 bridge local
4e5caf1b11f4 none null local
[root@server1 ns]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ff0f3e84bf3 nginx "/docker-entrypoint.…" 13 minutes ago Up 13 minutes 80/tcp demo2
6effdb7ac322 nginx "/docker-entrypoint.…" 22 minutes ago Up 13 minutes 80/tcp demo1[root@server1 ns]# docker run -d --name demo3 --network mynet1 --ip 172.23.0.10 nginx
5b3d1a0b5ba04931ca215d9fbf3b8e695bb00fe7b44ee8b93d64c56382b3da03
docker: Error response from daemon: user specified IP address is supported only when connecting to networks with user configured subnets. 只有配置子网才能指定ip
[root@server1 ns]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b3d1a0b5ba0 nginx "/docker-entrypoint.…" 2 minutes ago Created demo3
4ff0f3e84bf3 nginx "/docker-entrypoint.…" 17 minutes ago Up 17 minutes 80/tcp demo2
6effdb7ac322 nginx "/docker-entrypoint.…" 26 minutes ago Up 16 minutes 80/tcp demo1
[root@server1 ns]# docker rm -f demo1
demo1
[root@server1 ns]# docker rm -f demo2
demo2
[root@server1 ns]# docker rm -f demo3
demo3
[root@server1 ns]# docker network rm mynet1
mynet1
[root@server1 ns]# docker run -d --name demo2 --network mynet2 --ip 172.30.0.10 nginx
1d7670934b049577e3c42cc255418d680aa21b94f1da205e139cee9c6adbbc6b
[root@server1 ns]# brctl show 不同的容器桥接到不同的网桥上
bridge name bridge id STP enabled interfaces
br-7ace48192525 8000.024292b7c209 no veth36e866f
br-ee2e2bfae934 8000.02422b17f726 no veth5ffe06f
docker0 8000.0242258ffab5 no
桥接到不同网桥上的容器,彼此是不通信的。 docker在设计上就是要隔离不同network的。
那么如何使两个不同网桥的容器通信呢: 使用 docker network connect命令为serene_wozniak添加一块my_net1的网卡。
三、Docker的容器通信
容器之间除了使用ip通信外,还可以使用容器名称通信。
docker 1.10开始,内嵌了一个DNS server。
dns解析功能必须在自定义网络中使用。
启动容器时使用 --name 参数指定容器名称。
Joined容器一种较为特别的网络模式。 在容器创建时使用--network=container:vm1指定。(vm1指定的是运行的容器名)
处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。
busybox和demo两个容器使用相同的网络栈 网络资源唯一 它们监听资源的端口不能重复 demo使用nginx镜像 已经开通80端口 如果一个容器已经占取80端口 第二个容器在占取80端口 势必会冲突
--link 可以用来链接2个容器。
--link的格式: --link
name和id是源容器的name和id,alias是源容器在link下的别名
容器如何访问外网是通过iptables的SNAT实现的
外网访问容器用到了docker-proxy和iptables DNAT
宿主机访问本机容器使用的是iptables DNAT
外部主机访问容器或容器之间的访问是docker-proxy实现
当从外部网络访问172.25.15.1的80端口时会被重定向172.17.0.2的80端口( 访问宿主机80端口直接被重定向到80端口)
当删除docker映射端口时 外网依然可以访问
四、跨主机容器通信
跨主机网络解决方案
docker原生的overlay(docker集群)和macvlan
众多网络方案是如何与docker集成在一起的
libnetwork docker容器网络库
CNM (Container Network Model)这个模型对容器网络进行了抽象
CNM分三类组件
Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace)
Endpoint:作用是将sandbox接入network (veth pair)
Network:包含一组endpoint,同一network的endpoint可以通信。
macvlan网络方案实现
Linux kernel提供的一种网卡虚拟化技术。 无需Linux bridge,直接使用物理接口,性能极好。
在两台docker主机上各添加一块网卡,打开网卡混杂模式: # ip link set eth1 promisc on
本次实验演示macvlan网络方案
1、不添加网卡的方式
分别打开server1和server2的eth0网卡的混杂模式
查看两台主机网卡混杂模式是否开启并且网卡必须是激活(up)状态
创建私有网络 -d 指定驱动类型 (macvlan网络方式)-o 父级 使用物理接口进行通信 不用添加新的虚拟网卡
查看没有新的虚拟网卡 没有桥接
macvlan网络结构分析
没有新建linux bridge
容器的接口直接与主机网卡连接,无需NAT或端口映射。
2、添加网卡方式
查看添加eth1网卡 激活eth1网卡并打开eth1网卡的混杂模式
不指定mynet2 的ip地址会随机分取
macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094。
通过子接口的方式来进行创建不一样的虚拟网络
macvlan网络间的隔离和连通
macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。
可以在三层上通过网关将macvlan网络连通起来。
docker本身不做任何限制,像传统vlan网络那样管理即可。