可以再找一些资料补充一下知识:(也没必要太全,毕竟不是运维)

1 Docker 网络端口映射

在启动容器的时候,可以配置容器的端口映射方式。一种是随机端口映射,一种是指定端口映射。

# 随机端口映射
docker run -d -P microweb python app.py
 
# 指定端口映射
# 将主机的 8123 端口与容器的 80 端口绑定
docker run -d -p 8123:80 microweb python app.py

docker port  命令可以让我们快捷地查看端口的绑定情况。

docker port microweb 80  # 127.0.0.1:8123

2 Docker 网络模式

Docker 网络模式有四种:bridge、host、none、container。

  • bridge 模式:为每一个容器分配、设置 IP 等,并将容器连接到一个  docker0。属于虚拟网桥,默认配置。
  • host 模式:容器将不会虚拟出自己的网卡、配置自己的 IP,而是使用宿主机的 IP 和端口。
  • none 模式:容器有独立的 network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网络链接、IP 等。
  • container 模式:新创建的容器不会创建自己的网卡和配置自己的 IP,而是和一个指定的容器共享 IP 、端口范围等。

在启动容器的时候可以指定 Docker 网络模式。

# 默认就是 bridge 模式
docker run -d -p 8081:8080 billygoo/tomcat8-jdk8
docker run -d -p 8081:8080 --network billygoo/tomcat8-jdk8
 
# host 模式,此时配置端口映射会 warning
docker run -d --network=host billygoo/tomcat8-jdk8
 
# none 模式
docker run -d --network=none billygoo/tomcat8-jdk8
 
# container 模式
docker run -d --network=container:NAME_OR_ID billygoo/tomcat8-jdk8

3 查看 Docker 网络命令

3.1 查看网络模式

docker network ls
---
NETWORK ID    NAME    DRIVER   SCOPE
a097979797    bridge  bridge   local
lkasjdfljl    host    host     local
sjaklfajas    none    null     local

3.2 查看网络信息

docker inspect a097979797
---
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
	"Driver": "default",
	"Options": null,
	"Config": [
		{
			"Subnet": "10.11.0.0/16",
			"Gateway": "10.11.0.1"
		}
	]
},

3.3 删除网络

docker network rm 网络名字

3.4 查看网络命令

docker network --help
---
docker network COMMAND
Commands:
  connect: connect a container to a network
  create: create a network
  disconnect: disconnect a container to a network
  inspect: display detailed info on one or more networks
  ls: list networks
  prune: remove all unused networks
  rm: remove one or more networks

4 了解 Docker 网络模式

Docker 网络模式的用处

  1. 容器间的互联和通信以及端口映射
  2. 容器 IP 变动时候可以通过服务名直接网络通信而不受到影响

Docker 容器 IP 地址分配

  1. 创建 docker1、docker2,通过 docker network inspect 观察两个的网络 IPAddress。
  2. 关闭 docker2,创建 docker3,再次观察 docker3 的网络 IPAddress,发现和原 docker2 的地址是一样的。

500
500

Docker 不启动,默认的网络情况

Docker @7 网络-2.png

在 CentOS7 的安装过程中如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的私网地址的 virbr0 网卡(virbr0 网卡:它还有一个固定的默认 IP 地址 192.168.122.1),是做虚拟机网桥的使用的,其作用是为连接其上的虚机网卡提供 NAT 访问外网的功能。

Docker 启动后,网络情况

会产生一个名为 docker0 的虚拟网桥。

Docker @7 网络-3.png

5 bridge 模式

Docker 服务默认会创建一个 Docker 容器网桥(其上有一个 docker0 内部接口),该桥接网络的名称为 docker0。Docker 容器上会有名为 eth0 的网卡接口与网桥上的 veth 接口进行一一匹配,从而彼此联通。

它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docker0 接口的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。

  1. Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0),Docker 启动一个容器时会根据 Docker 网桥的网段分配给容器一个 IP 地址,称为 Container-IP,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信。

  2. docker run 的时候,没有指定 network 的话默认使用的网桥模式就是 bridge,使用的就是 docker0。在宿主机 ifconfig,就可以看到 docker0 和自己 create 的 network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,lo 代表 127.0.0.1,即 localhost,inet addr 用来表示网卡的 IP 地址

  3. 网桥 docker0 创建一对对等虚拟设备接口一个叫 veth,另一个叫 eth0,成对匹配。

    1. 整个宿主机的网桥模式都是 docker0,类似一个交换机有一堆接口,每个接口叫 veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫 veth pair);
    2. 每个容器实例内部也有一块网卡,每个接口叫 eth0;
    3. docker0 上面的每个 veth 匹配某个容器实例内部的 eth0,两两配对,一一匹配。

通过上述,将宿主机上的所有容器都连接到这个内部网络上,两个容器在同一个网络下,会从这个网关下各自拿到分配的 ip,此时两个容器的网络是互通的。

425

验证 bridge 模式 - 容器 eth0 与主机 veth

docker run -d -p 8081:8080   --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080   --name tomcat82 billygoo/tomcat8-jdk8

