原理简介
网络是一种很好的通讯方式,在容器中我们要解决两个问题:
- 容器间的相互通信
- 容器与外部的通信
首先看 Docker 中的网络,如下图:
如图: - 容器内部有自己的网络空间
Network Namespace
,拥有自己的网络设备,IP地址、路由表、防火墙、网络配置、端口等。网络是被封闭隔离的。 - Docker 创建了网桥
Linux Bridge
,起着交换机的作用。Docker会默认创建网络,可以自定义多个网桥。因为这个网桥既是容器的又是宿主机的,从容器内部看,Docker默认会自动创建一个名叫bridge
的网桥。但在宿主机中,它叫docker0
,可以理解成不同角度对相同对象的称呼。 - 容器通过
Veth Pair
连接到Linux Bridge
,连在同一个Linux Bridge
上的容器之间可以相互通信。 - 端口映射可以让
Linux Bridge
与宿主机“连接”,宿主机可以和外界通信。由此容器也间接地和外界通信了! Iptables
(图中漏了s)是 Linux 中用于管理网络过滤的程序。用于提供网络数据传输等功能。
命令
基本命令
sudo docker network ls #列出当前网络
sudo ifconfig #这个其实是宿主机系统的命令了,需要安装网络工具才可以用。可以看见Docker的网桥,如docker0.
sudo docker inspect $network #查看 $network 的信息
sudo docker network create --driver bridge $networkName #创建一个叫 $networkName 的网络
这里解释一下 --driver bridge
,bridge
还可以换成host
,但前者是创建一个和前面说的Linux Bridge
同等级的网桥,要与外界连接还需要端口映射
,所以外界不能直接访问容器。而用host
则直接使用宿主机中的网络环境,那么容器连到host
驱动的网桥上,则与宿主机处在同一个网络中的机器也能发现容器。--driver
也可以直接缩写为-d
。
容器与外部通信
数据从容器传输到docker0
或者其他网桥(宿主机的虚拟网卡),再转发到宿主机网卡。要使容器与外界通信正常,关键是保证网络数据转发,也就是 IP forward 功能正常启用。Docker daemon 启动时,可以通过 --ip-forward 参数来控制,默认是开启的。宿主机的 IP forward 启用命令为:
sudo sysctl net.ipv4.conf.all.forwarding=1
容器间通信
sudo docker run --link $container1 $container2 #运行$container2,并与$container1连接
两个容器要能相互通信,要保证它们在同一个子网上,即连到同一个网桥上。
进入容器,cat /etc/hosts
可以查看容器的配置信息。env
可以查看一些关于容器连接信息的环境变量。
实战
sudo docker network ls #列出docker网络
sudo ifconfig #查看宿主机网络信息
sudo docker inspect bridge #查看 bridge 的信息
sudo docker network create --driver bridge mynet #创建一个叫 mynet 的网络
安装ifconfig
里面的bridge
、host
、none
都是docker自动创建的。下图查看 docker0
的信息。docker0
是宿主机角度来看的。
查看宿主机的 IP forward。如果不是1,则在命令后加=1
.
sudo sysctl net.ipv4.conf.all.forwarding
容器间通信:
sudo docker run -d --name service-mysql gengli/mysql:0.0.1
sudo docker run -it --name client-mysql --link service-mysql gengli/mysql:0.0.1 bin/bash
env
cat /etc/host
注意,这里的gengli/mysql:0.0.1
是我在第10节做的镜像,自己实践时直接用mysql
即可,会从网上自动下载镜像。
之前第10节的问题没有解决,用官方的 mysql 镜像也失败。