目录

Docker网络与容器之间通信原理

Docker网络与容器之间通信原理

1、namespace

扩展知识:

实战:打通两个命名空间的网络,模拟两个容器通信原理

查看命名空间列表
ip netns list
新增一个网络命名空间(名称test1)
ip netns add  test1
删除网络命名空间test1
ip netns delete test1
查看本机namespace默认是down的状态
ip netns exec test1 ip a
变为up状态,显示为unknown
ip netns exec test1 ip link set dev lo up
ip netns exec test1 ip a

https://i-blog.csdnimg.cn/blog_migrate/01c7fa8d6f5c750eb9ec53dffc1e8e35.png

1)先创建一对veth虚拟网络设备veth-test1和veth-test2

创建并查看link
ip link add veth-test1 type veth peer name veth-test2
ip link 或者 ip addr

https://i-blog.csdnimg.cn/blog_migrate/624e79f1f01ac8c69d69cb40a0c82b33.png

  1. 把veth-test1设置到test1命名空间,把veth-test2设置到test2命名空间:
添加veth-test1到test1的namespace
ip link set veth-test1 netns test1
ip netns exec test1 ip a
添加并查看veth-test2
ip link set veth-test2 netns test2
ip netns exec test2 ip a

https://i-blog.csdnimg.cn/blog_migrate/333c54159d4f707e350ed369f4fac2b4.png

3)给两个主机分别配置ip(进入命名空间启动网卡然后给网卡配置ip),然后互ping

ip netns exec test1 ip link set veth-test1 up

ip netns exec test2 ip link set veth-test2 up

ip netns exec test1 ip a add 192.168.1.1/24 dev veth-test1

ip netns exec test2 ip a add 192.168.1.2/24 dev veth-test2
# 然后互ping
ip netns exec test1 ping 192.168.1.2
ip netns exec test2 ping 192.168.1.1

https://i-blog.csdnimg.cn/blog_migrate/63840cbb0af921279449c6ccf6776ad1.png

https://i-blog.csdnimg.cn/blog_migrate/8be589bab7f2d652c648949051854974.png

2、bridge网络(桥接网络)

实战演练:

test1与test2通过docker0访问宿主机然后访问的百度外网;

test1、test2与docker在同一网段内是互通的

https://i-blog.csdnimg.cn/blog_migrate/4f3592eaf4092dc377bed5d7c3a6b18c.png

1、新建3个容器

docker run -d –name test1 busybox /bin/sh -c “while true;do sleep 3600;done”

docker run -d –name test2 busybox /bin/sh -c “while true;do sleep 3600;done”

docker run -d –name test3 busybox /bin/sh -c “while true;do sleep 3600;done”

2、可以看到容器test1和本机的网卡有veth对,test2与test3也是如此,通过虚拟出的网卡与veth一一对应建立通信

docker exec test1 ip a

https://i-blog.csdnimg.cn/blog_migrate/f01e0a67a25820bbce9100598a7b7aca.png

3、查看本机网卡,docker0下这个veth与docker容器中的test1网卡一一对应

ip addr

https://i-blog.csdnimg.cn/blog_migrate/185ce14121014f8c7a86f6478586487a.png

4、安装brctl查看交接网络

yum -y install bridge-utils

5、查看本机的veth,查看本机网卡,docker0下有这3个veth(veth40000c8、veth7c8618c、veth825d419)

brctl show

https://i-blog.csdnimg.cn/blog_migrate/2946c7d302b756206754568e49f4739c.png

3、容器通信

解决不同ip网段不同之间的通信

1、首先启动一个容器test5

docker run -d –name test5 busybox /bin/sh -c “while true;do sleep 3600;done”

2、再创建一个有—link的容器,谁link谁就能ping通谁

docker run -d –name test6 –link test5 busybox /bin/sh -c “while true;do sleep 3600;done”

3、此时,可以用test6直接访问test5,类似于访问主机名,但是test5是单独创建的,所以test5容器内是无法平通test6的

https://i-blog.csdnimg.cn/blog_migrate/42f443b7f5f2637f592f0c505a421c30.png

4、端口映射

实战运行一个nginx并对外提供访问

1.运行一个nginx容器

docker run –name web -d nginx

2.查看桥接网络状态

docker network inspect bridge

https://i-blog.csdnimg.cn/blog_migrate/4118197bde6504fa59ef4507f4d3aedc.png

3.容器内可以访问,容器外访问不到

ping 172.17.0.7

telnet 172.17.0.7 80

curl http://172.17.0.7

https://i-blog.csdnimg.cn/blog_migrate/622b8ddd390501865e29d8dad0937214.png

https://i-blog.csdnimg.cn/blog_migrate/8a9eb4b37b354d44d1392df1ea355b82.png

https://i-blog.csdnimg.cn/blog_migrate/5d882b788ab39b1a045441fbd8065886.png

4.停止并删除容器

docker stop web

docker stop web

5.重新创建容器,并指定端口映射

docker run –name web -d -p 80:80 nginx

6.外界可以访问了

http://192.168.56.10/

https://i-blog.csdnimg.cn/blog_migrate/5f78b8fb7370798c9fc995ba762c482e.png

5、网络的none和host

查看docker所有网络

docker network ls

none网络:应用场景是安全性极高的情况,应用并不多

创建新的容器,使用none网络

docker run -d –name test7 –network none busybox /bin/sh -c “while true;do sleep 3600;done”

查看none网络状态

docker network inspect none

外界访问不了也无法查看该容器ip,只有进去,127.0.0.1可以访问

ip netns exec test7 a

docker exec -it test7 /bin/sh

ip a

https://i-blog.csdnimg.cn/blog_migrate/f5fcc0b42ffcabefa48f7ea9d3f78505.png

https://i-blog.csdnimg.cn/blog_migrate/e6e98b156e0dcecfa2398ca521fe15eb.png

host网络,也就是复制并使用宿主机网络:

创建新的容器,使用host网络

docker run -d –name test8 –network host busybox /bin/sh -c “while true;do sleep 3600;done”

查看host网络状态

docker network inspect host

进入容器,查看网络,发现容器外宿主机网络一致

ip netns exec test8 a

docker exec -it test8 /bin/sh

ip a

https://i-blog.csdnimg.cn/blog_migrate/b2b260d4f1ad7ed3ebe85cb57b0c66ee.png

6、多容器部署和应用

实例

运行redis容器

docker run -d –name redis redis

编写app.py,做web服务,

$ cat app.py 
from flask import Flask
from redis import Redis
import os
import socket

app=Flask(__name__)
redis=Redis(host=os.environ.get('REDIS_HOST','127.0.0.1'),port=6379)

@app.route('/')
def hello():
    redis.incr('hits')
    return 'hello docker! count %s and hostname is %s. \n'%(redis.get('hits'),socket.gethostname())

if __name__ == "__main__":
        app.run(host="0.0.0.0",port=5000,debug=True)

编写Dockerfile

$ vi Dockerfile 

FROM python:2.7
LABEL maintaner="[email protected]"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 5000
CMD ["python","app.py"]

构建redis镜像

docker build -t liuyuanshan/flask-redis .

运行容器,并设置环境变量REDIS_HOST,设置flask-redis 去link redis

docker run -d -p 5000:5000 –link redis –name flask-redis -e REDIS_HOST=redis liuyuanshan/flask-redis

进入容器并查看环境变量

docker exec -it redis /bin/bash

env

访问:

http://192.168.56.10:5000

https://i-blog.csdnimg.cn/blog_migrate/9a3900829d83186f3761e238102341e5.png

7、多机器多容器通信