主要总结的是在单个主机上的docker网络,创建用户自定义的网络,以及容器之间如何进行联通。
1 概述三种默认的网络
在docker安装之后,启动docker的服务,那么默认就会看到三个docker创建的网络:
[root@docker-ce ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
33515cad48dc bridge bridge local
34a3b40daa38 host host local
0be7c01923ae none null local
在上面的结果中可以看到,创建了一个none的网络,这个网络和主机是不通的,也就是无法连接的,相当于一个隔离的网络;而host网络,主要是表示容器和主机共享同一个网络栈,也就是网络接口都是相同的,也就是当容器里面监听了80端口,那么在主机上会监听80端口;而bridge接口,主要就是桥接的网络接口,在创建容器的时候,默认都是使用这个桥接的网络接口,查看主机上的接口如下所示:
[root@docker-ce ~]# ip -4 addr show(查看ipv4的网络)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 192.168.1.111/24 brd 192.168.1.255 scope global ens33
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
从以上的结果可以看到,在本机上是看不到host网络和none网络,而在本机上是可以看到桥接的网络,可以看到默认创建的docker0的ip地址就是网关。
2 创建一个none网络的容器:
[root@docker-ce ~]# docker run -itd --name httpd --network=none httpd(创建一个基于none网络的容器)
62ede9a7d8ad5614964525d506e12ab4973808f1605e1260aaa552a223db7aca
[root@docker-ce ~]# docker ps(查看运行的容器)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
62ede9a7d8ad httpd "httpd-foreground" 4 seconds ago Up 2 seconds httpd
[root@docker-ce ~]# docker port 62(查看容器映射的端口)
[root@docker-ce ~]# docker network inspect none(查看连接这个网络的容器)
。。。。
"ConfigOnly": false,
"Containers": { "62ede9a7d8ad5614964525d506e12ab4973808f1605e1260aaa552a223db7aca": {
"Name": "httpd",
"EndpointID": "b0f3a2f2de5bc07a07747b7c747f62fa0116ca35f26fc41b66b9d92d2cd089bd",
"MacAddress": "",
"IPv4Address": "",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
从以上可以看到,创建一个none网络的容器,在主机上不会创建虚拟的网络接口,并且容器也不会分配网络ip和mac地址,从而外界无法连接,形成一个隔离的环境,感觉。。没啥用。
3 创建一个基于host网络的容器
[root@docker-ce ~]# docker run -itd --name kel --network=host httpd (创建一个基于host的容器)
ef828d5836143aa49928b46e941a90be877c5e8caf439a2617c26cb30d4d21c1
[root@docker-ce ~]# netstat -ntlp|grep httpd (在本机上已经监听了80端口)
tcp6 0 0 :::80 :::* LISTEN 8597/httpd
[root@docker-ce ~]# docker ps(查看运行的容器)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef828d583614 httpd "httpd-foreground" 9 seconds ago Up 8 seconds kel
从此处可以看到,两者是共享相同的网络栈的,也就是在docker里面可以到相同的网卡信息,从而也不会在主机上创建虚拟网卡。
主要的用途就是当容器使用的网络流量很大的时候,需要性能很高的场合。
3 创建基于桥接网络的容器
[root@docker-ce ~]# docker run -itd --name testbridge httpd(创建一个基于默认的桥接的容器)
af3831c727c1d6523ab9cd1584bf22f6aaf090b2af15a324a21afba93e13597d
do[root@docker-ce ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af3831c727c1 httpd "httpd-foreground" 6 seconds ago Up 5 seconds 80/tcp testbridge
[root@docker-ce ~]# ip -4 addr show(查看ipv4的地址,主要是查看docker0的ip地址会作为网关地址)
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
[root@docker-ce ~]# docker port testbridge
[root@docker-ce ~]# docker network inspect bridge(查看桥接网络的ip地址和网关,及包含的容器)
。。。
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
"af3831c727c1d6523ab9cd1584bf22f6aaf090b2af15a324a21afba93e13597d": {(桥接的网络,容器会分配ip地址和mac地址,从而主机能够通过docker0来连接容器,从而也可以使用ssh进行连接)
"Name": "testbridge",
"EndpointID": "fed61bfff4f2703bee7c6ddfb39cd876536325586ebd35351d623481e3cb1c11",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
]
[root@docker-ce ~]# docker exec af ip addr show(容器内部的网卡)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
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
49: eth0@if50: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
[root@docker-ce ~]# ip addr show(查看本机上创建的虚拟网卡)
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:c2:a5:64:dd brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:c2ff:fea5:64dd/64 scope link
valid_lft forever preferred_lft forever
50: veth0195fae@if49: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP
可以看到在容器内部创建了一个网卡,而在主机上也创建了一个网卡,两者的关系相当于一个是锁一个钥匙,然后这个网络连接到docker0这个桥接网络上,从而可以和主机相互进行通信。
可以看到,当创建桥接网络的时候,都会创建一对虚拟网卡,也就是如果再次创建一个桥接的网络,那么依旧会创建一个虚拟网卡对。
4、 默认桥接网络中容器之间连通(非推荐方式)
创建两个容器,然后使用--link的方式,从而两个容器之间能基于主机名来进行通信,如下:
[root@docker-ce ~]# docker run -itd --name web1 httpd
8047ab360f53bd83c502fa6102910129ecf37ee0fac332001eb8cd3a233c0823
[root@docker-ce ~]# docker run -itd --name kel --link web1:web1 httpd(使用--link的方式可以连接web1这个容器)
d91faee0e8add078b3881d494c54d755ee9e006a531109255742425848c36ea5
[root@docker-ce ~]# docker exec -it d91 bash
root@d91faee0e8ad:/usr/local/apache2# ping -c 2 web1
PING web1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=2.869 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.988 ms
--- web1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.988/1.929/2.869/0.941 ms
从上可以看到,当使用默认的docker0的时候,可以使用--link的方式将两个容器进行连接。
[root@docker-ce ~]# docker network --help(查看网络的相关命令)
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
connect主要是将一个容器连接到一个存在的网络之中,一般如果加入到桥接中,那么相当于新建一个网卡,分配一个ip地址进去。
create主要是创建一个自定义的网络,一般都是桥接网络。
disconnect主要是将网卡移除,和connect是相反的作用。
ls主要是列出所有的网络设备。
inspect主要用来查看网络的详细信息。
prune主要是用来移除未使用的网络,移除的标准是这个自定义网络中最少含有一个容器在使用。
rm主要是用来删除自定义网络。
在一般环境中,都是使用自定义网络,不会使用默认的docker0网络,从而在这里 1、可以创建自定义网络
[root@docker-ce ~]# docker network create --driver=bridge kel(创建一个自定义的桥接网络kel)
602d9510407627d8c1a76ed90bf646843a29d6420265f886f434ee414ba84c6f
[root@docker-ce ~]# docker network ls(新增了一个桥接网络)
NETWORK ID NAME DRIVER SCOPE
33515cad48dc bridge bridge local
34a3b40daa38 host host local
602d95104076 kel bridge local
0be7c01923ae none null local
[root@docker-ce ~]# docker network inspect kel(查看自定义的桥接网络信息)
。。。
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
。。。
[root@docker-ce ~]# ip addr show(在主机上会新建一个相当于交换机的网络设备,ip地址为容器的网关地址)
55: br-602d95104076: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:10:51:76:99 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 scope global br-602d95104076
valid_lft forever preferred_lft forever
2 、在相同的网络中通过主机名来进行通信
[root@docker-ce ~]# docker run -itd --name kel --network=kel httpd(设定容器名称为kel,桥接网络为kel)
29879130f66a9cc9c5e1769c212a9b51398adbf65452d5689f028ed566d7643d
[root@docker-ce ~]# docker run -itd --name test --network=kel httpd设定容器名称为test,桥接网络为kel)
3bd7244e347615bdaadac8127e70928a9f510cf24878f65099a47c239b840473
[root@docker-ce ~]# docker exec -it 3b bash
root@3bd7244e3476:/usr/local/apache2# ping kel(在同一个桥接网络中,可以通过主机名直接进行通信)
PING kel (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.316 ms
root@3bd7244e3476:/usr/local/apache2# cat /etc/resolv.conf (默认的dns服务器进行了dns解析)
nameserver 127.0.0.11
options ndots:0
3、 在不同的网络中加入新网卡来进行通信
在docker0网络中新建一个容器,然后看看是否和自定义网络中的容器能通信:
[root@docker-ce ~]# docker run -itd --name old httpd(创建一个docker0网络上面的容器)
1f5e999979e2d5e5955d252daf80f6e2dded4d21ba985c9768acf4f86730582d
[root@docker-ce ~]# docker exec -it 1f bash
proot@1f5e999979e2:/usr/local/apache2# ping test(无法ping通另外一个网络的容器)
ping: unknown host
root@1f5e999979e2:/usr/local/apache2# exit
exit
[root@docker-ce ~]# docker network connect kel 1f(将容器加入到自定义网络中)
[root@docker-ce ~]# docker exec -it 1f bash
root@1f5e999979e2:/usr/local/apache2# ping test(能够基于主机名进行通信)
PING test (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: icmp_seq=0 ttl=64 time=0.714 ms
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.203 ms
两个自定义网络中,默认是不能进行通信的,主要是由于iptabes的设定。
[root@docker-ce ~]# iptables-save |grep -i isolation(查看iptables规则)
-A DOCKER-ISOLATION -i docker0 -o br-0531ccfa1784 -j DROP
-A DOCKER-ISOLATION -i br-0531ccfa1784 -o docker0 -j DROP
当把防火墙关闭之后,就会发现能ping两个不同网络的容器了,使用的命令:
[root@docker-ce ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43f61cb622ca httpd "httpd-foreground" About a minute ago Up About a minute 80/tcp test
e610e4cf4543 httpd "httpd-foreground" About a minute ago Up About a minute 80/tcp kel
[root@docker-ce ~]# systemctl stop firewalld(关闭防火墙)
[root@docker-ce ~]# docker exec -it 43 bash
root@43f61cb622ca:/usr/local/apache2# ping kel
^C
root@43f61cb622ca:/usr/local/apache2# ping 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=63 time=1.221 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=63 time=0.561 ms
而在桥接模式下,默认是可以上网的,其实也是通过防火墙做的NAT规则,从而进行源地址和目标地址转换,也就是NAT。
[root@docker-ce ~]# iptables -t nat -L(查看nat规则)
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 10.0.0.0/8 anywhere
MASQUERADE all -- 172.18.0.0/16 anywhere
MASQUERADE all -- 172.18.0.0/16 anywhere
MASQUERADE all -- 172.18.0.0/16 anywhere
MASQUERADE all -- 172.17.0.0/16 anywhere
MASQUERADE all -- 172.18.0.0/16 anywhere
4、 创建自定义网络指定ip
[root@docker-ce ~]# docker network rm kel(删除原来的自定义网络)
kel
[root@docker-ce ~]# docker network create --driver=bridge --subnet=10.0.0.0/8 --gateway=10.0.0.1 kel(指定子网和网关)
0531ccfa1784193cdb7ffbb916a7e55dc50f78d1d6981e820f00a71dd75f7a8d
[root@docker-ce ~]# docker network inspect kel(查看创建的自定义网络)
。。。
"Config": [
{
"Subnet": "10.0.0.0/8",
"Gateway": "10.0.0.1"
}
。。。
5、 访问容器端口
在访问容器端口的时候,一般使用端口映射,如下所示:
[root@docker-ce ~]# docker run -itd --name kel -p 80 httpd(主机上一个随机端口映射到容器的80端口,一般是30000端口以上)
89e5045e3bebe794b95e597b3c2388238bb5a22316b66d73593386e0cc4b39f2
docker [root@docker-ce ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
89e5045e3beb httpd "httpd-foreground" 4 seconds ago Up 2 seconds 0.0.0.0:32768->80/tcp kel
[root@docker-ce ~]# docker port kel(port用来查看映射的端口)
80/tcp -> 0.0.0.0:32768
[root@docker-ce ~]# curl localhost:32768(直接访问监听的端口)
<html><body><h1>It works!</h1></body></html>
[root@docker-ce ~]# docker rm -f 89
89
[root@docker-ce ~]# docker run -itd --name kel -p 80:80 httpd(指定端口进行映射)
9d1c8d7030166b4679739222e55fd767e8515b57470bdf219d1015db2ffe760f
[root@docker-ce ~]# docker port kel(port用来查看映射的端口)
80/tcp -> 0.0.0.0:80
[root@docker-ce ~]# curl localhost:80
<html><body><h1>It works!</h1></body></html>
不使用端口映射怎么办?(跨主机就不行)
[root@docker-ce ~]# docker run -itd --name kel httpd(创建容器)
0a28b74a8e0daecd728b9c4c764312e5b4148c17e1496b96906fb3f93dfe2bef
[root@docker-ce ~]# docker ps(查看运行的容器)
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0a28b74a8e0d httpd "httpd-foreground" 5 seconds ago Up 3 seconds 80/tcp kel
[root@docker-ce ~]# docker inspect kel|grep 172(查看容器的ip地址)
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
[root@docker-ce ~]# curl 172.17.0.2:80(通过ip地址和端口来进行访问)
<html><body><h1>It works!</h1></body></html>
好看的皮囊玩不起,有趣的灵魂看不上。。。心好累,哈哈。。。
要之无用,弃之可惜。。。。
经常会听到有人说,没兴趣,没意思。。。不好玩,无聊,各种各样的相似的话语。。。
所有这一切归根结底,多追问对哪个感兴趣,又为什么没做,那么基本上都可以得到根本原因,是因为对结果的不确定,对结果不能负责,对失败无法忍受,不能达到自己想要的结果,害怕失去。。。本质原因是。。。因为怂。。。
有人说, 我喜欢linux,感兴趣想学,但是没老师教。。。没地方可以实验。。。没地方可以学习。。。有了条件之后,说。。。。好难啊,这么多的命令,记不住啊。。。等学会了后,又说学了这么多,又有啥用呢。。没意思,不好玩啊。。。但是。。。。你学这些,不是为了兴趣么?
很多东西都是矛盾的理论,但是你所想的东西,终究会是你的生活,所谓的坏事理论,你想的太多,那么你终将会遇到各种各样的烂事烂人。。。心态放开点,看看优点,或许有不一样的生活。。
脑中构建的世界,或许也是真实的世界,越是逃避的世界,越会变成现实,不如坦荡面对。。。
不停的进行思维训练,然后在自己的世界中竖起一道墙,此路不通,此路不通。。。。但是。。。
同样一本书,不同的人能看出不同的味道;同样一片风景,不同的人看出不同的魅;同样的锅,不同的人能扛出不同的姿势。。。。仁者见仁智者见智。。。。
珍惜当下,无须考虑太多,与其想着达到最完美的姿态,还不如全身心投入。。。。败可以获取智慧,胜可以为王(gou)。。。。只能求一战了。。。