docker为容器创建独立的网络环境,实现宿主和容器、容器之间的网络隔离,默认使用bridge模式的网络,实现容器之间、容器与宿主机之间、乃至与外界之间 的网络通信。
但是我们在实际部署应用的时候,发现并不能直接通过容器内部端口访问另外一个容器的应用(比如:mysql容器端口是3306,web应用不能直接通过3306访问mysql),而是通过端口映射到宿主机器来实现容器之间的访问。
那么有什么方式能实现直接通过容器内部端口进行数据通讯呢?那就是通过network方式。
docker network创建一个桥接网络,在docker run的时候将容器指定到新创建的桥接网络中,这样同一桥接网络中的容器就可以通过互相访问。
1、创建network
[root@iZbp13sno1lc2yxlhjc4b3Z ~]# docker network create my-network
[root@iZbp13sno1lc2yxlhjc4b3Z ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e4de24aaf1c2 bridge bridge local
093caaca12b4 host host local
a2b05d7d591a my-network bridge local
6e6497f8e311 none null local
[root@iZbp13sno1lc2yxlhjc4b3Z ~]#
可以看到my-network已经创建好,另外其他3个是docker默认创建的。
2、创建容器时指定网络
在创建容器时指定使用my-network网络,并设置网络别名。
docker run -itd --name mysql --network my-network --network-alias mysql -e MYSQL_ROOT_PASSWORD=root mysql:5.7.24
--network 指定使用的网络
--network-alias 设置网络别名
如果容器已创建好但是之前没有指定自己的网络,则使用下面命令修改:
docker network connect --alias mysql my-network mysql
第一个mysql是网络别名 第二个mysql是容器名
3、通过网络别名测试访问
进入web容器,使用ping命令测试
[root@iZbp13sno1lc2yxlhjc4b3Z ~]# docker exec -it tomcat_kq bash
root@161eee53356c:/usr/local/tomcat# ping mysql
PING mysql (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.my-network (172.18.0.2): icmp_seq=1 ttl=64 time=0.049 ms
可以看到通过mysql网络别名可以直接访问。
另外通过容器id或者主机名也是可以访问的。但是你不加入这个自定义网络,则没法访问。这个在项目实际应用中非常重要,特别是通过主机名识别服务的项目,如springcoud项目
4、项目实际应用
修改web项目访问mysql的数据库地址,由ip改为网络别名,端口为容器内部端口:
jdbc:mysql://mysql:3306/kaoqin?allowMultiQueries=true
注意:mysql是前面设置的网络别名,3306是容器内部端口
这里特别提一下springcloud项目,eureka中心一般是通过主机名来中注册发现服务的,但是一放到docker容器中,springboot应用就报错,提示不能发送心跳到注册中心,就是因为容器中间的网络隔离造成的,通过把所有容器加入到自定义网络就能解决此问题。