第六章 Docker网络
一.Docker默认网络
1.Docker网络模式概述
Docker使用Linux桥接的方式,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。
2.Docker网络模式工作方式
Docker自身的4种网络工作方式,和一些自定义网络模式.
Docker容器与容器之间网络相互隔离。
安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host.
你可以使用以下docker network ls命令列出这些网络:
[root@m01 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
daa11493364f bridge bridge local
fc5d4a69c90d host host local
16b8d6c8be22 none null local
Docker内置这三个网络,运行容器时,你可以使用该--network标志来指定容器应连接到哪些网络。
该bridge网络代表docker0所有Docker安装中存在的网络。除非你使用该docker run --network=<NETWORK>选项指定,否则Docker守护程序默认将容器连接到此网络。
我们在使用docker run创建Docker容器时,可以用 --net 选项指定容器的网络模式,Docker可以有以下4种网络模式:
host模式:使用 --net=host 指定。
none模式:使用 --net=none 指定。
bridge模式:使用 --net=bridge 指定,默认设置。
container模式:使用 --net=container:NAME_or_ID 指定。
Docker网络模型 | 配置 | 说明 |
---|---|---|
host模式 | –-network=host | 容器和宿主机共享Network namespace。 |
containe模式 | --network=container:ID | 容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。 |
none模式 | --network=none | 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。 |
bridge模式 | --network=bridge | 当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。(默认为该模式 |
一、Docker默认网络详述
1.Bridge网络模式
相当于Vmware中的Nat模式,容器使用独立network Namespace,并连接到docker0虚拟网卡(默认模式)。通过docker0网桥以及Iptables nat表配置与宿主机通信;bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。
#实现原理:
通过一个虚拟网桥,建立一个统一的网络名称空间,依赖于docker0网桥
#使用及使用场景
一般使用在多个容器之间互联互通
#使用特点
多个容器之间互联互通
为容器提供一个统一的网络环境
2.Host 网络方式
相当于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独立IP地址。众所周知,Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
#解释:
host模式主要用于跟宿主主机相连,此时docker容器不会虚拟出自己的网卡。
#优点:
- 1、共享宿主主机网络,无需再做网络转发
- 2、性能比较好
#缺点:
- 1、隔离性不强
- 2、容易跟宿主主机服务之间起冲突
例如,我们在10.0.0.61/24的机器上用host模式启动一个含有nginx应用的Docker容器,监听tcp80端口。
# 运行容器;
[root@m01 ~]# docker run --name=nginx_host --net=host -p 80:80 -d nginx
WARNING: Published ports are discarded when using host network mode
c47d062687104ac58325a255185c216df9390ab0ad32dc18af61659ff0d88e48
# 查看容器;
[root@m01 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c47d06268710 nginx "/docker-entrypoint.…" 11 seconds ago Up 10 seconds nginx_host
当我们在容器中执行任何类似ifconfig命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用10.0.0.61/24即可,不用任何NAT转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
[root@m01 ~]# netstat -nplt | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 63118/nginx: master
tcp6 0 0 :::80 :::* LISTEN 63118/nginx: master
3. Container网络方式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
#解释:一个容器将网络共享给另外一个容器使用(两个容器之间网络其实是一个网络)
[root@m01 ~]# docker run -itd --name test01 busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
d60bca25ef07: Pull complete
Digest: sha256:caf2e0529ee842cfa1950a1d8b15b120e884288d507774dc6751bc3861aa4b35
Status: Downloaded newer image for busybox:latest
a0ccfa2177d0b4118ef1b42a58b71326f0a13a6f501e9a7a9c80579cc42c7499
[root@m01 ~]# docker run -itd --name test02 --network "container:test01" busybox
b20a68e25b4d3b0946f0d037ed5df8308ee0c6ed911d402db61b4eb680c01ae9
[root@m01 ~]# docker exec -it test02 sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:06
inet addr:172.17.0.6 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 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:656 (656.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # exit
[root@m01 ~]# docker exec -it test01 sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:06
inet addr:172.17.0.6 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 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:656 (656.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #
4.None 网络方式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
#解释:
none模式只为容器提供一个lo回环网络,外界是无法与容器进行互联互通。
#优点:
安全
#缺点:
无法与外界进行网络互通
[root@m01 ~]# docker run -itd --name test03 --network=none busybox
aa1334718dd0d0ecda5ae5b08afde6dab34883d8933ce5ef7504f9591f49caa5
[root@m01 ~]# docker exec -it test03 sh
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #
二.Docker自定义网络
1除了以上得四种网络我们也可以创建自定义网络
2.自定义网络介绍
建议使用自定义的网桥来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。Docker提供了创建这些网络的默认网络驱动程序,你可以创建一个新的Bridge网络,Overlay或Macvlan网络。你还可以创建一个网络插件或远程网络进行完整的自定义和控制。
你可以根据需要创建任意数量的网络,并且可以在任何给定时间将容器连接到这些网络中的零个或多个网络。此外,您可以连接并断开网络中的运行容器,而无需重新启动容器。当容器连接到多个网络时,其外部连接通过第一个非内部网络以词法顺序提供。
**#也就是一句话 自定义网络模式 就是启动容器时 知道自己创建得网络模式 容器与容器之间就可以通信了**
3.Docker Network
#1.格式:
docker network [cmd]
#2.ls:查看网桥列表
[root@docker100 ~/conf.d]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a985cfca04ae bridge bridge local
c3d4dd997242 jinhui bridge local
a425f4733836 host host local
5902bdedd1b1 lnmd bridge local
ce7e9b514c2a none null local
##自定义网络名称
docker network create -d <mode>--subnet<CIDR> --gateway <网关> <自定义网络名称>
##引用自定义网络
docker run --network <自定义网络名称> <镜像名称>
##删除自定义网络
##创建实例
docker network create -d bridge --subnet 192.168.100.0/24 --gateway 192.168.100.1 mynet
##查看信息
#启动容器时,指定--name即可通过主机名ping通
三、案例:
1.要求
起一个django服务,使用nginx代理,只向外暴露80端口,提供django服务。
2..配置
#1.创建bridge网络
[root@docker100 ~]# docker network create lnmd
5b8eaeba89602659eb4c3637db25798b03376777f2f89cd230167d9346e4119d
#2.运行Django容器
[root@docker100 ~]# docker run -d --network=lnmd alvinos/django:v3
49b11e72cbf13f9184153d33f7bf76a6a74a9b3c45348d4679a7863acc48533c
[root@docker100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
49b11e72cbf1 alvinos/django:v3 "python3 manage.py r…" 17 seconds ago Up 15 seconds 80/tcp, 443/tcp frosty_maxwell
#3.创建nginx代理配置文件
[root@docker100 ~]# mkdir conf.d/
[root@docker100 ~]# pwd
/root
[root@docker100 ~]# touch ./conf.d/django.conf
#4.运行nginx代理
[root@docker100 ~]# docker run -d -p 38080:80 --network=lnmd -v /root/conf.d/:/etc/nginx/conf.d nginx
8192fa09c6a2e4d3ba12327f16a87052753e82aaa3e6e7ab727daaf7ad0bcee4
[root@docker100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8192fa09c6a2 nginx "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 0.0.0.0:38080->80/tcp unruffled_bohr
49b11e72cbf1 alvinos/django:v3 "python3 manage.py r…" 27 minutes ago Up 27 minutes 80/tcp, 443/tcp frosty_maxwell
#5.写入nginx代理文件
[root@docker100 ~]# vim ./conf.d/django.conf
server {
listen 80;
server_name _;
location / {
proxy_pass http://49b11e72cbf1;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
}
}
#6.测试nginx
[root@docker100 ~]# docker exec -i -t unruffled_bohr bash
root@8192fa09c6a2:/# cd /etc/nginx/conf.d/
root@8192fa09c6a2:/etc/nginx/conf.d# ls
django.conf
root@8192fa09c6a2:/etc/nginx/conf.d# cat django.conf
server {
listen 80;
server_name _;
location / {
proxy_pass http://49b11e72cbf1;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
}
}
root@8192fa09c6a2:/etc/nginx/conf.d# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@8192fa09c6a2:/etc/nginx/conf.d# nginx -s reload
2021/01/13 09:33:36 [notice] 42#42: signal process started
root@8192fa09c6a2:/etc/nginx/conf.d# exit
exit
#7.访问测试
10.0.0.61:38080 #正常
10.0.0.61:38080/index #正常
#8.80端口访问
[root@docker100 ~]# docker run -d -p 80:80 --network=lnmd -v /root/conf.d/:/etc/nginx/conf.d nginx
c4db530a98337fe4c70f82e879fb1f921b506046888d6059efec316cea023368
#9.再次访问
10.0.0.61 #正常
10.0.0.61/index #正常