从 Docker 的所有容器都是隔离的来说,对 Docker 对网络同样也会有以下几个问题:
1.容器外部如何访问外部网络?
2.多个容器网络如何共享?
3.外部如何访问到容器内部服务?
Drivers 网络驱动
Docker 提供了以下类型的网络类型:
1.bridge 桥接网络,没有声明网络类型的时候默认使用的网络类型。会生成一个虚拟网桥,使用同一个网桥的容器可以互相进行通信。因为是挂载外 Docker 默认的网桥下,所以可以访问到外部网络,但是外部网络无法直接访问到容器内部。
2.host 使用宿主机的网络,直接使用主机的网桥进行通信,相当于容器和主机直接共享,之间没有任何隔离。
3.overlay 正常情况下不会使用,是用于多个 Docker 宿主机之间的通信。一般被 Swarm 使用。
4.ipvlan 可以完全指定网桥的配置。
5.mavlan 会向路由器直接申请一个 MAC 地址,然后在直接虚拟出来一个网口,对于外部访问来说就是一个单独的 ip 进行访问。同一个 mavlan 网桥下所有网口可以互通,但是和宿主机的网口不可以互通。
6.none 不使用网络,容器内外网直接无法进行互通。
网络模式
在这里先介绍几种常用的网络模式,后续会继续介绍其他的网络模式。
Host 宿主机网络
host 在使用时类似于直接使用了宿主机的网络,容器内部所有用到的端口也都会在宿主机上直接进行占用。对外的 ip 也都是同一个地址。需要注意的是,使用 host 网络的时候就相当于直接放弃了 Docker 的网络隔离。
# 使用 host 网络创建一个 nginx 容器,nginx 容器在启动时会直接对 80 端口进行监听。
docker run -d --net=host nginx
# 查看一下所有的容器,看下 nginx 容器运行起来没有。
docker ps -a
# 看一下宿主机的 80 端口是否被占用了。
netstat -lnp | grep 80
Bridge 桥接网络
这里先清理掉上次运行的容器,然后创建一个新的使用桥接网络的容器。
# 这里不指定网络配置,默认使用 bridge 网络。
docker run -d nginx
# 看一下宿主机的 80 端口是否被占用了。
netstat -lnp | grep 80
看一下容器的信息可以看到现在这个容器拥有了自己的 ip 地址。
# 找一下容器的 IP 地址,这里的容器 ID 是 9b9059b9ea8a。
docker inspect 9b9059b9ea8a | grep IPAddress
直接 ping 一下容器的地方,发现可以访问了。使用 curl 访问 80 端口返回的也是 nginx 的默认页面。
这个时候我们实现宿主机和容器互通了,那外部用户怎么直接访问到容器内部呢?Docker 提供了端口映射的方式来实现。
# 这里使用 -p 参数来指定端口映射,将容器的 80 端口映射到宿主机的 8080 端口。
# 使用 --name 指定容器的名称。
docker run --name nginx -d -p 8080:80 nginx
# 试下访问
curl localhost:8080
Container 网络共享
Container 网络更像是 Docker 的一个语法糖,直接使用另一个容器的网络。
# 先创建一个 busybox 容器。
# busybox 是一个网络测试的工具,避免多个 nginx 端口占用的问题。
docker run --name busybox1 -it -d busybox
# 使用 --network container:busybox1 来指定容器的网络。
docker run --name busybox2 -it -d --network container:busybox1 busybox
# 查看一下两个容器的网络信息。
docker exec -it busybox1 ifconfig
docker exec -it busybox2 ifconfig
可以看到两个容器的 ip 完全一致,这样就实现了两个容器共享网络的功能。