Docker 学习 | 第六篇:容器网络配置
前言
Docker
容器中可以运行网络应用,可以让外部可以访问容器。Docker
提供了很多对网络的配置命令。本篇文章主要介绍Docker
中的网络默认配置/网络端口映射/容器互联/DNS配置/网络模型等等网络相关的知识。
Docker默认的网络配置
Docker
启动的时候会在主机上自动创建一个docker0
网桥,实际上是一个Linux
网桥,所有容器的启动如果在docker run
的时候没有指定网络模式的情况下都会挂载到docker0
网桥上。这样容器就可以和主机甚至是其他容器之间通讯了。
我们可以通过以下命令查看Docker0
网桥:
[root@VM_0_14_centos ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242f9dd21f4 no veth211edda
如果想查看Docker0
的IP
地址可以通过ifconfig
命令
[root@VM_0_14_centos ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:f9:dd:21:f4 txqueuelen 0 (Ethernet)
RX packets 838 bytes 114894 (112.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1225 bytes 568128 (554.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
如果发现找不到
brctl
命令,可以同过yum install -y brctl
安装
外部访问容器
在使用docker run
的时候可以使用-P
或者-p
来进行容器和主机之间的端口映射。
使用-P
则不需要指定任何映射关系,默认情况下,Docker
会随机映射一个49000~49900
的端口到内部容器开放的网络端口。
使用-p
则需要指定对应的主机的端口应该到容器中的端口。使用格式如下:
-p hostPort:containerPort
不管使用哪一种方式进行端口映射,其他原理都是在本地的iptable
的nat
表中添加相应的规则,将访问外部IP
地址的网包进行目标地址的转换,将目标地址修改为容器的IP
地址。可以通过以下命令来查看iptable
的nat
表:
[root@VM_0_14_centos ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
607df94722dd redis "docker-entrypoint.s…" 9 days ago Up 3 days 0.0.0.0:62255->6379/tcp redis
[root@VM_0_14_centos ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 239K packets, 7950K bytes)
pkts bytes target prot opt in out source destination
239K 7979K DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 239K packets, 7950K bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 267K packets, 18M bytes)
pkts bytes target prot opt in out source destination
0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 267K packets, 18M bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:6379
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
481 28828 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:62255 to:172.17.0.2:6379
[root@VM_0_14_centos ~]#
从上面可以看到,Docker
中跑了一个容器名为redis
,并且把本机的62255
端口映射到了容器的6379
端口上。
通过查看nat
表,可以看到,有两条链。POSTRONTING
的第二个规则负责包到达网络接口时,改写其目的地址,将所有的流量都扔到DOCKER
链,而DOCKER
链的第二个规则将所有不是从docker0
进入的网包,将目标端口为62255
的,都修改目标地址为172.17.0.2
,端口为6379
。
由于本篇不是介绍
iptable
的,并且可能笔者对于iptable
理解的不够深入,上述说法仅仅是表达的笔者的理解,可能有些说法存在错误。~
容器访问外部网络
默认情况下,容器可以访问到外部网络的连接,因为容器的默认网络接口为docker0
网桥上的接口,也即是主机上的本地接口。其原理是通过Linux
系统的转发功能实现的,在Linux
中检查转发是否打开:
[root@VM_0_14_centos ~]# sysctl net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
0
表示转发未打开,1
表示转发已经打开。可以在docker run
时使用--ip-forward=true
来指定,Docker
会打开主机的转发功能。
同时可以通过上述的nat
表中找到对应的规则,在POSTRONTING
的第一个规则就是把所有原地址在172.17.0.0/16
网段但不是属于Docker0
的网包(即容器中的网包),动态伪装为0.0.0.0/0
网段,即主机网卡。
配置容器DNS和主机名
容器中的主机名和DNS
配置信息都是通过三个系统配置文件来维护,/etc/resolv.conf
、/etc/hostname
、/etc/hosts
,其中:
/etc/resolv/conf
在创建容器的时候,会默认与本地主机/etc/resolv.conf
保持一致/etc/hosts
中则记载了容器自身的一些地址和名称。/etc/hostname
中记录的容器的主机名
可以直接在容器内部修改这三个文件使之直接生效,不过这些修改只会在容器中保留,容器重启后则又会恢复原样,同样的,docker commit
也无法保存这三个文件的修改。
配置主机名
配置主机名可以通过docker run
的时候使用-h hostname
或者--hostname hostname
这样的形式来执行。
配置DNS
可以统一配置所有容器的DNS
,通过修改主机/etc/docker/daemon.json
增加以下内容:
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
同时,也可以通过在docker run
的时候使用--dns=address
参数来指定.
容器互联
link 方式互联
容器之间相互通讯可以通过docker run
中的--link=container_name:alias
参数来达到效果。
此种方式可以很方便让容器使用容器名进行通讯,而不需要依赖ip
地址,不过link
方式仅仅解决了单机容器间的互联,多机的情况下,需要通过别的方式进行连接。
自定义网络方式
除了使用link
方式,还可以使用自定义网桥的方式进行互联。
下面演示了通过自定义网络方式来使容器互联
[root@VM_0_14_centos ~]# docker network create -d bridge my-net
d90fc3d8515b9402f2aca86767aa81ebb115cb4fcea4c90ed82446326cce7d35
[root@VM_0_14_centos ~]# docker run -it -d --name centos1 --network my-net centos
a43d83dbbde5827aeb3a66bab0e954df3b95a157dc0aea218cb23565af9655ce
[root@VM_0_14_centos ~]# docker run -it -d --name centos2 --network my-net centos
4f59c5ed14e075a1ef05468d9bfd75fe02fd210b3b580c8b0994bb3c0310a80e
[root@VM_0_14_centos ~]# docker exec -it centos1 /bin/bash
[root@a43d83dbbde5 /]# ping centos2
PING centos2 (172.18.0.3) 56(84) bytes of data.
64 bytes from centos2.my-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.112 ms
64 bytes from centos2.my-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.061 ms
64 bytes from centos2.my-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.058 ms
64 bytes from centos2.my-net (172.18.0.3): icmp_seq=4 ttl=64 time=0.056 ms
^C
--- centos2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.056/0.071/0.112/0.025 ms
[root@a43d83dbbde5 /]#
上面演示了创建一个bridge类型网络my-net
然后创建了两个容器centos1、centos2都连接到这个容器,然后进入centos1,使用ping centos2成功。
Docker Compose
如果有多个容器之间需要相互连接,推荐使用Docker Compose
。 Docker Compose
不是本篇文章的内容,后面文章会对他进行专门讲解。
Docker的四种网络模式
在docker run
的时候可以通过--net=xxx
或者--network=xxx
来指定使用哪一种网络模式启动容器。总共有以下四种模式:
bridge模式网络
这是Docker
默认的网络模式,在该模式中,Docker
守护进程创建了一个虚拟以太网桥docker0
,附加骑上的任何网卡之间能自动转发数据包。默认情况下,守护进程会创建一对对等接口,将其中一个接口设置为容器的eth0
接口,另一个接口放置在宿主机的命名空间,从而将宿主机上的所有容器都连接到这个内部网络。同时,守护进程还会从网桥的私有地址空间中分配一个IP地址和子网给该容器。
host模式网络
该模式中将禁用Docker
容器的网络隔离,容器共享宿主机的网络命名空间,直接暴露在公网中,容器会继承宿主机的IP
地址。使用host
模式会将容器直接暴露在公网,会存在安全隐患。
container模式网络
该模式中,容器会使用另一个容器的网络命名空间。使用方式为:--net=container:containername
none模式网络
该模式将容器放置在自己的网络栈中,并不进行任何配置,该模式实际上是关闭了容器的网络功能。
Docker网络操作
Docker
默认会创建一个docker0
网桥,在启动docker
服务的时候,可以对docker0
进行配置:
--bip=CIDR
IP
地址加掩码,如:192.168.1.5/24
--mtu=BYTES
覆盖默认的mtu
(接口允许接收最大传输单元)配置
除此之外,Docker
还提供了很多对于网络的操作命令:
docker network create
创建一个网络,用法如下:
docker network create -d bridge --subnet 172.25.0.0/16 mynet
可以通过
-d
参数指定网络模式,同时--subnet
指定子网的ip
以及掩码。最后是网络名称docker network connect
连接一个容器到网络中,用法如下:
docker network connect mynet containername
docker network ls
显示所有网络:
[root@VM_0_14_centos ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 1743c0f6d043 bridge bridge local 99fefa50be75 host host local d90fc3d8515b my-net bridge local c42853bb3a87 none null local
可以看到默认情况下
docker
会存在3个网络分别使用对应的网络模型名称作为网络名称。在启动容器的时候可以使用--net
或--network
来指定使用哪个网络,默认情况下使用bridge
网络,它是一个bridge
类型的网络。docker network rm
移除网络
docker networdk disconnect
容器和网络断开。
docker network inspect
查看网络详情。
总结
本篇文章介绍了一些对于Docker中网络的理解。包括Docker中默认的网络配置,以及如何对Docker中的网络进行管理等。
参考: