Docker 必知必会4----容器之间的通信

docker · 浏览次数 : 16

小编点评

**构建 Bridge 网络的步骤:** 1. 创建 3 个容器。 2. 在每个容器中运行一个 Tomcat 服务。 3. 为每个容器分配不同的端口。 4. 使用 `docker exec` 命令在不同的容器中访问对方容器的端口。 5. 创建一个网络并将其命名为 `bridge网络」。 6. 将容器加入到 `bridge 网络` 中。 7. 使用 `docker exec` 命令在容器中访问其他容器的端口。

正文

前面几篇文章,我们聊了docker的基本概念,以及基本的操作手段:

https://www.cnblogs.com/jilodream/p/18177695   初识docker
https://www.cnblogs.com/jilodream/p/18184687   基本操作
https://www.cnblogs.com/jilodream/p/18189478   镜像制作

但是现在随着分布式多节点的考虑,我们往往需要容器之间可以进行通信。
容器之间的通信一般分为(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )三种途径:
1、通过虚拟ip直接访问
2、通过link方式,指定要连接的容器
3、创建bridge网络,来实现容器互联

为了满足接下来的学习,我们需要利用官方的tomcat镜像为基础,初始化一些指令,DockerFile 如下:

 1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# cat Dockerfile 
 2 #指定基础镜像
 3 FROM tomcat:my-tomcat-image  
 4 
 5 #指定维护人员
 6 MAINTAINER wangruoyi "encijietuo@123.com"  
 7 
 8  # 设置环境变量
 9 ENV BASE_DIR="/usr/local/" 
10 
11 #指定工作路径
12 WORKDIR /$BASE_DIR  
13 
14 #删除原有的webapps 文件夹
15 RUN rm -rf ./tomcat/webapps && cp -r  ./tomcat/webapps.dist  ./tomcat/webapps  && apt-get update && apt-get install net-tools && apt install iputils-ping -y
16 
17 #暴露8080端口,其实没有必要,因为原有的
18 EXPOSE   8080
19 
20 #ENTRYPOINT ["echo 'hello myImage'"]

开始构建镜像,并查看

1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker  build  -t new  .
2 省略部分输出
3 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker images 
4 REPOSITORY                     TAG               IMAGE ID       CREATED        SIZE
5 new                            latest            9a36ac14523d   21 hours ago   706MB

然后我们回到重点,依次来看看容器的3种通信途径:

1、通过虚拟ip直接访问
安装docker之后,docker会默认搭建一个docker0的网络,后续每个容器就是网络中的一个节点,(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )每个节点因此会有属于网络中的一个虚拟ip。我们可以利用虚拟ip直接进行访问。
如下,我们创建两个容器:

 

1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker run -p 8081:8080 -d --name mytom8081 9a36ac14523d
2 f3f1b0f09320e6e42e704625fa4aa2d544a553976cf38dba7c1dcddfe65e8563
3 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker run -p 8082:8080 -d --name mytom8082 9a36ac14523d
4 744a1395c38840cc01659ec9fa2d55026389ca5d99387092de1d23c026613a65
5 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker ps 
6 CONTAINER ID   IMAGE          COMMAND             CREATED         STATUS         PORTS                    NAMES
7 744a1395c388   9a36ac14523d   "catalina.sh run"   3 minutes ago   Up 3 minutes   0.0.0.0:8082->8080/tcp   mytom8082
8 f3f1b0f09320   9a36ac14523d   "catalina.sh run"   3 minutes ago   Up 3 minutes   0.0.0.0:8081->8080/tcp   mytom8081

 我们可以通过ifconfig或者inspect 查看容器ip,接着使用 ping 和curl 命令实现两个容器的互相访问,我们发现网络是通着的:

进入8081容器,并查看ip为172.17.0.2

1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker exec -it f3f1b0f09320  /bin/bash
2 root@f3f1b0f09320:/usr/local# ifconfig
3 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
4         inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
5 
6 以下省略部分

进入8082容器,,并查看ip为172.17.0.3

1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker exec -it 744a1395c388 /bin/bash
2 root@744a1395c388:/usr/local# ifconfig
3 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
4         inet 172.17.0.3  netmask 255.255.0.0  broadcast 172.17.255.255
5         inet6 fe80::42:acff:fe11:3  prefixlen 64  scopeid 0x20<link>
6 
7 以下省略部分

8081 ping 8082,并访问对方tomcat端口

 1 root@f3f1b0f09320:/usr/local# ping 172.17.0.3
 2 PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
 3 64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.218 ms
 4 64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.084 ms
 5 ^C
 6 --- 172.17.0.3 ping statistics ---
 7 2 packets transmitted, 2 received, 0% packet loss, time 1000ms
 8 rtt min/avg/max/mdev = 0.084/0.151/0.218/0.067 ms
 9 root@f3f1b0f09320:/usr/local# curl 172.17.0.3:8080
10 
11 
12 
13 <!DOCTYPE html>
14 <html lang="en">
15     <head>
16         <meta charset="UTF-8" />
17         <title>Apache Tomcat/10.0.14</title>
18 
19 以下省略部分

8082 ping 8081,并访问对方tomcat端口

 1 root@744a1395c388:/usr/local# ping 172.17.0.2
 2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
 3 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.150 ms
 4 ^C
 5 --- 172.17.0.2 ping statistics ---
 6 1 packets transmitted, 1 received, 0% packet loss, time 0ms
 7 rtt min/avg/max/mdev = 0.150/0.150/0.150/0.000 ms
 8 root@744a1395c388:/usr/local# curl 172.17.0.2:8080
 9 
10 
11 
12 <!DOCTYPE html>
13 <html lang="en">
14     <head>
15         <meta charset="UTF-8" />

这种情况一般比较简单,而且实际搭建网络集群时,比较复杂,ip地址也不好维护,所以我们一般只是在环境测试时使用。

2、通过link方式,指定要连接的容器
命令描述如下:

docker run  -d --name 容器名称 --link 被连接容器名:被连接容器别名 镜像Id

我们创建两个容器。然后通过ifconfig或者inspect 查看容器ip

我们可以直接通过(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )别名来访问另外一个容器,
以下为8081容器:ip为172.17.0.2:

 1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker run -p 8081:8080 -d --name mytom8081 9a36ac14523d
 2 ce95c0e7a3f10a3623c0c86ef38caaa33a758ca15fd2a246757686c7329c9092
 3 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker ps
 4 CONTAINER ID   IMAGE          COMMAND             CREATED          STATUS          PORTS                    NAMES
 5 a67f455d6bf0   9a36ac14523d   "catalina.sh run"   15 seconds ago   Up 15 seconds   0.0.0.0:8082->8080/tcp   mytom8082
 6 ce95c0e7a3f1   9a36ac14523d   "catalina.sh run"   18 minutes ago   Up 18 minutes   0.0.0.0:8081->8080/tcp   mytom8081
 7 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker exec -it ce95c0e7a3f1 /bin/bash
 8 root@ce95c0e7a3f1:/usr/local# ifconfig
 9 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
10         inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
11         inet6 fe80::42:acff:fe11:2  prefixlen 64  scopeid 0x20<link>

以下为8082容器,ip为172.17.0.3 :

1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker run -p 8082:8080 -d --name mytom8082 --link mytom8081:mytom8081alias  9a36ac14523d
2 a67f455d6bf0d37b9fb43769d6d93d0e59903fb585b2fd4d37434b3199394869
3 
4 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker exec -it  a67f455d6bf0 /bin/bash
5 root@a67f455d6bf0:/usr/local# ifconfig
6 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
7         inet 172.17.0.3  netmask 255.255.0.0  broadcast 172.17.255.255

8082容器通过ip和网络别名访问8081容器:

 1 root@a67f455d6bf0:/usr/local# ping 172.17.0.2
 2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
 3 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.158 ms
 4 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.063 ms
 5 ^C
 6 --- 172.17.0.2 ping statistics ---
 7 2 packets transmitted, 2 received, 0% packet loss, time 999ms
 8 rtt min/avg/max/mdev = 0.063/0.110/0.158/0.047 ms
 9 root@a67f455d6bf0:/usr/local# ping mytom8081alias
10 PING mytom8081alias (172.17.0.2) 56(84) bytes of data.
11 64 bytes from mytom8081alias (172.17.0.2): icmp_seq=1 ttl=64 time=0.081 ms
12 64 bytes from mytom8081alias (172.17.0.2): icmp_seq=2 ttl=64 time=0.063 ms
13 ^C
14 --- mytom8081alias ping statistics ---
15 2 packets transmitted, 2 received, 0% packet loss, time 1000ms
16 rtt min/avg/max/mdev = 0.063/0.072/0.081/0.009 ms
17 root@a67f455d6bf0:/usr/local# curl mytom8081alias:8080
18 
19 
20 
21 <!DOCTYPE html>
22 <html lang="en">

link方式本质上还是使用docker0网络,(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )修改host文件的ip映射,来实现网络通信。并且随着ip的变化还可以动态的维护这种映射关系。

但是link方式也有自己的局限性,如只能单向请求,两个容器无法互相连接请求对方,因为link配置是在启动容器时就已经生成好的,也就是只能后边的容器单向请求前边的容器,无法形成循环的网络。由于诸多不便,link方式也被抛弃了,更推荐的是bridge网络方式。

3、创建bridge网络,来实现容器互联

(1)首先我们创建一个bridge网络:
docker network create 网络名称

如下,我们创建一个网络名称为mynet的网络

 1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker network ls
 2 NETWORK ID     NAME      DRIVER    SCOPE
 3 aa377d4ce411   bridge    bridge    local
 4 39d44fbbca56   host      host      local
 5 2b8ed0e20118   none      null      local
 6 
 7 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker network create mynet
 8 fd1097786e75a0e3b7160fdacc49f60d815457dbbcc4654bb138136f02d9cb54
 9 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker network ls
10 NETWORK ID     NAME      DRIVER    SCOPE
11 aa377d4ce411   bridge    bridge    local
12 39d44fbbca56   host      host      local
13 fd1097786e75   mynet     bridge    local
14 2b8ed0e20118   none      null      local

(2)新创建3个容器加入到bridege网络中

命令如下docker run -it --name  容器名 ---network bridge网络名 --network-alias 当前容器在网络中的别名  镜像名

 1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker run -p 8083:8080 -d --name mytom8083 --network mynet --network-alias mytom8083alias  9a36ac14523d
 2 1d993226c559408a54d18f9258d2dc196283dc5b6b0cffa2d113b4eef579f7c4
 3 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker run -p 8084:8080 -d --name mytom8084 --network mynet --network-alias mytom8084alias  9a36ac14523d
 4 c7de74283019bccfc87174941afdeb2fbbd0137496094bd7fd9d6a500352a4ad
 5 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker run -p 8085:8080 -d --name mytom8085 --network mynet --network-alias mytom8085alias 9a36ac14523d
 6 28c5fa396b54649edc31c52c4cdf85a96063919272a12f61b208cfb99f1325f9
 7 
 8 CONTAINER ID   IMAGE          COMMAND             CREATED          STATUS          PORTS                    NAMES
 9 28c5fa396b54   9a36ac14523d   "catalina.sh run"   4 minutes ago    Up 45 seconds   0.0.0.0:8085->8080/tcp   mytom8085
10 c7de74283019   9a36ac14523d   "catalina.sh run"   13 minutes ago   Up 13 minutes   0.0.0.0:8084->8080/tcp   mytom8084
11 1d993226c559   9a36ac14523d   "catalina.sh run"   14 minutes ago   Up 13 minutes   0.0.0.0:8083->8080/tcp   mytom8083

(3)进入到3个容器中,分别访问其它容器

以下为8083容器:8083访问8084

1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker exec -it 1d993226c559   /bin/bash
2 root@1d993226c559:/usr/local# curl  mytom8084alias:8080
3 
4 
5 
6 <!DOCTYPE html>
7 <html lang="en">
8     <head>
9         <meta charset="UTF-8" />

以下为8084容器: 8084访问8083

 1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker exec -it c7de74283019  /bin/bash
 2 root@c7de74283019:/usr/local# 
 3 root@c7de74283019:/usr/local# 
 4 root@c7de74283019:/usr/local# 
 5 root@c7de74283019:/usr/local# ping mytom8083alias
 6 PING mytom8083alias (172.18.0.2) 56(84) bytes of data.
 7 64 bytes from mytom8083.mynet (172.18.0.2): icmp_seq=1 ttl=64 time=0.151 ms
 8 64 bytes from mytom8083.mynet (172.18.0.2): icmp_seq=2 ttl=64 time=0.057 ms
 9 ^C
10 --- mytom8083alias ping statistics ---
11 2 packets transmitted, 2 received, 0% packet loss, time 1001ms
12 rtt min/avg/max/mdev = 0.057/0.104/0.151/0.047 ms
13 root@c7de74283019:/usr/local# curl  mytom8083alias:8080
14 
15 
16 
17 <!DOCTYPE html>
18 <html lang="en">
19     <head>
20         <meta charset="UTF-8" />
21         <title>Apache Tomcat/10.0.14</title>

以下为8085容器:8085访问8083、8084

 1 [root@iZ2ze3bpa0o5cw6gp42ry2Z ~]# docker exec -it 28c5fa396b54 /bin/bash
 2 root@28c5fa396b54:/usr/local# curl mytom8083alias:8080
 3 
 4 <!DOCTYPE html>
 5 <html lang="en">
 6     <head>
 7         <meta charset="UTF-8" />
 8         <title>Apache Tomcat/10.0.14</title>
 9         <link href="favicon.ico" rel="icon" type="image/x-icon" />
10         <link href="tomcat.css" rel="stylesheet" type="text/css" />
11 
12 省略若干
13 
14 root@28c5fa396b54:/usr/local# curl mytom8084alias:8080
15 <!DOCTYPE html>
16 <html lang="en">
17     <head>
18         <meta charset="UTF-8" />
19         <title>Apache Tomcat/10.0.14</title>
20         <link href="favicon.ico" rel="icon" type="image/x-icon" />
21         <link href="tomcat.css" rel="stylesheet" type="text/css" />

我们可以发现第三种(构建bridge网络)的方式,相对来说最为灵活实用,不需要提前规划,并且可以实现网状的网络通信请求

与Docker 必知必会4----容器之间的通信相似的内容:

Docker 必知必会4----容器之间的通信

前面几篇文章,我们聊了docker的基本概念,以及基本的操作手段: https://www.cnblogs.com/jilodream/p/18177695 初识dockerhttps://www.cnblogs.com/jilodream/p/18184687 基本操作https://www.cn

Docker 必知必会3----使用自己制作的镜像

前面的两篇文章分别讲了,docker的基础概念,设计思路以及docker的基本操作。感兴趣的同学可以查阅: https://www.cnblogs.com/jilodream/p/18177695https://www.cnblogs.com/jilodream/p/18184687 本文我们将介绍

Docker 必知必会2----跟我来一步步执行基本操作

通过前文(https://www.cnblogs.com/jilodream/p/18177695)的了解,我们已经大致明白了什么是docker,为什么要用docker,以及docker的基本设计思路是什么。今天来看下,docker的基本操作有哪些? 1、linux下安装docker 首先我们来安装

Docker 必知必会----初识

什么是Docker?Docker 是一个开源的容器管理引擎。开发者可以通过Docker直接管理应用程序所需要的容器。它的logo如下: 为什么需要Docker使用Docker主要有两个原因,1、屏蔽不同环境的硬件差异,减轻开发人员在不同环境上,为了适配环境差异所需要做的工作。如各项系统配置、环境变量

500行代码手写docker开篇-goland远程编译环境配置

(1)500行代码手写docker开篇-goland远程编译环境配置 本系列教程主要是为了弄清楚容器化的原理,纸上得来终觉浅,绝知此事要躬行,理论始终不及动手实践来的深刻,所以这个系列会用go语言实现一个类似docker的容器化功能,最终能够容器化的运行一个进程。 代码最终运行效果 本系列源码已经上

500行代码手写docker-以新命名空间运行程序

(2)500行代码手写docker-以新命名空间运行程序 本系列教程主要是为了弄清楚容器化的原理,纸上得来终觉浅,绝知此事要躬行,理论始终不及动手实践来的深刻,所以这个系列会用go语言实现一个类似docker的容器化功能,最终能够容器化的运行一个进程。 本章的源码已经上传到github,地址如下:

500行代码代码手写docker-将rootfs设置为只读镜像

# (3)500行代码代码手写docker-将rootfs设置为只读镜像 > 本系列教程主要是为了弄清楚容器化的原理,纸上得来终觉浅,绝知此事要躬行,理论始终不及动手实践来的深刻,所以这个系列会用go语言实现一个类似docker的容器化功能,最终能够容器化的运行一个进程。 本章的源码已经上传到git

500代码行代码手写docker-设置网络命名空间

# (4)500代码行代码手写docker-设置网络命名空间 > 本系列教程主要是为了弄清楚容器化的原理,纸上得来终觉浅,绝知此事要躬行,理论始终不及动手实践来的深刻,所以这个系列会用go语言实现一个类似docker的容器化功能,最终能够容器化的运行一个进程。 本章的源码已经上传到github,地址

500行代码手写docker-实现硬件资源限制cgroups

# (5)500行代码手写docker-实现硬件资源限制cgroups > 本系列教程主要是为了弄清楚容器化的原理,纸上得来终觉浅,绝知此事要躬行,理论始终不及动手实践来的深刻,所以这个系列会用go语言实现一个类似docker的容器化功能,最终能够容器化的运行一个进程。 本章的源码已经上传到gith

Docker通信全视角:原理、实践与技术洞察

本文全面深入地探讨了Docker容器通信技术,从基础概念、网络模型、核心组件到实战应用。详细介绍了不同网络模式及其实现,提供了容器通信的技术细节和实用案例,旨在为专业从业者提供深入的技术洞见和实际操作指南。 关注【TechLeadCloud】,分享互联网架构、云服务技术的全维度知识。作者拥有10+年