前言已经介绍了Docker的镜像和容器,下面主要涉及Docker网络相关知识

Linux网络命名空间

#进入一个已经运行的容器
docker exec -it 61512b362534 bash
#执行ip a
ip a


会发现有一些接口,这就是这个容器自己的network namespace
退出容器,在宿主机执行ip a

显示出来的是宿主机的network namespace,这2个network namespace是不一样的
再创建第二个容器,2个docker容器的network namespace也是不一样的,他们之前是隔离开的。并且2个容器是可以ping通的

底层原理


(1)创建network namespace

#创建2个network namespace
ip netns add test1
ip netns add test2
#删除network namespace
ip netns delete test1
#查看创建network namespace
ip netns list

(2)查看test1、test2的network namespace信息

ip netns exec test1 ip a
ip netns exec test2 ip a

(3) 使lo端口up起来

ip netns exec test1 ip link set dev lo

(4) 添加一对veth接口

ip link add veth-test1 type veth peer name veth-test2

(5) 将veth-test1添加到test1中,veth-test2添加到test2

ip link set veth-test1 netns test1
ip link set veth-test2 netns test2
#查看是否添加成功
ip netns exec test1 ip link
ip netns exec test2 ip link

(6)给veth-test1、veth-test2分配端口

ip netns exec test1 ip addr add 192.168.1.1/24 dev veth-test1
ip netns exec test2 ip addr add 192.168.1.2/24 dev veth-test2

(7)将veth-test1、veth-test2端口up,并查看ip

#up端口
ip netns exec test1 ip link set dev veth-test1
ip netns exec test2 ip link set dev veth-test2
#查看ip
ip netns exec test1 ip a
ip netns exec test2 ip a

(8)查看互相是否可以通信

ip netns exec test1 ping 192.168.1.2
ip netns exec test2 ping 192.168.1.1


其实docker容器之间的通信也是通过这种技术实现的

Docker Bridge0

Container Test1容器通过自己端口与宿主机的docker0的veth端口相连,Container Test2容器通过自己的端口与宿主机另外一个veth端口相连,这样就保证了2个容器可以互相通信

#查看docker的network
docker network ls
#查看bridge中有哪些容器
docker network inspect <network ID>
ip a

与其他容器通信时,通过ip来访问的。创建容器时使用–link 来实现容器连接,这样通过name也可以访问了,但是link这种方式是单向的
除非2个容器都是连接在用户自己创建的network上,可以使用name来访问

docker run -d --name test2 --link test1 container1
docker exec -it test2 bash
ping test1
#创建network
docker network create net3
#删除network
docker network rm net3
#新建容器,使用net3,使用--network
docker run -d --name test2 --network net3 container1
#将已经存在的容器连接到net3上
docker network connect net3 container1

端口映射

我们pull了一个nginx镜像,创建nginx容器,但是我们在外面无法访问nginx容器的80端口,这时就要将nginx服务暴露给外面,可以将nginx的80端口映射到本地

# -p表示端口映射
docker run --name nginx -d -p 80:80

none和host network

当容器连接到none时,不存在ip和mac地址,none是与外界隔绝的network
当容器连接到host时,他没有独立的network,他与宿主机的network共享一套network(如果创建2个nginx都绑定在80端口,容易端口冲突)

多机通信


docker提供了overlay来实现2台linux主机之间的通信
2台linux主机通信,必须保证2个主机上的docker容器的ip不一样,我们使用etcd来实现

下载etcd

#下载
wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
#解压缩
tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
#进入etcd-v3.0.12-linux-amd64目录下
cd etcd-v3.0.12-linux-amd64

启动服务

#启动第一台node1主机etcd服务
nohup ./etcd --name docker-node1 --initial-advertise-peer-urls http://192.168.186.129:2380 \
--listen-peer-urls http://192.168.186.129:2380 \
--listen-client-urls http://192.168.186.129:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.186.129:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.186.129:2380,docker-node2=http://192.168.186.130:2380 \
--initial-cluster-state new&
#启动另一台node2主机etcd服务
nohup ./etcd --name docker-node2 --initial-advertise-peer-urls http://192.168.186.130:2380 \
--listen-peer-urls http://192.168.186.130:2380 \
--listen-client-urls http://192.168.186.130:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.186.130:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.186.129:2380,docker-node2=http://192.168.186.130:2380 \
--initial-cluster-state new&

查看cluster是否建立

./etcdctl cluster-health

重启docker

#node1
service docker stop
sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.186.129:2379 --cluster-advertise=192.168.186.129:2375&
#node2
service docker stop
sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.186.130:2379 --cluster-advertise=192.168.186.130:2375&

创建overlay

#在node1上创建overlay
docker network create -d overlay demo
#查看node1上的network
docker network ls
#再查看node2主机上的network,会发现存在名叫demo的overlay
docker network ls

创建容器

#在node1主机上创建busybox容器
docker run -d --name test1 --net demo busybox sh -c "while true; do sleep 3600; done"
#在node2上再次创建,会发现报错,提示test1已经存在
docker run -d --name test1 --net demo busybox sh -c "while true; do sleep 3600; done"
#创建test2
docker run -d --name test2 --net demo busybox sh -c "while true; do sleep 3600; done"

查看2个容器的ip,是不一致的

docker exec -it test1 ip a
docker exec -it test2 ip a