本章内容
1.dokcer 默认自带的几种网络介绍
2. 自定义网络
3. 容器间通信
4. 容器与外界交互
docker 网络分为单个主机上的容器网络和多个主机上的哇网络, 本文主要讲解单个主机上的容器网络.
Docker 的四种网络模式
一. bridge 模式
docker 网络隔离基于网络命名空间, 在物理机上创建 docker 容器时会为每一个 docker 容器分配网络命名空间, 并且把容器 IP 桥接到物理机的虚拟网桥上.
二. none 模式
此模式下创建容器是不会为容器配置任何网络参数的, 如: 容器网卡, IP, 通信路由等, 全部需要自己去配置.
三. host 模式
此模式创建的容器没有自己独立的网络命名空间, 是和物理机共享一个 Network Namespace, 并且共享物理机的所有端口与 IP, 并且这个模式认为是不安全的.
四. container 模式
此模式和 host 模式很类似, 只是此模式创建容器共享的是其他容器的 IP 和端口而不是物理机, 此模式容器自身是不会配置网络和端口, 创建此模式容器进去后, 你会发现里边的 IP 是你所指定的那个容器 IP 并且端口也是共享的, 而且其它还是互相隔离的, 如进程等.
1. dokcer 默认自带的几种网络介绍
一, none
二, host
三, bridge
可以使用如下命令进行查看
- [[email protected] ~]# docker network ls
- NETWORK ID NAME DRIVER SCOPE
- d8cf2efc8881 bridge bridge local
- 2fb7c9abfab5 host host local
- d300d17755a4 none null local
一, none 网络
none 网络没有网络, 只有 lo 即本地地址, 没有任何的网卡. 创建容器时可以使用 - network=none 来指定 none 网络:
- [[email protected] ~]# docker run --network=none -it busybox
- / # ip a
- 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
- link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
- .NET 127.0.0.1/8 scope host lo
- valid_lft forever preferred_lft forever
none 网络的应用场景主要是用于对于安全性要求比较高的场景.
二, host 网络
连接到 host 的网络的容器共享主机的网络栈, 容器的网络配置与宿主机完全一样, 创建容器时可以通过 - network=host 指定使用 host 网络:
- [[email protected] ~]# docker run --network=host -it busybox
- / # ip a
- 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
- link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
- .NET 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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
- link/ether 00:0c:29:2d:5b:b8 brd ff:ff:ff:ff:ff:ff
- .NET 172.20.10.2/24 brd 172.20.10.255 scope global eth0
- valid_lft forever preferred_lft forever
- inet6 2408:84e1:41:da2a:20c:29ff:fe2d:5bb8/64 scope global dynamic
- valid_lft forever preferred_lft forever
- inet6 fe80::20c:29ff:fe2d:5bb8/64 scope link
- valid_lft forever preferred_lft forever
- 3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue qlen 1000
- link/ether 52:54:00:da:70:83 brd ff:ff:ff:ff:ff:ff
- .NET 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
- valid_lft forever preferred_lft forever
- 4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 qlen 1000
- link/ether 52:54:00:da:70:83 brd ff:ff:ff:ff:ff:ff
- 5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
- link/ether 02:42:59:83:33:89 brd ff:ff:ff:ff:ff:ff
- .NET 172.17.0.1/16 brd 172.17.255.255 scope global docker0
- valid_lft forever preferred_lft forever
- inet6 fe80::42:59ff:fe83:3389/64 scope link
- valid_lft forever preferred_lft forever
- 35: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0
- link/ether 3e:ba:6b:44:3a:e6 brd ff:ff:ff:ff:ff:ff
- inet6 fe80::3cba:6bff:fe44:3ae6/64 scope link
- valid_lft forever preferred_lft forever
并且 hostname 也是宿主机的
/ # hostname ken1
直接使用主机的网络最大的好处就是性能, 如果容器对网络传输效率有较高的要求, 则可以选择宿主机的网络. 但是需要考虑端口冲突的问题, 宿主机已经使用的端口就不能再用了.
三, bridge 网络
docker 安装时会创建一个 docker0 的 Linux brdge. 如果不指定 - network, 创建的容器 more 都会挂到 docker0 上:
- [[email protected] ~]# brctl show
- bridge name bridge id STP enabled interfaces
- docker0 8000.024259833389 no
- virbr0 8000.525400da7083 yes virbr0-nic
当前的 docker0 上 interfaces 处没有任何其他的网络设备, 我们创建一个容器看看有什么变化:
- [[email protected] ~]# docker run -it busybox
- / #
- [[email protected] ~]# brctl show
- bridge name bridge id STP enabled interfaces
- docker0 8000.024259833389 no vethca1bd59
- virbr0 8000.525400da7083 yes virbr0-nic
再来看一下网卡信息
- [[email protected] ~]# 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
- .NET 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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
- link/ether 00:0c:29:2d:5b:b8 brd ff:ff:ff:ff:ff:ff
- .NET 172.20.10.2/24 brd 172.20.10.255 scope global noprefixroute eth0
- valid_lft forever preferred_lft forever
- inet6 2408:84e1:41:da2a:20c:29ff:fe2d:5bb8/64 scope global mngtmpaddr dynamic
- valid_lft forever preferred_lft forever
- inet6 fe80::20c:29ff:fe2d:5bb8/64 scope link
- valid_lft forever preferred_lft forever
- 3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
- link/ether 52:54:00:da:70:83 brd ff:ff:ff:ff:ff:ff
- .NET 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
- valid_lft forever preferred_lft forever
- 4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
- link/ether 52:54:00:da:70:83 brd ff:ff:ff:ff:ff:ff
- 5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
- link/ether 02:42:59:83:33:89 brd ff:ff:ff:ff:ff:ff
- .NET 172.17.0.1/16 brd 172.17.255.255 scope global docker0
- valid_lft forever preferred_lft forever
- inet6 fe80::42:59ff:fe83:3389/64 scope link
- valid_lft forever preferred_lft forever
- 41: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
- link/ether ca:82:1f:2a:2a:3d brd ff:ff:ff:ff:ff:ff link-netnsid 1
- inet6 fe80::c882:1fff:fe2a:2a3d/64 scope link
- valid_lft forever preferred_lft forever
使用 ip a 可以发现我们每启动一个容器相关的网卡信息也都会显示出来.
我们启动了一个容器, 产生了一个新的网络接口 vethca1bd59 被挂到了 docker0 上, vethca1bd59 就是新创建容器的虚拟网卡. 下面看一下容器的网络配置:
- [[email protected] ~]# docker run -it busybox
- / #
- / # ip a
- 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
- link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
- .NET 127.0.0.1/8 scope host lo
- valid_lft forever preferred_lft forever
- 40: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
- link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
- .NET 172.17.0.3/16 brd 172.17.255.255 scope global eth0
- valid_lft forever preferred_lft forever
容器有一个网卡 [email protected], 实际上[email protected] 和 vethccd6a69 是一对 veth pair.veth pair 是一种成对出现的椰树网络设备, 可以把它想象成一根虚拟网线连接起来的一对网卡, 网卡的一头 ([email protected]) 在容器中, 另一头 (vethca1bd59) 挂在 docker0 上, 其效果就是将 [email protected] 也挂在了 docker0 上.
可以看到 [email protected] 已经配置开了 IP 172.17.0.3, 那为什么会是这个网段那? 可以通过如下的命令查看网络的配置信息:
- [[email protected] ~]# docker network inspect bridge
- [
- {
- "Name": "bridge",
- "Id": "d8cf2efc88817902c3a1c8fff7adb22194ee3c78a427bda5b0543987c1db1bd7",
- "Created": "2019-01-26T20:27:17.164824695+08:00",
- "Scope": "local",
- "Driver": "bridge",
- "EnableIPv6": false,
- "IPAM": {
- "Driver": "default",
- "Options": null,
- "Config": [
- {
- "Subnet": "172.17.0.0/16",
- "Gateway": "172.17.0.1"
- }
- ...
原来 beidge 网络配置的 subnet 就是 172.17.0.0/16, 并且网关是 172.17.0.1, 其实这个网关就是 docker0.
容器创建时, docker 会自动从 172.17.0.0/16 中分配一个 IP.
2. 自定义网络
除了 none,host,bridge 这三个自动创建的网络, 用户也可以根据业务需要创建 user-defined 网络.
Docker 提供三种 user-defined 网络驱动: bridge, overlay 和 macvlan.overlay 和 macvlan 用于创建跨主机的网络, 后面单独讨论.
我们可通过 bridge 驱动创建类似前面默认的 bridge 网络, 例如:
新增了一个网桥 br-e2e6bf5189a6, 这里 br-e2e6bf5189a6 正好新建 bridge 网络 ken 的短 id. 执行 docker network inspect 查看一下 my_net 的配置信息:
这里 172.19.0.0/16 是 Docker 自动分配的 IP 网段.
我们可以自己指定 IP 网段吗?
答案是: 可以.
只需在创建网段时指定 --subnet 和 --gateway 参数:
- [[email protected] ~]# docker network create --driver bridge --subnet 172.21.0.0/16
- --gateway 172.21.0.1 ken3
查看网络
容器要使用新的网络, 需要在启动时通过 --network 指定:
到目前为止, 容器的 IP 都是 docker 自动从 subnet 中分配, 我们能否指定一个静态 IP 呢?
答案是: 可以, 通过 --ip 指定.
注: 只有使用 --subnet 创建的网络才能指定静态 IP.
3. 容器间通信
容器之间可通过 IP,Docker DNS Server 或 joined 容器三种方式通信.
我们接下来启动两个容器并且指定同一个网络验证是否可以通信:
可见同一网络中的容器, 网关之间都是可以通信的.
再 ping 一个不是同一个网段 的容器:
显然是不能通信的, 那如何实现不同网段之间的容器间的通信那?
答案是: 为 另外一个 容器添加一块 ken3 的网卡. 这个可以通过 docker network connect 命令实现.
[[email protected] ~]# docker network connect ken3 dc4c1258f267
查看网络信息
容器中增加了一块网卡 eth1, 分配了 ken3 的 IP, 现在两个容器之间就可以访问了.
从上面的列子可以得出这样一个结论: 两个容器要能通信, 必须要有属于同一个网络的网卡.
满足这个条件后, 容器就可以通过 IP 交互了. 具体做法是在容器创建时通过 --network 指定相应的网络, 或者通过 docker network connect 将现有容器加入到指定网络.
Docker DNS Server
通过 IP 访问容器虽然满足了通信的需求, 但还是不够灵活. 因为我们在部署应用之前可能无法确定 IP, 部署之后再指定要访问的 IP 会比较麻烦. 对于这个问题, 可以通过 docker 自带的 DNS 服务解决.
从 Docker 1.10 版本开始, docker daemon 实现了一个内嵌的 DNS server, 使容器可以直接通过 "容器名" 通信. 方法很简单, 只要在启动时用 --name 为容器命名就可以了.
使用 docker DNS 有个限制: 只能在 user-defined 网络中使用. 也就是说, 默认的 bridge 网络是无法使用 DNS 的. 下面验证一下:
joined 容器
joined 容器是另一种实现容器间通信的方式.
joined 容器非常特别, 它可以使两个或多个容器共享一个网络栈, 共享网卡和配置信息, joined 容器之间可以通过 127.0.0.1 直接通信. 请看下面的例子:
先创建一个 busybox 容器, 名字为 web1.
- [[email protected] ~]# docker run --rm -it --name=web1 busybox
- / #
查看信息
然后创建 busybox 容器并通过 --network=container:web1 指定 jointed 容器为 web1:
看! busybox 和 web1 的网卡 Mac 地址与 IP 完全一样, 它们共享了相同的网络栈. busybox 可以直接用 127.0.0.1 访问 web1.
joined 容器非常适合以下场景:
不同容器中的程序希望通过 loopback 高效快速地通信, 比如 Web server 与 App server.
希望监控其他容器的网络流量, 比如运行在独立容器中的网络监控程序.
4. 容器与外界交互
容器访问外部世界:
只要宿主机可以访问外网, 默认容器是可以访问外网的:
外部世界访问容器:
即端口映射详情参考我之前的文章《Docker 端口映射及创建镜像演示(二) https://www.cnblogs.com/kenken2018/p/10030567.html
Docker 网络(五)
来源: http://www.bubuko.com/infodetail-3164324.html