Docker 网络
通常,我们都会部署很多网络应用,例如Nginx,MySql
但是,比起我们手动安装,使用docker无疑是更加方便的,因为容器内的软件环境都全部配置好了啊,只需要拉取镜像并启动就好。
但是我们在运行容器的时候会出现问题,就是,外网访问mysql 3306端口的时候访问不到,这是为什么呢
Docker内网
事实上,Docker所有的容器都会在宿主机上构成一个内网,这个是存在于宿主机上的专属于所有Docker容器的内网。
其中:
- 所有容器都可以通过内网相互访问
- 宿主机可以通过内网访问每个容器的对应端口
- 但是,外网不能直接访问某个宿主机的某个容器的端口
端口映射
那么,外网怎么去访问宿主机的某个容器的端口呢?
我们可以使用端口映射
比如,我们可以把3307的端口映射到宿主机的3307端口上,容器启动后,外网访问宿主机3307的端口,就可以访问到Mysql容器的3306端口上
实现映射很简单,使用 -p即可
docker run -id --name=mysql1 -v /root/mysql/conf:/etc/mysql/conf.d -v /root/mysql/logs:/logs -v /root/mysql/data:/var/lib/mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
两个-v的意思是挂载mysql容器里面的数据到宿主机上,如果不知道数据卷如何挂载的小伙伴可以去看看我之前写的博客。
我们进行了三个目录的挂载,分别是mysql的conf,logs和data(方便数据的备份)
可见,-p参数的格式是本机端口:容器端口
通常,这三个数据卷的挂载不是必须
此时,我们再通过外网访问mysql的3307端口就可以访问到了
可见这样,MySQL就安装完毕了!是不是比自己安装简单多了?因为MySQL镜像都是官方配置好了的,我们拉取并运行即可。
Docker内网的虚拟路由
先普及一个知识点,我们家里甚至是一个房间,所有的设备都要上网,都需要一个路由器,我们的电脑和手机就可以通过有线网络或者无线网络的形式,连接路由器广播的网络,路由器给我们的设备分配一个内网ip才能够上网。
上面提到了所有的Docker容器都在一个内网之中,是不是意味着每个容器也会分配一个内网ip呢?确实是这样
Docker内网中也有一个类似这样的虚拟路由,这个虚拟路由就是给每个容器都分配内网ip地址,当然分配的内网ip地址只能是容器和容器之间访问或者宿主机访问容器,外网还是不能直接访问,除非是通过上述的端口直接映射
我们默认的所有容器,都会分配一个名为bridge的虚拟路由虚拟路由来分配ip地址
案例
我们先再宿主机上运行两个Nginx容器,接下来就以这个为例来讲解
(1) 查看一个容器的内网IP
比如说我们要查看上述名为nginx1容器的内网ip地址,通过docker inspect命令即可:
在宿主机中通过ping命令可以发现这个是ping的通的,可以访问:
大家可以进入一个容器然后ping另一个容器,也是可以的,说明容器之间也可以互相访问。
大家可以开启一个MySQL的容器,并使用宿主机的MySQL连接它,体验一下容器的网络通信。
(2) 查看一个路由内的所有容器及其IP
上面提到过,所有的容器创建时默认被分配到名为bridge虚拟路由中,通过docker network命令查看:
# 查看名为bridge的虚拟路由器下的所有容器
docker network inspect bridge
bashcopy
找到Containers字段即可看到这个虚拟路由下所有的容器。
(3) 创建新的路由器
虽然大多数情况我们使用默认的虚拟路由bridge即可,不过我们仍然可以创建多个虚拟路由,并把容器连接到不同的路由下。
通过以下命令查看现在所有的虚拟路由列表:
docker network ls
bashcopy
现在如果要创建一个名为maiqu的虚拟路由,命令如下:
docker network create maiqu
bashcopy
可见创建完成:
我们可以把一个已有的容器连接到指定的虚拟路由,例如现在我要把nginx2容器连接到路由maiqu下,命令如下:
# 命令格式:docker network connect 路由名 容器名/ID
docker network connect maiqu nginx2
bashcopy
这时,分别查看两个路由,发现默认的bridge中只有nginx1了,nginx2在路由maiqu中去了,IP地址也发生了改变。
与此同时,在创建容器的时候,我们可以加上--network参数指定创建这个容器时将其连接到哪个虚拟路由器:
# 创建一个名为nginx3的Nginx容器,并连接到虚拟路由器maiqu下
docker run -id --name=nginx3 --network=maiqu nginx
bashcopy
注意,位于不同的虚拟路由下的容器是不能互相访问的,也就是说虚拟路由通常是为了隔离一些容器的网络环境。
(4) Docker网络常用命令
我们可以查看一下docker network的帮助:
可见我们还可以把容器断开网络连接、删除虚拟路由器等等:
# 把名为nginx3的容器从虚拟路由maiqu下断开连接,此时这个容器处于离线状态无法通过内网访问
docker network disconnect maiqu nginx3
# 删除名为maiqu的虚拟路由器,需要将路由器下的全部容器断开连接才能删除
docker network rm maiqu
\