这篇Docker的网络通信与数据共享文章看不懂你来打我吧

一、容器之间通信

1、单向通信

1.1、什么意思

在这里插入图片描述

mysql和tomcat是两个独立的容器,但是tomcat需要和mysql通信,而mysql完全不用和tomcat通信,这就叫容器之间的单向通信。

1.2、怎么通信

要谈通信,就需要谈一下ip,因为不知道ip是无法通信的。最简单的例子你jdbc要连接mysql数据库,你也需要配置mysql的ip地址。容器之间也不例外,都是靠虚拟ip来完成的。

何为虚拟ip?

虚拟ip:容器创建完成后都会生成一个唯一的ip,这个ip外界不能直接访问,他只用于容器之间进行通信交互用。这就是虚拟ip。

容器之间的虚拟ip是互通的。

通信是什么意思、靠什么通信我们都知道了,那还不抓紧实战一把?

1.3、实战演示

1.3.1、创建tomcat容器
docker run -d --name mytomcat tomcat
# --name指定的名称再docker ps里是可以看到的,最后一列Name
docker ps

知识点出现了!!! --name是神马鬼? 先看如下一个场景

在公司或者你直接买的阿里云数据库/redis等服务为什么给你个数据库域名而不是推荐用ip?因为ip的话可变,比如你业务系统写死了ip,这时候人家那边内网ip变了,你这所有用这个数据库的业务系统都要跟着改。用域名的话一劳永逸,底层ip变了后再映射到新域名上就行,不影响业务系统。

–name就是给docker配置名称来与虚拟ip做映射,因为ip老变化,每次变化的时候其他容器都需要跟着改动才行。配个名称一劳永逸。创建容器的时候通过 --name xxx 即可指定。

1.3.2、创建mysql容器

我也没拉取mysql镜像,就用centos模拟一下数据库吧,主要是看能不能ping 通,能ping 通就代表能通信。

docker run -d --name database -it centos /bin/bash
1.3.3、小试一把

我们需要进入mytomcat的容器然后去ping database的ip看看是否通,那么容器的虚拟ip怎么查呢?

# 这又是一个知识点
docker inspect 容器id
# 比如:(9bf58b4014dd是我们database的容器id)
docker inspect 9bf58b4014dd

在这里插入图片描述

现在知道数据库的ip了,那赶紧进入我们的mytomcat的容器去ping一波

docker exec -it mytomcat /bin/bash
ping 172.17.0.6

在这里插入图片描述

完美!

等等,貌似不是很完美,我们给数据库指定了名称database,那我们赶紧ping database 试一下。结果啪啪啪打脸,完全不通,那是因为相当于你就起了个名字,并没有做映射。那怎么映射呢?mytomcat启动容器的时候指定一个–link参数即可。

# 强制删除老的
docker rm -f mytomcat
# 创建新的容器,用--link指定我们想连的配置的数据库“域名”
docker run -d --name mytomcat --link database tomcat
# 进入mytomcat容器
docker exec -it mytomcat /bin/bash
# ping
ping database

在这里插入图片描述

这次是真的完美~!

1.4、- -link的原理

其实–link就是我们在hosts配置中增加了一个ip 名称的映射。仅此而已,很笨拙,已经不推荐此方式了。不信的话你–link完可以进入容器看下此容器的hosts文件,会多出–link配置的内容。

1.5、总结

  • 容器简单虚拟ip是互通的
  • 用–name 和 --link可以完成自定义“域名”来取代可变化的ip
  • 只支持单向通信,而且原理是写入hosts文件,太笨重了,不推荐。

2、双向通信

一般采取自定义网络的方式。

2.1、自定义网络

(1)我们先查一下当前有哪些网络:

docker network ls
# 输出结果
NETWORK ID     NAME      DRIVER    SCOPE
8f241fe133e3   bridge    bridge    local
cfdc23ad04e2   host      host      local
301558771ccb   none      null      local

(2)创建一个自定义的网络名叫mynet

docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 再次查看当前有哪些网络
docker network ls
# 发现我们的mynet诞生了
NETWORK ID     NAME      DRIVER    SCOPE
8f241fe133e3   bridge    bridge    local
cfdc23ad04e2   host      host      local
4e090905a675   mynet     bridge    local
301558771ccb   none      null      local

