背景:
在学习 Docker 过程中,自己先开启了一个 mysql 容器,并且通过端口映射Navicat可以远程连接
后来在部署 nacos 过程中,对于其中参数 MYSQL_SERVICE_HOST 配置 mysql 的 IP 时
首先配置的是 localhost,结果 nacos容器 无法访问 mysql容器
localhost 无法访问原因:
因为 容器中的ip地址 和 宿主机的ip地址 是不同的,所以当 nacos 用 localhost 时,其实对应的是 nacos容器的ip地址,所以调用 localhost 时,并不能通过 宿主机的ip地址调用3306端口映射到容器中3306端口调用mysql容器,也不能通过 nacos容器ip地址调用3306端口调用mysql容器,因为docker中 nacos容器 和 mysql容器分配的地址是不同的
解决办法:
先查看 mysql容器 对应的 ip 地址:
docker inspect mysql | grep IPAddress
在查到 mysql容器 ip地址后,那么就可以配置到 nacos 中 MYSQL_SERVICE_HOST 里了,这时候就可以实现 nacos容器 与 mysql容器 之间的通信了
虽然容器之间实现了互相通信,问题得到了解决,但是始终觉得还没理解透彻,于是又查阅了大量资料,发现有更好的解决办法
该方法弊端:
当把容器访问ip写死后,这种方式绝对是很笨拙的,因为当重启Docker时,容器的 IP 地址会变化
浅解Docker容器网络模式
通过命令:
docker network ls
可以看到有三种网络模式:
-
bridge模式,–net=bridge(默认)
这是docker网络的默认设置,为容器创建独立的网络命令空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。
在进行docker run启动容器的时候,如果不加–net参数,就默认采用这种网络模式。
安装完docker,系统会自动添加一个供docker使用的网桥docker0,我们创建一个新的容器时,容器通过DHCP获取一个与docker0同网段的IP地址,并默认连接到docker0网桥,以此实现容器与宿主机的网络互通。 -
host模式,–net=host
这个模式创建出来的容器,直接使用容器宿主机的网络命名空间,将不拥有自己独立的Network Namespace,即没有独立的网络环境,不需要设置端口映射即可连接到容器端口。它使用的是宿主机的ip和端口。 -
none模式,–net=none
为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。这种模式下,docker不为容器进行任何网络配置,需要我们自己为容器添加网卡,配置IP。
因此,如果要使用pipework配置docker容器的ip地址,必须要在none模式下才可以。
所以之前创建的两个Docker容器是默认在 bridge模式下的,会自动分配不同 ip,可以通过 ip 地址实现容器之间的互相访问,但是不能通过 Docker容器名 来实现互相访问
最终解决方案:通过容器名来实现互相访问
要想实现通过容器名来互相访问,需要创建自定义网卡,网络驱动仍然使用 bridge:
docker network create my-net
# 查看
docker network ls
将容器添加到自定义网络 my-net 当中,在容器运行时添加 --network my-net
# mysql容器运行
docker run --name mysql --network my-net -e MYSQL_ROOT_PASSWORD=xxx -p 3306:3306 -v $PWD/mysql/data:/var/lib/mysql -d mysql:5.7.25
# nacos容器运行
docker run --name nacos --network my-net -e MODE=standalone -p 8848:8848 -v $PWD/nacos/application.properties:/home/nacos/conf/application.properties -d nacos/nacos-server
可以通过查看 my-net 网卡详细信息看容器是否添加成功:
docker inspect my-net
这时候两个容器之间可以通过 容器名 来实现互相访问了