600

6 host 模式

容器将不会虚拟出自己的网卡、配置自己的 IP,而是使用宿主机的 IP 和端口,不再需要额外进行 NAT 转换。

450

# 创建容器 正确示例
docker run -d --network host --name tomcat83 billygoo/tomcat8-jdk8
 
# 创建容器 错误示例
# 由于使用 host 模式,所有不会进行端口映射。此时会提示 warning。
docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8
 
# 访问容器 tomcat83
http://宿主机IP:8080/
// 查看网络信息,发现 Gateway 和 IPAddress 均为空了
docker inspect tomcat83 | tail -n 20
---
"Networks":{
	"host": {
		"IPAMConfig": null,
		"Links": null,
		"Aliases": null,
		"NetworkID": "ae13c04d76263af4ed36cef3f63a945d...",
		"EndpointID": "bbdb4ba60381326b6224d3f9dbcd567...",
		"Gateway": "",
		"IPAddress": "",
		"IPPrefixLen": 0,
		"IPv6Gateway": "",
		"GlobalIPv6Address": "",
		"GlobalIPv6PrefixLen": 0,
		"MacAddress": "",
		"DriverOpts": null
	}
}

7 none 模式

在 none 模式下,并不为 Docker 容器进行任何网络配置。
也就是说,这个 Docker 容器没有网卡、IP、路由等信息,只有一个 lo。
lo 就是 127.0.0.1 表示本地回环。
需要我们自己为 Docker 容器添加网卡、配置 IP 等。

# none 模式创建方式
docker run -d -p 8084:8080 --network none --name tomcat84 billygoo/tomcat8-jdk8

8 container 模式

新建的容器和已经存在的一个容器共享一个网络 ip 配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。

425

# 创建容器 alpine1
docker run -it --name alpine1  alpine /bin/sh
 
# 创建容器 alpine2,网络依托于 alpine1
docker run -it --network container:alpine1 --name alpine2  alpine /bin/sh
 
# 进入容器内部后,查看网络,可以看到两者使用同一个 eth0
ip addr
 
# 当关闭容器 alpine1 后,alpine2 上的网络就没有 eth0 了
ip addr

需要注意的是,使用 container 模式时,避免端口冲突。

# tomcat86和tomcat85公用同一个ip同一个端口,导致端口冲突
docker run -d -p 8085:8080 --name tomcat85 billygoo/tomcat8-jdk8
docker run -d -p 8086:8080 --network container:tomcat85 --name tomcat86 billygoo/tomcat8-jdk8

9 自定义网络

在之前,使用服务名进行 ping 会失败。Docker 自定义服务就是可以使得,同一个 network 下,容器之间可以通过服务名 (name) 而不是仅仅通过 IP 进行通信。多个容器的服务规划,就采用自定义网络服务,使得他们在同一个 network 下,避免了只能通过 IP 来通信、容器重启使得 IP 变更无法通信的情况。

自定义桥接网络,自定义网络默认使用的是桥接网络 bridge。

自定义网络本身就维护好了主机名和 ip 的对应关系(ip 和域名都能通)。

# 创建自定义 network
docker network create temp_network
 
# 创建容器加入自定义的 network
docker run -d -p 8081:8080 --network temp_network  --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --network temp_network  --name tomcat82 billygoo/tomcat8-jdk8
 
# 进入容器后,可以互相使用服务名进行 ping
ping tomcat82
ping tomcat81

自定义网络下,可以使用  docker network inspect 网络名称  来查看当前子网下有哪些容器。通过下面可以看到,网络中已经建立起来了,容器名与 IP 的映射关系。

root@KitDevVps:~# docker network inspect mynet
[
    ...
    "Containers": {
        "2a26067838f1724347ef50a1b8988a50603715e514fb288ab86401571dc70173": {
            "Name": "centos02",
            "EndpointID": "83e59d8f388561cb006564de55bb1c76278ab54b0e87f1f7e671a9962efe3608",
            "MacAddress": "02:42:c0:a8:00:03",
            "IPv4Address": "192.168.0.3/16",
            "IPv6Address": ""
        },
        "43f47db12bf4a8be9ea6172a89a44c530a23b29de49bf2a5ef95a88308675025": {
            "Name": "centos01",
            "EndpointID": "b0a1f17acc6a4c835952ae4e764c7f7e26a90fc3ce28be97cf9bb8c2ee0c10a4",
            "MacAddress": "02:42:c0:a8:00:02",
            "IPv4Address": "192.168.0.2/16",
            "IPv6Address": ""
        }
    },
    "Options": {},
    "Labels": {}
]

Docker 自定义网络中,还可以自定义子网、网关。docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet。具体参数可以通过  docker network create -h  进行查看。

Docker 自定义网络中,不同网桥/bridge 下的容器,无法通过 ip 进行 ping 通。通过  dockers network connect 另一个网桥名称 当前网桥的容器  命令,可以在当前容器下创建一个新的虚拟网卡,从而能 ping 通过。Site Unreachable (感觉自定义网络这里还是有些模糊)