docker网络模式
安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络,也就是在不使用–network参数时)、 none 、host。还有以后一种自定义模式,自定义模式有三种:bridge、overlay、macvlan。
- host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
- none:该模式关闭了容器的网络功能。
- bridge:此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。
通过如下命令可以查看docker网络
docker network ls
NETWORK ID NAME DRIVER SCOPE
2e3e4dcbd3d7 bridge bridge local
f3055283e718 docker-mac-network_default bridge local
fdbd9040885e host host local
9c38974a6323 mybridge bridge local
1c8d0ddedbbe none null local
自定义bridge模式
docker启动的容器通常使用默认的bridge网络,有个弊端就是不能指定IP,如果停止容器再一次启动IP会发生变化,如果需要指定IP需要使用自定义网络。
创建network命令如下
docker network create -d bridge --ip-range=192.168.2.0/24 --gateway=192.168.2.1 --subnet=192.168.2.0/24 bridge2
在使用docker run命令启动容器的时候,可以通过–net参数来指定容器的网络配置。
- –net=bridge:默认值,在Docker网桥docker0上为容器创建新的网络栈。
- –net=none:让Docker将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自行进行配置。
- –net=container:NAME_or_ID:让Docker将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享IP地址和端口等网络资源,两者进程可以直接通过lo环回接口通信。
- –net=host:告诉Docker不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其他root进程一样打开低范围的端口,可以访问本地网络服务,比如D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用–privileged=true参数,容器甚至会被允许直接配置主机的网络栈。
- –net=user_defined_network:用户自行用network相关命令创建一个网络,通过这种方式将容器连接到指定的已创建网络上去。
创建两个容器指定ip并指定network
#指定容器IP为192.168.1.3,使用网络bridge2
docker run -it --network=bridge2 --ip=192.168.1.3 busybox
#指定容器IP为192.168.1.4,使用网络bridge2
docker run -it --network=bridge2 --ip=192.168.1.4 busybox
容器之间的通信方式
IP 通信
两个容器要能通信,必须要有属于同一个网络的网卡。满足这个条件后,容器就可以通过IP交互了。具体做法是在容器创建时通过 –network 指定相应的网络,或者通过docker network connect将现有容器加入到指定网络。
Docker DNS Server
通过 IP 访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署应用之前可能无法确定IP,部署之后再指定要访问的IP会比较麻烦。对于这个问题,可以通过docker自带的DNS服务解决。
从Docker1.10版本开始,docker daemon实现了一个内嵌的DNS server,使容器可以直接通过"容器名"通信。方法很简单,只要在启动时用 –name 为容器命名就可以了。
使用 docker DNS 有个限制:只能在用户自定义网络中使用。也就是说,默认的bridge网络是无法使用DNS的。
joined容器
joined容器是另一种实现容器间通信的方式。它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信。
joined容器使用方式如下:
#先创建一个http容器,名字为 box1
docker run -it --name box1 http
#然后创建 busybox 容器并通过 --network=container:box1 指定 jointed 容器为 box1
docker run -it --network=container:box1 busybox
容器访问控制
容器访问外部网络
我们知道容器默认指定了网关为docker0网桥上的docker0内部接口。docker0内部接口同时也是宿主机的一个本地接口。因此,容器默认情况下是可以访问到宿主机本地的。更进一步,容器要想通过宿主机访问到外部网络,需要宿主机进行转发。
#查看转发是否打开
sysctl net.ipv4.ip_forward
#如果为0,则没有开启转发,则需要手动打开:
sysctl -w net.ipv4.ip_forward=1
更简单的,在启动Docker服务的时候设定–ip-forward=true,Docker服务会自动打开宿主机系统的转发服务。
外部访问容器实现
容器允许外部访问,可以在docker run时候通过-p或-P参数来启用
不管用那种办法,其实也是在本地的iptable的nat表中添加相应的规则,将访问外部IP地址的网包进行目标地址DNAT,将目标地址修改为容器的IP地址