原文地址:https://blog.csdn.net/subfate/article/details/81396532?utm_source=copy

很多时候,同一台机器上,需要运行多个docker容器,前文提到的docker-compose就是方便同时管理多个容器的工具,那么,容器与容器之间如何访问、通信呢?本文对此问题进行探讨。

方式一:内部网络
在安装docker时,会自动创建一个默认的bridge网络docker0。如下:

$ ifconfig
docker0   Link encap:以太网  硬件地址 02:42:7b:b6:74:3b  
          inet 地址:172.17.0.1  广播:0.0.0.0  掩码:255.255.0.0
          inet6 地址: fe80::42:7bff:feb6:743b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          接收数据包:575938 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:700716 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:0
          接收字节:47416735 (47.4 MB)  发送字节:1246042404 (1.2 GB)

每个容器启动时,都会创建对应的网卡,地址为172.17.0.X,因此,容器之间都可以通过对应的IP地址进行访问。
然后,运行ubuntu镜像:

docker run -it –rm ubuntu bash

在同一台电脑启动另一个终端,启动ubuntu镜像,使用同样的命令启动ubuntu镜像:

docker run -it --rm ubuntu bash

两个容器的IP如下(因为都是相同的镜像,所以直接列出IP地址):

root@4e097f487019:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:02  
          inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:25 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3653 (3.6 KB)  TX bytes:0 (0.0 B)

root@c02729d604f6:/# ifconfig  
eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:03  
          inet addr:172.17.0.3  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:23 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3380 (3.3 KB)  TX bytes:0 (0.0 B)
Ping测试结果如下:

root@c02729d604f6:/# ping -c 3 172.17.0.2
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.178 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.118 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.119 ms
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.118/0.138/0.178/0.028 ms
这个方式只能通过IP形式,前提是要知道每个容器的IP地址。这种方式实用性不强。

方式二:使用link
在方式一基础上,使用–link选项,则可以将网络别名(或容器别名)的方法进行ping。
先启动ubuntu镜像:

docker run -it --rm --name ubuntu1 ubuntu bash

这里将其命名为ubnntu1。
接着在另一个终端启动再启动ubuntu镜像:

docker run -it --rm --name ubuntu2 --link ubuntu1:ubuntu1  ubuntu bash

这个容器命名为ubuntu2,而且将其连接到ubuntu1中。注意–link ubuntu1:ubuntu1第一个ubuntu1表示容器,第二个ubuntu1表示网络/容器别名。为了统一性,建议两者相同(这种情况下,只需要写–link ubuntu1即可,文中只是为了示例其选项用法)。
在这个容器中查看hosts文件,内容如下:

root@f8199115a731:/# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      ubuntu1 e288b5d2f0a4
172.17.0.3      f8199115a731

倒数第二行看到,已经将IP地址172.17.0.2和ubuntu1(容器ID为e288b5d2f0a4)对应起来了。
下面ping测试

root@f8199115a731:/# ping -c 3 172.17.0.2  
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.123 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.109 ms
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.109/0.114/0.123/0.000 ms
root@f8199115a731:/#

使用ping -c 3 ubuntu1也可以ping通。

root@f8199115a731:/# ping -c 3 ubuntu1    
PING ubuntu1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.134 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.121 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.121 ms
--- ubuntu1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.121/0.125/0.134/0.000 ms

对于容器A和容器B之间使用–link连接,必须先启动其中一个容器,比如容器A,然后在启动容器B时,将其连接到容器A。这样,就可以在容器B中使用网络别名连接容器A了。以gitlab为jenkins为例,实际应用中,需要先启动gitlab,然后启动jenkins并连接到gitlab容器。

方式三:自定义bridge网络
首先在主机上创建一个网络,命令如下:

docker network create mynet
1
在主机用ifconfig查看网络情况,对应的网卡地址如下:

br-49d34a6504d1 Link encap:以太网  硬件地址 02:42:bc:ba:62:17  
          inet 地址:172.18.0.1  广播:0.0.0.0  掩码:255.255.0.0
          inet6 地址: fe80::42:bcff:feba:6217/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          接收数据包:1400 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:1558 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:0
          接收字节:79757 (79.7 KB)  发送字节:3650465 (3.6 MB)

注:可以创建多个网络,每个网络IP范围均不相同。
然后,运行ubuntu镜像:

docker run -it --rm --network mynet --network-alias ubuntu1  ubuntu bash

其中,--network mynet表示使用mynet网络,--network-alias ubuntu1表示该容器运行时,使用的网络别名为ubuntu1。(网络别名的作用类似hostname,不管容器IP如何变化,都可以使用同一个别名。)
接着,在同一台电脑启动另一个终端,启动ubuntu镜像:

docker run -it --rm --network mynet --network-alias ubuntu2 ubuntu bash

命令形式同上。只是将网络别名改为ubuntu2。
在ubuntu容器中使用ifconfig查看该容器的IP地址,如下:

root@74f4089ce79c:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:12:00:02  
          inet addr:172.18.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1575 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1405 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3652734 (3.6 MB)  TX bytes:99679 (99.6 KB)

再ping另一个容器ubuntu2,结果可以ping通。

root@74f4089ce79c:/# ping ubuntu2
PING jenkins (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: icmp_seq=0 ttl=64 time=0.142 ms
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.131 ms

同样地,在ubuntu2容器中ping另一个容器ubuntu,也可以ping通。

root@927fe3bab506:/# ping ubuntu
PING ubuntu (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.122 ms
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.113 ms

推荐使用这个方式。
默认网络中的link是静态的,不允许链接容器重启,而自定义网络下的link是动态的,支持链接容器重启(以及IP变化)
因此,使用–link时链接的容器,在默认网络中必须提前创建好,而自定义网络下不必预先建好。使用网络别名后,不管容器ip地址如何变化,都可以根据别名进行连接。

docker网络相关命令
在主机上创建一个网络,命令如下:

docker network create mynet

查看自定义bridge网络命令如下:

docker network inspect mynet

移除网络要求网络中所有的容器关闭或断开与此网络的连接时,才能够使用移除命令:

docker network disconnet mynet 容器ID

再移除网络

docker network rm mynet

Docker容器相互访问的更多相关文章

  1. docker 容器不能访问宿主端口原因

    因为数据包到了eth0的 上的iptables 表,首先匹配PREROUTING 链,这个拒绝了来自docker0的流量,从而跳到input链,input没有放开服务端口,所以容器访问宿主端口失败;但 ...

  2. 解决Docker容器内访问宿主机MySQL数据库服务器的问题

    懒得描述太多,总归是解决了问题,方法简要记录如下,虽然简要,但是完整,一来纪念处理该问题耗费的大半天时间,二来本着共享精神帮助其他遇到该问题的哥们儿,当然这个方法并不一定能解决你们的问题,但是多少能提 ...

  3. docker 容器内部访问宿主机

    在宿主机执行: ifconfig 然后查看 docker0 的那个网卡的 ip 地址,比如我的是 172.18.0.1

  4. 关于docker容器访问的主机的端口问题

    docker容器需要访问主机的,不能使用127.0.0.1,127.0.0.1访问的是docker容器不是主机: docker容器创建时会分配一个主机ip,可在主机使用命令 docker inspec ...

  5. Docker容器学习梳理 - 容器间网络通信设置(Pipework和Open vSwitch)

    自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求.容器的网络通信又可以分为两大方面:单主机容器上的相互通信,和跨主机的容器相互通信.下面将分别针对这两方面,对容 ...

  6. docker容器网络通信原理分析

    概述 自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求.而容器的网络通信又可以分为两大方面:单主机容器上的相互通信和跨主机的容器相互通信.而本文将分别针对这两 ...

  7. docker容器网络通信原理分析(转)

    概述 自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求.而容器的网络通信又可以分为两大方面:单主机容器上的相互通信和跨主机的容器相互通信.而本文将分别针对这两 ...

  8. docker容器的学习笔记

    目录 Docker入门学习笔记(一) 1. 什么是Docker? 2. Docke的目标 3. Docker通常应用场景 4. Docker的基本组成 补:Docker容器相关技术简介 安装Docke ...

  9. 外部连接mysql docker容器异常

    为了方便,使用python测试连接mysql容器 脚本内容非常简单 #!/usr/bin/python3 import pymysql conn=pymysql.connect(host=,passw ...

随机推荐

  1. [Functional Programming + React] Provide a reasonable default value for mapStateToProps in case initial state is undefined

    For example we have a component, it needs to call 'react-redux' connect function. import { compose, ...

  2. JAVA 报错exe4j中this executable was created with an evaluation 怎么办

    如果使用未破解注册的exe4j打包JAR文件为EXE,运行EXE的时候就会出现下面的提示   打开exe4j软件,Change License或者是输入序列号,然后用注册机算一个注册码即可  

  3. IEngineEditor接口的0x80004003错误

    在定制ArcEngine数据编辑程序时,经常使用IEngineEditor 接口来完成开始.保存和停止编辑.但我遇到了一个问题,测试纠结了两天终于解决,我十分佩服自己.嘻嘻. 错误描述 使用IEngi ...

  4. Python小任务 - 如何编写指定时间执行的Python小程序

    我们在平时的工作中经常会遇到这样的需求,需要再某个时间点执行一段程序逻辑. 那么,在python中我们是怎么做的呢? 下面看代码: waitDesignatedTimeToRun.py import ...

  5. WPF加载HTML、WPF与JavaScript交互

    目录 一.WebBrowser加载远程网页 二.WebBrowser加载本地网页,注:不可以加载本地样式CSS和脚本JS文件 三.WebBrowser隐藏网页的JavaScript错误 四.网页屏蔽鼠 ...

  6. FIS前端集成解决方案

    FIS前端集成解决方案-文档结构 什么是FIS 部署FIS FIS基本使用 模块定义 加载方式 调用Tangram 2.0 FIS开发实例 --附件下载-- 什么是FIS FIS提供了一套贯穿开发流程 ...

  7. CSS 之 伪类及伪元素

    伪类和伪元素用起来非常的方便,在查阅资料及测试后整理下来. 一.伪类 CSS 伪类用于向某些选择器添加特殊的效果.伪类对元素进行分类是基于特征(characteristics)而不是它们的名字.属性或 ...

  8. Java通过ScriptEngine 执行js脚本案例

    public static void main(String[] args) throws ScriptException, FileNotFoundException, NoSuchMethodEx ...

  9. 关于inode&硬连接

    这两天看了一道面试题,什么是inode?我勒个去,第一次听说.于是Google了一下,发现下面这段内容讲解的非常不错,供大家参考. 一.inode是什么? 理解inode,要从文件储存说起.文件储存在 ...

  10. vuejs组件交互 - 02 - 事件中心管理组件间的通信

    事件中心 这个可以是一个空的全局的Vue实例,其他的组件利用这个实例emit和on自定义事件,这样组件定义了自己的事件处理方法. import Vue from 'Vue' window.eventH ...