使用none模式
将网络设置为none模式,容器将无法与外界通信,容器仍然有一个回环接口,不过没有外部流量的路由。这种模式可以启动没有任何网络设备的容器
使用 none 模式,Docker容器拥有自己的网络名称空间,但是并不会为Docker容器进行任何网络配置,构造任何网络环境,Docker容器内部只能使用回环网络接口(Linux中名为1o),即使用 IP 地址为127.0.0.1 的本机网络,也不会再有网卡、IP 地址、路由等其他网络资源。当然管理员自己可以为Docker 容器添加网卡、配置IP地址等。这种模式将容器放置在它自己的网络栈中,但是并不进行任何配置,实际上是关闭了容器的网络功能。
应用场合
none 网络模式还是有应用场合的。有些容器并不需要网络,如只需要写磁盘卷的批处理任务,还有自定义网络的情形有时也可以选择这种模式
配置实例
在创建容器时使用--network none来指定该容器使用none网络,完全关闭容器的网络栈,此时只会创建回环设备在容器中
1.创建容器
2.通过在容器内执行常见的网络命令查看容器的网络栈
这表明只有一个1o接口,没有创建eth0
没有输出,表明没有路由表
3.停止容器,因为在创建容器时,使用了--rm选项,容器会在停止时自动删除
使用container网络模式
这种模式会重用另一个容器的网络空间名称。通常来说,当要自定义网络栈时,该模式很有用。实际上,该模式也是Kubernetes所使用的网络模式。
container是Docker中一种较为特别的网络模式。采用此模式的Docker容器会共享其他容器的网络环境,因此,至少这两个容器之间不存在网络隔离,而这两个容器又与主机以及除此之外其他的容器存在网络隔离。
该模式指定新创建的容器和已经存在的一个容器共享同一个网络名称空间。新创建的容器不会创建自己的网卡、配置自己的P地址,而是和一个指定的容器共享IP地址,端口范围等。同样,两个容器除了在网络方面,其他方面如文件系统、进程列表等还是相互隔离的。两个容器的进程可以通过回环网卡设备(lo)进行通信。
这种模式主要用于容器与容器之间频繁交流的情况
配置实例
1.启动一个nginx容器,将其绑定到localhost接口
2.然后运行另一个容器,执行nginx-cli命令,通过localhost连接到nginx服务器
没成功,可能是因为镜像加速器挂了?
3.使用nginx容器的网络栈来访问localhost
也是没有成功
相关网络配置
采用container网络模式时,容器将共享另一个容器的网络栈。需要以--network container:的格式提供另一个容器的名称。选项--add-host、--hostname、--dns、--dns-search、--dns-opt 和--mac-address在container网络模式中是无效的,选项--publish、--publish-all 和-expose在container网络模式下同样是无效的。
用户自定义桥接网络
管理员可以使用Docker网络驱动或外部网络驱动插件创建一个自定义的网络,然后将多个容器连接到同一个自定义网络中。连接到用户自定义网络的容器之间只需要使用对方的IP地址或名称就
能相互通信。
Docker本身内置bridge网络驱动,可以用来创建自定义桥接网络。生产环境中应使用用户自定义桥接网络,不推荐使用默认桥接网络。
用户自定义桥接网络和默认桥接网络的区别
1.用户自定义桥接网络提供了容器化应用之间更好的隔离和互操作性
连接到同一个用户自定义桥接网络的容器会自动互相暴露所有端口,并且不会将端口暴露到外部。这让容器化应用之间的相互通信更容易,而不会意外地对外部开放访问。假设一个应用包含 Web 前端和数据库后端。外部网络需要访问 Web 前端(可能是80端口),但是只有后端本身需要访问数据库主机和端口。使用用户自定义桥接网络,只需要开放前端的Web端口,数据库应用不需要开启任何端口,因为Web前端可以通过用户自定义桥接网络直接访问它。如果在默认桥接网络上运行同一个应用栈,需要同时打开Web前端和数据库后端的端口,每个容器都需要使用-p或-publish选项定义端口。这意味着Docker主机需要通过其他方式来限制对数据库后端端口的访问
2.用户自定义桥接网络提供了容器间自动DNS解析
默认桥接网络上的容器只能通过IP地址相互访问,或者使用--link建立容器连接,这是可能被弃用的传统方式。在用户自定义桥接网络中,容器之间可以通过容器名称或别名互相访问
3.容器可以在运行时与用户自定义桥接网络连接或断开
容器要断开与默认桥接网络的连接,需要停止容器并使用不同的网络选项重新创建该容器
4.可以为每个用户自定义桥接网络创建一个可配置的网桥
默认桥接网络中的容器都使用相同的配置,例如最大传输单元(MTU)和iptables规则,此外,对默认桥接网络的配置是通过配置文件实现的,并不是由docker本身进行的,需要重启Docker守护进程
用户自定义桥接网络是通过
docker network create
创建和配置的
5.默认桥接网络中的容器可以共享环境变量
起初在两个容器之间共享环境变量的唯一办法是使用--link选项建立容器连接,在用户自定义桥接网络中是不可以使用的,还有下面的方式:
多个容器使用Docker卷挂载包含共享信息的一个文件或目录
通过docker-compose命令同时启动多个容器,由Compose文件定义共享变量
使用Swarm集群服务代替单个容器,共享机密数据和配置数据
注意连接到同一个用户自定义桥接网络的容器可以有效地将所有端口暴露给对方,要让不同网络上的容器或非docker主机访问到容器的某端口,该端口必须使用-p(--publish)对外进行发布
管理用户自定义桥接网络
创建用户自定义网络
将容器连接到用户自定义桥接网络
--network:指定要连接的用户自定义桥接网络
将ubuntu连接到了mynet,同时还将容器的80号端口发布到Docker主机的8080端口,这样外部客户端就可以访问了
连接到mynet的所有容器都可以访问myubuntu容器的所有端口,反之亦然
使用docker network connect命令将正在运行的容器连接到已经存在的用户自定义桥接网络
断开容器到用户自定义桥接网络的连接
删除用户自定义桥接网络
配置实例
下面在同一个docker主机上启动两个不同的centos容器,连接到一个已经创建的用户自定义桥接网络(cento-net),不连接到默认桥接网络
然后启动第三个centos容器并连接到默认桥接网络(默认名为bridge),再启动第四个容器并同时连接到这两个网络
1.创建用户自定义桥接网络
docker network create --driver bridge centos-net #也可以使用这个,选项--driver bridge可加可不加,因为它是docker默认的网络驱动
2.列出docker主机上的网络
#注意,用户自定义桥接网络也是桥接类型
查看网络的详细信息:
可以看出目前还没有任何容器连接到它
3.分别创建4个centos容器
在docker run中仅能连接到一个网络,因此对于第四个容器,需要使用docker network cinnect连接到默认桥接网络
查看正在运行的容器:
4.分别查看bridge网络和centos-net网络的详细信息
docker network inspect bridge/cent-os
bridge:
说明容器centos3和centos4连接到了bridge网络
centos-net:
说明centos1、centos2、centos4连接到了centos-net网络
5.在自定义网络中,容器不仅能通过IP地址进行通信,而且能将容器名解析到IP地址,这种功能称为自动服务发现
连接到centos1,并通过容器名连接centos2,centos4进行测试,验证可以解析IP地址
尝试连接centos3,发现不能连接centos3,用IP地址也不行
离开centos1容器而不停止它,是组合按下ctrl+P+Q
6,下面使用centos4进行测试
注意访问centos3时要通过它的IP地址
7.最后ping一个外网
分别对centos4(同时连接到默认桥接网络和用户自定义桥接网络)centos3(只连接到默认桥接网络)centos1(只连接到用户自定义桥接网络)
8.停止并删除以上的容器和centos-net网络,完成实验环境的清理
docker stop之后docker ps之后没有了,docker ps -a还有,表示只是停止了,不是删除
docker rm之后docker ps -a没有了,说明已经删除了
ls列出docker中的网络,然后rm删除,再ls可以发现确实删除了
容器与外部的网络通信
默认情况下,容器可以主动访问外部网络,但是从外部网络无法访问容器
容器访问外部网络
启动容器到外部的访问
1.配置Linux内核允许IP转发
值为1说明已经允许,值为0说明未启动该功能,可以这样启动:
sysctl -w net.ipv4.conf.all.forwarding=1
也可以在启动docker服务时,通过提供设置选项--ip-forward=true来启动IP转发;还可以编辑/etc/default/docker配置文件,在DOCKER_OPTS选项中设置
2.确认iptables默认的FORWARD策略设置为“ACCEPT”
如果出现Chain FORWARD (policy ACCEPT)说明已经配置好,如没有出现,可按照上图的方法配置
通过NAT实现容器到外部的访问
使用默认网桥的容器通过NAT方式实现到外部的访问,通过iptables的源地址伪装操作实现
查看Docker主机上的nat表上的POSTROUTING链的规则进行验证
POSTROUTING链包含的是路由后的规则,负责包在离开防火墙主机之前改写其源地址
docker0:默认网桥
将所有源地址在172.17.0.0网段,目标地址是外网(! -o docker0)的流量交由MASQUERADE(动态伪装)处理,动态伪装将包的源地址替换为Docker主机的IP地址发出去,实现网络地址转换
自定义一个桥接网络,可以发现,docker也为通过自定义网桥转发到外部的流量提供了NAT规则
从外部网络访问容器
不同容器网络之间的流量和从Dooker主机进入容器的流量都要经过防火墙,这是Docker的个基本安全措施,旨在保护容器免受来自外部网络和其他容器的威胁。默认情况下,创建的容器不会将其任何端口对外发布,从容器外部是无法访问容器内部的网络应用和服务的。要从外部访问容器内的应用必须要有明确的授权,是通过内部端口映射来实现的。要让容器能够被外部网络(Docker 主机外部)或者那些未连接到该容器的网络上的Docker主机访问,就要在通过docker run命令创建容器时使用选项-p(--publish)或-P(-publish -all)进行设置,将会创建一个iptables防火墙规则,将容器的一个端口映射到docker主机上的一个端口,允许外部网络通过该端口访问容器。这种端口映射也是一种NAT 实现
使用选项-p发布特定端口
通过docker run命令创建容器时使用选项-p将一个或多个特定的容器端口绑定到Docker主机上。
可以多次使用选项-p进行任意数量的端口映射。该选项有多种形式的参数,可实现不同的端口映射
1.映射主机上所有网络接口的地址:
采用以下形式的参数,会将容器端口映射到主机上所有网络接口的所有IP地址的端口(参数中的主机端口):
-p 主机端口:容器端口
例如,-p 8080:80会将容器的80端口映射到Docker主机上所有 IP 地址的8080端口
2.映射指定地址的指定端口:
采用以下形式的参数,会将端口映射到特定的主机IP地址:
-p 主机IP地址:主机端口:容器端口
例-p 192.168.1.100:80:5000 会将容器的 5000 端口映射到主机上IP地址为192.168.1.100的80端口
3.映射指定地址的任一端口
采用以下形式的参数,会将容器的端口映射到主机特定IP地址的任意端口:
-p 主机IP地址::容器端口
例如,-p 127.0.0.1::5000将容器的端口映射到主机上地址为127.0.0.1的任意端口(由docker守护进程自动分配)
4.自动分配主机端口
选项-p的参数中可以忽略主机IP地址或主机端口,但是必须要指定需要发布的容器端口,可以采用以下格式将容器的端口映射到主机任意IP地址的任意端口
-p 容器端口
这种方式没有显式指定主机端口,docker会自动选择一个主机端口,对于一台docker主机上要发布许多容器的情形,可以有效避免主机上的端口冲突
5.发布UDP端口
默认发布的都是TCP窗口,在-p的参数的末端部分加上“/udp”
例如,-p 8080:80/udp将容器的UDP80端口映射到docker主机的UDP 8080端口
-p 8080:80/tcp -p 8080:80/udp将容器的TCP 80端口和UDP 80端口映射到docker主机的TCP 8080端口和UDP 8080端口:同时发布TCP和UDP端口
验证端口映射的NAT过程
创建一个通过端口映射发布http服务的容器:
httpd容器的80端口被映射到主机上的8080端口,这样可以通过<主机IP>:<8080> 访问容器的web服务
对外发布端口其实也是在docker主机的iptables的nat表中添加相应的规则,将访问外部IP地址的包进行目标地址转换(DNAT),将目标地址修改为容器的IP地址
查看相应的iptables规则:
对于每一个映射的端口,docker主机都会启动一个docker-proxy进程来处理访问容器的流量
查看端口映射配置
docker port CONTAINER [ PRIVATE_PORT [/PROTO] ] #可以列出容器当前所有的端口映射及指定的映射
80/tcp是容器发布的端口
0.0.0.0:8080是映射到主机上的IP地址和端口
查看容器的详细信息:
停止并删除容器:
使用选项-p发布所有暴露的接口
httpd镜像通过EXPOSE指令暴露了80端口,可以使用-p发布它,上例中docker自动映像的端口是32768
再通过inspect命令查看容器的详细信息:
Config节暴露了端口信息
NetworkSettings节给出端口映射信息:
限制外部网络访问
默认情况下,所有外部源IP都被允许连接到Docker守护进程,若仅允许特定的IP或网络访问容器,可以在DOCKER过滤器链的顶部插入否定规则。例如,以下规则只允许外部IP地址为192.168.0.1的主机访问容器(ext_if表示传入包的网络接口,下同):
iptables -I DOCKER-USBR -i ext_if ! -s 192.168.0.1 -j DROP
也可以改为允许来自子网的连接。以下规则仅允许从子网192.168.0.0/24 进行访问:
iptables -I DOCKER-USER -i ext_if ! -s 192.168.0.0/24 -j DROP
还可以通过--src-range 选项指定 IP 地址范围(注意,在使用--src-range 选项或--dst-range 选项时需要添加-m 选项):
iptables -I DOCKER-USER -m iprange -i ext_if ! --src-range 192.168.0.1-192.168.0.3 -j DROP
在 Linux上,Docker通过iptables规则提供网络隔离,Docker的所有iptables规则都被添加到DOCKER链中,不要手动修改此链表。如果需要添加在Docker规则之前加载的规则,则应将它们添加到DOCKER-USER链中,这些规则会在Docker自动创建任何规则之前加载。