Docker容器间互访的几种方式

我们都知道Docker容器之间是互相隔离的,不能互相访问,但如果有些依赖关系的服务要怎么办呢。下面介绍几种方法解决容器互访问题。

虚拟ip访问

安装Docker时,Docker会默认创建一个内部的桥接网络docker0,每创建一个容器分配一个虚拟网卡,容器之间可以根据ip互相访问。

[root@master ~]# ifconfig 
docker0: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:ecff:fefb:4f56  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ec:fb:4f:56  txqueuelen 0  (Ethernet)
        RX packets 439143754  bytes 128557512771 (119.7 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 204101251  bytes 111401928320 (103.7 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

显然上面网卡的地址是172.17.0.1,然后看一下其他容器的IP地址,如:

[root@master ~]# docker ps
132b54e8bf0f        nginx                   "nginx -g 'daemon of…"   10 months ago       Up 3 hours                      0.0.0.0:11180->80/tcp                                                                                    nginx
64b298e41e38        tomcat:8.5              "catalina.sh run"        10 months ago       Up 3 hours                      0.0.0.0:8092->8080/tcp                                                                                   tomcatB
20573cd3ae78        tomcat:8.5              "catalina.sh run"        10 months ago       Up 3 hours                      0.0.0.0:8091->8080/tcp                                                                                   tomcatA

看一下nginx的IP地址:

[root@master ~]# docker inspect 132b54e8bf0f
...
  "Networks": {
       "bridge": {
           "IPAMConfig": null,
           "Links": null,
           "Aliases": null,
           "NetworkID": "4f2301f96036e312cf04bc2d893764f39493090e35d15a3d0bc46980a3817e9a",
           "EndpointID": "1cc6ba035ff2f68d85db21651a2c0b09be94f54f84fd8cfca5ee779703fa1130",
           "Gateway": "172.17.0.1",
           "IPAddress": "172.17.0.4",
           "IPPrefixLen": 16,
           "IPv6Gateway": "",
           "GlobalIPv6Address": "",
           "GlobalIPv6PrefixLen": 0,
           "MacAddress": "02:42:ac:11:00:04",
           "DriverOpts": null
       }
   }

地址是172.17.0.4,再看一下tomcatA的IP地址:

[root@master ~]# docker inspect tomcatA
...
	"Networks": {
		"bridge": {
           "IPAMConfig": null,
           "Links": null,
           "Aliases": null,
           "NetworkID": "4f2301f96036e312cf04bc2d893764f39493090e35d15a3d0bc46980a3817e9a",
           "EndpointID": "70abb178c727cf4766bbd8e8cdb1fe1d285e4d1ad150459a6418f9ee7a428274",
           "Gateway": "172.17.0.1",
           "IPAddress": "172.17.0.6",
           "IPPrefixLen": 16,
           "IPv6Gateway": "",
           "GlobalIPv6Address": "",
           "GlobalIPv6PrefixLen": 0,
           "MacAddress": "02:42:ac:11:00:06",
           "DriverOpts": null
       }
   }

地址是172.17.0.6,注意,这两个容器的Gateway都是172.17.0.1,因此,他们之间相互可以ping通。
如下:

[root@master ~]# docker exec -it tomcatB /bin/bash
root@64b298e41e38:/usr/local/tomcat# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
31: eth0@if32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
root@64b298e41e38:/usr/local/tomcat# ping 172.17.0.6
PING 172.17.0.6 (172.17.0.6) 56(84) bytes of data.
64 bytes from 172.17.0.6: icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from 172.17.0.6: icmp_seq=2 ttl=64 time=0.092 ms
64 bytes from 172.17.0.6: icmp_seq=3 ttl=64 time=0.105 ms
64 bytes from 172.17.0.6: icmp_seq=4 ttl=64 time=0.100 ms
64 bytes from 172.17.0.6: icmp_seq=5 ttl=64 time=0.059 ms
^C
--- 172.17.0.6 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3999ms
rtt min/avg/max/mdev = 0.059/0.093/0.111/0.020 ms

上面,首先进入容器tomcatB,然后获取IP地址是172.17.0.5,再去ping容器tomcatA的地址172.17.0.6,通过。

使用容器内IP地址这种方式,首先你必须知道每个容器的IP,但实际情况是你并不一定能获取到这个地址,在实际使用中并不实用。
如:

[root@datanode1 ~]# docker ps
CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS              PORTS               NAMES
2f81fe405433        mysql:5.7                           "/.r/r docker-entryp…"   2 months ago        Up 2 months                             r-mysql-mysql-1-30bfa217

有一个这样的mysql容器,进入容器后,你无法使用命令ifconfig或者ip address,因为容器就没有集成这些命令,然后用docker inspect查看容器也发现IP地址为空

[root@datanode1 ~]# docker exec -it 2f81fe405433 /bin/bash
root@2f81fe405433:/# ifconfig
bash: ifconfig: command not found
root@2f81fe405433:/# ip address
bash: ip: command not found
root@2f81fe405433:/# exit
exit
[root@datanode1 ~]# docker inspect 2f81fe405433
...
  "Networks": {
      "none": {
          "IPAMConfig": null,
          "Links": null,
          "Aliases": null,
          "NetworkID": "801ce736d6cff60a8eab3e8bff5727f1b6ebaa89f2d53315514dfc3dbf112134",
          "EndpointID": "0fee4ef4c035c10040da81166054df8d805fdd3f0ff3aa97e595baa05f71ff70",
          "Gateway": "",
          "IPAddress": "",
          "IPPrefixLen": 0,
          "IPv6Gateway": "",
          "GlobalIPv6Address": "",
          "GlobalIPv6PrefixLen": 0,
          "MacAddress": "",
          "DriverOpts": null
      }
  }

link

运行容器的时候加上参数link。

运行第一个容器

docker run -it --name centos-1 docker.io/centos:latest

运行第二个容器

[root@CentOS ~]# docker run -it --name centos-2 --link centos-1:centos-1 docker.io/centos:latest

--link:参数中第一个centos-1是容器名,第二个centos-1是定义的容器别名(使用别名访问容器),为了方便使用,一般别名默认容器名。

[root@e0841aa13c5b /]# ping centos-1
PING centos-1 (172.17.0.7) 56(84) bytes of data.
64 bytes from centos-1 (172.17.0.7): icmp_seq=1 ttl=64 time=0.210 ms
64 bytes from centos-1 (172.17.0.7): icmp_seq=2 ttl=64 time=0.116 ms
64 bytes from centos-1 (172.17.0.7): icmp_seq=3 ttl=64 time=0.112 ms
64 bytes from centos-1 (172.17.0.7): icmp_seq=4 ttl=64 time=0.114 ms

此方法对容器创建的顺序有要求,如果集群内部多个容器要互访,使用就不太方便。

创建bridge网络

  1. 安装好docker后,运行如下命令创建bridge网络:docker network create testnet

查询到新创建的bridge testnet

[root@master ~]# docker network create testnet
41b2f0c05d93aaf14eea6b686c9da6bcfb9b36b3ab4f6f81bc08b65d6b3ac935
[root@master ~]# docker network ls
NETWORK ID          NAME                   DRIVER              SCOPE
4f2301f96036        bridge                 bridge              local
4ef93e2e7978        docker-taiga_default   bridge              local
2b3e95aceda3        host                   host                local
34d4431a931c        none                   null                local
41b2f0c05d93        testnet                bridge              local
  1. 运行容器连接到testnet网络

使用方法:docker run -it --name <容器名> --network <bridge> --network-alias <网络别名> <镜像名>

[root@master ~]# docker run -it --name centos-1 --network testnet --network-alias centos-1 docker.io/centos:latest
[root@master ~]# docker run -it --name centos-2 --network testnet --network-alias centos-2 docker.io/centos:latest
  1. 从一个容器ping另外一个容器,测试结果如下
[root@0bce3262d2df /]# ping centos-1
PING centos-1 (172.20.0.2) 56(84) bytes of data.
64 bytes from centos-1.testnet (172.20.0.2): icmp_seq=1 ttl=64 time=0.158 ms
64 bytes from centos-1.testnet (172.20.0.2): icmp_seq=2 ttl=64 time=0.108 ms
64 bytes from centos-1.testnet (172.20.0.2): icmp_seq=3 ttl=64 time=0.112 ms
64 bytes from centos-1.testnet (172.20.0.2): icmp_seq=4 ttl=64 time=0.113 ms 
  1. 若访问容器中服务,可以使用这用方式访问 <网络别名>:<服务端口号>

推荐使用这种方法,自定义网络,因为使用的是网络别名,可以不用顾虑ip是否变动,只要连接到docker内部bright网络即可互访。bridge也可以建立多个,隔离在不同的网段。

容器内脚本访问容器内服务

容器服务

1、以mysql:5.6镜像创建一个mysql容器服务 容器端口3306映射宿主机端口3307
启动后配置阿里云服务器安全组开放映射的端口

docker run -id -p 3307:3306 \
--name=my1 \
--network testnet \
--network-alias my1 \
-v $PWD/conf/myconf.d:/etc/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
mysql:5.6

脚本创建

2、以centos:7基础镜像创建一个python脚本 查询mysql数据库中的内容

docker run -it \
--name=my2 \
--network testnet \
--network-alias my2 \
centos:7 \
bash

脚本

import pymysql

db = pymysql.connect("120.78.72.136","root","root","docker",port=3307)
cursor = db.cursor()
cursor.execute("SELECT * FROM test")
data = cursor.fetchone()
print (data)
db.close()

ip为宿主机ip 端口为容器映射到宿主机的端口

容器访问容器服务(离线)

s1容器放mysql服务,s2容器放一个python脚本能够查询s1容器内mysql数据库的内容

由上面方法创建bridge网络,s1和s2容器能够后互相ping通

创建s1容器(mysql)

docker run -id -p 3307:3306 \
--name=s1 \
--network testnet \
--network-alias s1 \
-v $PWD/conf/myconf.d:/etc/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
mysql:5.6

容器端口3306映射宿主机端口3307,对外开放3307端口,若想让外部访问需配置安全组开放3307端口

docker exec -it s1 bash    # 进入容器内
mysql -uroot -proot        # 进入mysql数据库 创建库和表

创建s2容器(python脚本)

容器创建

docker run -it \
--name=my2 \
--network testnet \
--network-alias my2 \
centos:7 \
bash

脚本创建

import pymysql

db = pymysql.connect("s1","root","root","docker",port=3306)
cursor = db.cursor()
cursor.execute("SELECT * FROM test")
data = cursor.fetchone()
print (data)
db.close()

# s1      为网络别名 在我们创建容器时创建
# 3306    容器内的服务端口号

参考:https://www.cnblogs.com/songzhixue/p/12540152.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

junehappylove

急急如律令,buibui~~

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

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

打赏作者

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

抵扣说明:

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

余额充值