1. 启动配置参数
1.1 网络启动过程
Docker服务启动时会首先在主机上自动创建一个 dockerO虚拟网桥,实际上是一个Linux 网桥。
同时, Docker 随机分配一个本地未占用的私有网段中的一个地址给 docker0接口。
当创建一个 Docker 容器的时候,同时会创建了一对 veth pa订互联接口。当向任一个接 口发送包时,另外一个接口自动收到相同的包。互联接口的一端位于容器内,即 eth0;另一 端在本地并被挂载到 docker0网桥,名称以 veth 开头。 通过这种方式,主机可以与容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有 容器之间一个虚拟共享网络。
1.2 参数
-b BRIDGE or --bridge=BRIDGE: 指定容器挂载的网桥;
--bip=CIDR: 定制docker0 的掩码;
-H SOCKET... or --host=SOCKET...; Docker 服务端接收命令的通道;
--icc=true I false : 是否支持容器之间进行通信;
--ip-forward=true I false: 启用net.ipv4.ip _forward, 即打开转发功能;
--iptables=true I false : 禁止Docker 添加 iptables 规则;
--mtu=BYTES: 容器网络中的 MTU
命令选项既可以在启动服务时指定, 也可以 Docker 容器启动(使用 docker [ container] run 命令)时候指定。在 Docker 服务启动的时候指定则会成为默认值, 后续执行该命 令时可以覆盖设置的默认值
--dns=IP_ADDRESS: 使用指定的 DNS 服务器;
--dns-opt= " ":指定 DNS 选项;
--dns-search=DOMAIN: 指定DNS搜索域
在 docker [con七ainer] run 命令执行时使用, 因为它针对容器的配置:
-h HOSTNAME or --hostname=HOSTNAME:配置容器主机名
-ip=" ": 指定容器内接口的ip地址;
--link=CPNTAINER_NAME:ALIAS: 添加到另外一个容器的连接;
--net=bridge | none | con七ainer:NAME_or_ID | host | user_defined_network: 配置容器的桥接模式;
--network-alias: 容器在网络中的别名;
-p SPEC or --publish=SPEC: 映射容器端口到宿主主机
-P or --publish-all=true | false: 映射容器所有端口到宿主主机。
net的支持模式
--net=bridge: 默认配置.为容器创建独立的网络命名空间,分配网卡、IP 地址等网络配置, 并通过veth接口对将容器挂载到一个虚拟网桥(默认为 docker0) 上;
--net=none: 为容器创建独立的网络命名空间,但不进行网络配置,即容器内没有创建网卡,IP地址等;
--net=container:NAME—or_ID: 新创建的容器共享指定的已存在容器的网络命名空间, 两个容器内的网络配置共享, 但其他资源(如进程空间、 文件系统等)还是相互隔离的;
--net=host:不为容器创建独立的网络命名空间, 容器内看到的网络配置(网卡信息路由表 Iptables 规则等)均与主机上的保持一致 注意其他资源还是与主机隔离的;
--net=user_defined_network: 用户自行用network相关命令创建一个网络,同一个网络内的容器彼此可见,可以采用更多类型的网络插件
2. 配置容器DNS和主机名
Docker 服务启动后会默认启用一个内嵌的DNS服务,来自动解析同一个网络中的容器主机名和地址,如果无法解析,则通过容器内的DNS相关配置进行解析,用户可以通过命令选项自定义容器的主机名和DNS配置
2.1 配置文件
容器中主机名和DNS配置信息通过三个系统配置文件来管理
/etc/resolv.conf
/etc/hostname
/etc/hosts
启动容器,在配置中使用monut命令可以看到这三个文件挂载信息;
[root@kubernetes ~]# docker run -it --rm ubuntu
root@2334d56d6268:/# mount
启动容器时,会从宿主机上复制/etc/resolv.conf
root@2334d56d6268:/# cat /etc/resolv.conf
/etc/hosts文件中默认只记录了容器自身的地址和名称
root@2334d56d6268:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 2334d56d6268
/etc/hostname文件则记录了容器的主机名
root@2334d56d6268:/# cat /etc/hostname
2334d56d6268
2.2 容器内修改配置
容器运行时,可以在运行中的容器里直接编辑/etc/hosts,/etc/hostname和/etc/resolve.conf文件,这些修改都是临时的,只是在运行的容器中保留,容器终止或重启后并不会被保存下来,也不会被docker commit 提交。
2.3 通过参数指定
想自定义容器的配置,可以在创建或启动容器时利用参数指定,注意不与-net=host一起使用,会破坏宿主机上的配置信息:
指定主机名 -h HOSTNAME 或者 --hostname=HOSTNAME: 设定容器的主机名容器主机名会被写到容器内的/etc/hostname和/etc/hosts 但这个主机名只有容器内中能看到,在容器外部则看不到,既不会在docker ps 中显示,也不会在其他容器的/etc/hosts中看到;
--link=CONTAINER_NAME:ALIAS:记录其他容器主机名.在创建容器的时候,添加一个所连接容器的主机名到容器内/etc/hosts 文件中 这样,新建容器可以直接使用主机名与所连接容器通信;
--dns=IP_ADDRESS:指定DNS服务器。添加DNS服务器到容器的/etc/resolv.conf 中,容器会用指定的服务器来解析所有不在/etc/hosts中的主机名;
--dns-option list:指定 DNS 相关的选项;
--dns-search=DOMAIN :指定DNS搜索域。设定容器的搜索域,当设定搜索域为.example.com时,在搜索一个名为host的主机时,DNS不仅搜索host,还会搜索host.example .com
3. 容器访问控制
3.1 容器访问外部网络
容器默认情况下可以访问到宿主 机本地网络 如果容器要想通过宿主机访问到外部网络,则需要宿主机进行辅助转发。
检查转发是否打开:
[root@kubernetes ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
若为0,说明没有开启转发,则需要手动打开
sysctl -w net.ipv4.ip_forward=1
Docker 服务启动时会默认开启--ip-forward=true,自动配置宿主机系统的转发规则。
3.2 容器之间访问
网络拓扑是否已经连通。默认情况下,所有容器都会连接到docker0网桥上,这意味着默认情况下拓扑是互通的;
本地系统的防火墙软件 iptables 是否允许访问通过 这取决于防火墙的默认规则许(大部分情况)还是禁止
(1)访问所有端口
启动docker服务时候,默认会添加一条"允许"转发策略到iptables的FORWARD 链上,通过配置--icc=true|false(默认为true) 参数可以控制默认的策略
docker 配置文件中配置DOCKER_OPTS= --ice=false来默认禁止容器之间的相互访问。
启动docker时手动指定--iptables=false参数,则不会修改宿主机系统上的iptables规则。
(2)访问指定端口
在通过-ice=false禁止容器间相互访问后,仍可以通过--link=CONTAINER_NAME:ALIAS选项来允许指定容器的开放端口。
启动docker服务时,
启动docker时,可以同时使用ice=false --iptables=true参数来配置容器间禁止访问,并允许docker自动修改系统中的iptables规则。测试系统中的iptables规则可能是类似如下规则,禁止转发流量
iptables -nL
驱动容器(docker [container] run )时使用 --link=CONTAINER_NAME:ALIAS选项。Docker 会在iptable中为两个互联容器分别添加一条ACCEPT规则,允许相互访问开放端口(取决于Dockerfile中的EXPOSE)
--link=CONTAINER_NAME:ALIAS 中的 CONTAINER_NAME 目前必须是 Docker 自动分配的容器名,或使用--name 参数指定的名字. 不能为容器-h 参数配置的主机名
4. 映射容器端口到宿主主机的实现
4.1 容器访问外部实现
容器内部的网络地址为 172.17.0.2 ,本地网络地址为 10.0 2.2 。容器要能访问外部网络,源地址不能为 172.17.0.2 ,需要进行源地址映射( Source NAT, SNAT ),修改为本地系统 IP 地址 10.0.2.2
映射是通过 iptables 的源地址伪装操作实现的。查看主机 nat 表上 POSTROUTING 链的 规则 。该链负责网包要离开主机前,改写其源地址:
iptables -t nat -nvL POSTROUTING
规则将所有源地址在 172 .1 .0.0/16 网段,且不是从 dock rO 接口发出的流量 即从容器中 来的流量),动态伪装为从系统网卡发出 MASQUERADE 行动与传统 SNAT 行动相比,好处是能动态地从网卡获取地址
4.2 外部访问容器
容器允许外部访问,可以在docker [container] run时候通过-p 或 -P参数来启用。
在本地添加iptables的nat表中添加相应规则
规则映射地址为0.0.0.0,意味着将接受主机来自所有网络接口上的流量。用户可以通过-p IP:host_port:container_port 或-p IP:port 来指定绑定的外部网络接口,以指定更严格的访问规则
如果希望映射绑定到某个固定的宿主机IP地址,可以在Docker配置文件中指定DOCKER_OPTS="--ip=IP_ADDRESS",之后重启Docker服务即可生效
5. 配置容器网桥
Docker 会默认创建一个docker0的Linux网桥(其上有一个docker0 内部接口),在内核层连通了其他的物理或虚拟网卡,将所有容器和本地主机都放在同一个物理网络。用户使用docker创建多个自定义网络时可能出现多个容器网桥。
docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU (接口允许接收的最大传输单元),通常是 1500B, 或宿主主机网络路由上支持的默认值。这些值 都可以在服务启动的时候进行配置
--bip=CIDR: IP地址加掩码格式
--mtu=BYTES: 覆盖默认的Docker mtu配置:
在配置文件中配置DOCKER_OPTS,重启服务docker网桥是Linux网桥,可以通过brctl show来查看网桥和端口信息
[root@kubernetes ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024226291d89 no vetha462a72
yum install bridge-utils
apt-get install bridge-utils
创建容器时,docker从可用的地址段选择空闲的ip地址分配给容器的eth0端口,使本地主机上的docker0接口的IP 作为容器的默认网关
[root@kubernetes /usr/local/nginx]# docker run -it --rm centos bash
[root@e188e00fe279 /]# ip addr show eth0
560: eth0@if561: mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@e188e00fe279 /]# ip route
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.3
6. 自定义网桥
除了默认的docker0网桥,还可以指定其他网桥来连接各个容器,在启动docker服务时,可使用-b BRIDGE或--bridge=BRIDGE指定网桥
先停止服务,删除旧网桥
systemctl stop docker
ip link set dev docker0 down
brctl delbr docker0
创建网桥
brctl addbr bridge0
ip addr add 192.168.5.1/24 dev bridge0
ip link set dev bridge0 up
查看确认网桥启动
ip addr show bridge0
配置服务,默认桥接到创建的网桥上:
echo 'DOCKER_OPTS"="-b=bridge0"' >> /etc/default/docker
systemctl start docker
启动一个容器,查看是否桥接到bridge0上。
可使用brctl show查看桥接的信息。在容器中可以使用ip addr和ip route命令查看ip地址配置和路由信息