(3)验证mynet网络
docker network inspect mynet

在这里插入图片描述

2.2、将容器加入自定义网络

(1)启动两个容器且加入到mynet网络中

docker run -d -P --name tomcat-mynet-01 --net mynet tomcat
docker run -d -P --name tomcat-mynet-02 --net mynet tomcat

(2)查看是否加入网络成功
在这里插入图片描述
(3)进行测试看tomcat-mynet-01和tomcat-mynet-02之间是否双向互通

docker exec -it tomcat-mynet-01 ping tomcat-mynet-02 
docker exec -it tomcat-mynet-02 ping tomcat-mynet-01

(4)结果可以发现互相ping通,很完美,那肯定是啊,两个容器再同一个网络中,ip所属网段都一样。

2.3、自定义网络的好处

不同的集群使用不同的网络,可以保证集群的安全性,也比较清晰。比如Redis集群就叫redis-net,MySQL集群就叫mysql-net。

2.4、新问题:不同网络之间怎么互相访问?

比如我们webapp属于web-net网络,他要请求redis-net中的容器,这怎么互通?

(1)在启动两个tomcat,不加入到mynet中

# 再启动两个tomcat,用默认的网络
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 tomcat

此时我们的容器有这四个

[root@k8s-node ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                     NAMES
b01192af8ede   tomcat    "catalina.sh run"   21 minutes ago   Up 21 minutes   0.0.0.0:49159->8080/tcp   tomcat02
d056eaecdab5   tomcat    "catalina.sh run"   22 minutes ago   Up 22 minutes   0.0.0.0:49158->8080/tcp   tomcat01
5cc71afe377e   tomcat    "catalina.sh run"   26 minutes ago   Up 26 minutes   0.0.0.0:49157->8080/tcp   tomcat-mynet-02
4bfc3403687c   tomcat    "catalina.sh run"   26 minutes ago   Up 26 minutes   0.0.0.0:49156->8080/tcp   tomcat-mynet-01

(2)测试是否能通?
不用测试,肯定通不了,为了让你死心,我测试下…

[root@k8s-node ~]# docker exec -it tomcat01 ping tomcat-mynet-01 
ping: tomcat-mynet-01: Name or service not known

(3)解决方案
很简单,采取docker network connect把tomcat01加入到mynet网络中

# 采取docker network connect进行连通
docker network connect mynet tomcat01
# 查看mynet网络,如下图所示
docker network inspect mynet

在这里插入图片描述可以发现连通之后就是将tomcat01放到了mynet网络下,那么都在mynet同一网络下的docker容器之间肯定是可以互通的啦。

(4)再次测试是否可以通

# tomcat01 ping tomcat-mynet-01 
[root@k8s-node ~]# docker exec -it tomcat01 ping tomcat-mynet-01 
PING tomcat-mynet-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-mynet-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.062 ms

# tomcat01 ping tomcat-mynet-02 
[root@k8s-node ~]# docker exec -it tomcat01 ping tomcat-mynet-02 
PING tomcat-mynet-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-mynet-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.063 ms

# tomcat-mynet-02 ping tomcat01
[root@k8s-node ~]# docker exec -it tomcat-mynet-02 ping tomcat01
PING tomcat01 (192.168.0.4) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.055 ms

(5)原理
其实就是相当于tomcat01容器有两个ip,一个在mynet下,一个在默认的网络下。一个服务器有多个ip很正常。就是这么简单粗暴,真的屌炸天。

2.5、总结

  • docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet创建自定义网络。
  • docker run -d -P --name tomcat-mynet-01 --net mynet tomcat将容器加入到自定义网络中。
  • 不同网络之间的容器互相访问采取docker network connect命令将其加入到同网络。

二、容器间数据共享

1、场景

需要宿主机和容器之间共享数据的业务场景。比如Mysql的

比如:集群部署的时候,我们的应用程序需要部署到10个docker容器里,那么比如要想改动一个文件的内容,就要重新打包然后部署10次。我们可以将我们需要部署的应用程序挂载到宿主机上,这样改一处就行了。比如静态html文件,再一个宿主机上启动了10个容器,这时候需求需要改文案(修改html),我们需要修改10个容器里的html,过于麻烦,所以可以把这个html挂载到宿主机,容器直接使用挂载到宿主机的文件即可。

再比如:Mysql的数据目录可配置文件(一些高级配置或者优化配置啥的肯定要用一份),这也可以用此场景。

2、语法

# 语法
docker run -v 宿主机路径:容器内挂载路径 镜像名
# 比如如下:他会把/home/main/programe下面的所有目录都挂载到容器的/usr/local/tomcat/webapps下
docker run -v /home/main/programe:/usr/local/tomcat/webapps tomcat

3、实战

3.1、准备

在如下目录里创建如下文件,并写上Hello Volumn~

/home/main/docker/webapps/volumn-test/index.html

3.2、操作

很简单,按照上面的语法来就成了,如下就是将/home/main/docker/webapps下的目录挂载到容器内部/usr/local/tomcat/webapps的目录下

docker run --name t2 -d -p 8200:8080 -v /home/main/docker/webapps:/usr/local/tomcat/webapps tomcat

3.3、验证

我们先进入容器

docker exec -it t2 /bin/bash

然后查看/usr/local/tomcat/webapps下是否有我们挂载的目录以及文件

root@4be396ff443b:/usr/local/tomcat/webapps# ls -R volumn-test/
volumn-test/:
index.html

最后我们访问下看看效果

[root@izm5 volumn-test]# curl 'localhost:8200/volumn-test/index.html'
Hello Volumn~~

我们修改下宿主机上的index.html的内容,修改为Hello Volumn~~ How are you?然后再次访问看效果:

这里修改的是宿主机/home/main/docker/webapps/volumn-test下的index.html,为不是容器内部的。

[root@izm5 volumn-test]# curl 'localhost:8200/volumn-test/index.html'
Hello Volumn~~ How are you?

很完美,容器无感知的就生效了。

3.4、好处

我这是启动了一个容器举例,如果多启动几个呢?然后产品要修改文案,那么你登录每个容器里去修改?或者重新打包然后重新启动所有容器?有点小题大做呀,利用-v命令进行挂载实现宿主机和容器的数据共享她不香吗?

4、新的问题

如果容器过多,那么每次启动容器都要-v xxx:xxx,这也很容易写错啊,写错一个字母都不行,还有,如果宿主机换地址了,这也需要批量更换容器的docker run -v的参数,机器太多不利于维护。

5、解决问题

共享容器诞生了!

5.1、共享容器概念

如果容器太多,每一次都要写-v xxx:xxx,过于复杂,也容易出错,这时候可以通过docker create创建共享容器,然后启动的时候通过--volumes-from指定创建的共享容器名称即可,也就是说可以把上面-v xxx:xxx这一串统一放到一个地方去管理,容器启动的时候直接引用这个统一配置即可,方便统一管理。

5.2、语法

# 创建共享容器语法,只是创建不是启动。最后的/bin/true 就是一个占位符,没啥乱用。
docker create --name 共享容器名称 -v 宿主机路径:容器内挂载路径 镜像名称 /bin/true
# 启动容器的时候通过--volumes-from 共享容器名称来使用共享容器挂载点
docker run --volumes-from 共享容器名称 --name xxx -d 镜像名称

5.3、实战

# 创建共享容器
docker create --name webpage -v /home/main/docker/webapps:/usr/local/tomcat/webapps tomcat /bin/true
# 采取共享容器的配置来启动容器
docker run -p 8300:8080 --volumes-from webpage --name t3 -d tomcat
# 在启动个
docker run -p 8400:8080 --volumes-from webpage --name t4 -d tomcat

5.4、验证&&好处

验证跟第一种-v的方式一样,修改内容,容器无感知。

相对于第一种方式的好处是:

  • 不用每次都写-v xxx:xxx这一长串不仅令人厌恶还容易出现错误的英文字母。
  • 更改路径,只修改一处即可。

三、SpringBoot项目部署到Docker

1、编写Dockerfile

FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]

在这里插入图片描述

2、运行

(1)将Dockerfile和demo-xx.jar上传到服务器。
(2)构建镜像
docker build -t test-docker .
(3)启动容器
docker run -d -p 8000:8080 --name test-springboot-docker test-docker
(4)然后访问就行了 curl 'http://localhost:8888'

3、补充

实际还可以考虑volume挂载log目录到宿主机。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

【原】编程界的小学生

没有打赏我依然会坚持。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值