目录
Docker网络通讯
通讯流程
物理网卡与docker网桥通过NAT技术连接,虚拟网卡(对端出现)一端在docker0上,另一端在container,使其实现通讯。若有多个设备则,通过docker0转发而实现设备间的通讯。(docker0可以看做二层交换机制,container内拥有Namespace隔离机制)
Namespace - 网络(netns)
netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境,目前 netns 在 lxc 容器中被用来为容器提供网络
使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样
# 创建虚拟网络空间
ip netns add r1
# 进入虚拟网络空间
ip netns exec r1 bash
# 添加一对 veth 设备
ip link add veth1.1 type veth peer name veth1.2
# 将其中一块网卡放入至 ns1 网络名称空间之中
ip link set veth1.1 netns r1
# 更改网络名称
ip link set veth1.1 name eth0
# 启动网卡
ip link set eth0 up
# 设置网卡名称
ip addr add 10.0.0.11/24 dev eth0
# 启动回环网卡
ip link set lo up
实验一:虚拟网络空间实现和内、外部通信
# 给虚拟的空间添加两个虚拟的网卡,一个网卡放于虚拟空间内,另一个放于外部虚拟网桥上,并赋予各自网络地址,实现通信。若有多个虚拟空间,则只需要将放于外部的网卡,放在同一网桥上,即可实现各个虚拟空间之间的通讯。容器与容器间的通信与此同理。
$ ip netns add r1 # 创建一个虚拟的网络空间
$ ip netns exec r1 bash # 进入虚拟网络空间
$ ip addr show # 展现网络接口(只拥有本地回环接口并处于关闭状态,ping不通任何网络)
$ ip link set lo up # 启动回环网卡
$ exit # 退出虚拟网络空间
$ ip link add veth1.1 type veth peer name veth1.2 # 添加虚拟对端网卡
$ ip addr show # 查看是否生成对端网卡
$ ip link set veth1.1 netns r1 # 将其中一个网卡放入虚拟网络空间中
$ ip addr show # 查看是否将网卡放入r1
$ ip netns exec r1 bash # 进入虚拟网络空间
$ ip addr show # 查看是否将网卡放入r1
$ ip link set veth1.1 name eth0 # 网卡改名(也可不改)
$ ip link set veth0 up # 启动虚拟空间内部网卡
$ ip addr show
$ ip addr add 192.168.67.100/24 dev eth0 # 虚拟空间内网卡添加网络信息(IP地址)
$ ifconfig # 查看网络信息
$ exit # 退出虚拟网络空间
$ ip link set veth1.2 up # 启动虚拟空间外的网卡
$ ip addr add 192.168.67.200/24 dev veth1.2# 虚拟空间内网卡添加网络信息(IP地址
$ ip addr show # 查看是否配置成功
$ ping 192.168.67.100 # 尝试能否实现虚拟网络空间内外通信
firewalld 规则
(1) 容器访问外部网络
$ iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o docker0 -j MASQUERADE
(2) 外部网络访问容器
$ docker run -d -p 80:80 apache
$ iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
# DOCKER 在路由前捕获,判断是否是本地数据包,交给下一个命令处理
$ iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80
Docker网络通信方案
隔离:Namespace-network
通讯:
容器间通讯(同主机)
网桥
容器与外部交流
外部访问容器内部
iptables-DNAT
容器访问外部网络
iptables-SNAT
Docker网络模式修改
Docker 进程修改
-b, --bridge=”” 指定 Docker 使用的网桥设备,默认情况下 Docker 会自动创建和使用 docker0 网桥设备,通过此参数可以使用已经存在的设备
--bip 指定 Docker0 的 IP 和掩码,使用标准的 CIDR 形式,如 10.10.10.10/24
--dns 配置容器的 DNS,在启动 Docker 进程是添加,所有容器全部生效
容器修改
--dns 用于指定启动的容器的 DNS
--net # 用于指定容器的网络通讯方式,有以下四个网络模式
$ bridge:Docker # 默认方式,网桥模式
$ none:# 容器没有网络栈
$ container:使用其它容器的网络栈,Docker容器会加入其它容器的 network namespace --network container:(ContainerName)
$ host:表示容器使用 Host 的网络,没有自己独立的网络栈。容器可以完全访问 Host 的网络,不安全 --network host
# 验证none容器没有网络栈:
$ docker run --name test1 -d wyylinux/centos7.3:run
$ docker run --name test2 --net=none -d wyylinux/centos7.3:run
$ docker exec -it test1 /bin/bash
$ ifconfig (若没有yum -y install net-tools) # 查看是否拥有对端网卡(172.)
$ exit
$ docker exec -it test1 /bin/bash
$ ifconfig # 查看是否拥有对端网卡(172.)
或
$ docker inspect test1 # 查看是否拥有对端网卡(172.)
$ docker inspect test2 # 查看是否拥有对端网卡(172.)
# 主要用于离线业务的使用
# 验证container使用其它容器的网络栈
$ docker run --name test3 -d wyylinux/centos7.3:run
$ docker run --name test4 --network container:test3 -d wyylinux/centos7.3:run
$ dcoker exec -it test3 /bin/bash
$ yum clean all
$ yum -y install httpd
$ /usr/bin/httpd # D-Bus(越权)
$ curl localhost # 查看是否可以访问
$ hostname > /var/www/html/index.html
$ curl localhost
$ cd /root/
$ touch why
$ exit
$ docker exec -it test4 /bin/bash
$ curl localhost
$ cd /root/
$ ls
# 可以看到在test3中修改的index.html文件,证明了,会共享与网络相关的,而其他的不会共享。
暴漏端口
-p / P 选项的使用格式
> -p <ContainerPort>:将制定的容器端口映射至主机所有地址的一个动态端口
> -p <HostPort>:<ContainerPort>:映射至指定的主机端口
> -p <IP>::<ContainerPort>:映射至指定的主机的 IP 的动态端口
> -p <IP>:<HostPort>:<ContainerPort>:映射至指定的主机 IP 的主机端口
> -P(大):暴露所需要的所有端口
$ docker port ContainerName 可以查看容器当前的映射关系
自定义 Docker0 的网桥地址
修改 /etc/docker/daemon.json 文件
{
"bip": "192.168.1.5/24", # 当前的docker0地址
"fixed-cidr": "10.20.0.0/16", # 当前的docker0cidr(路由)
"fixed-cidr-v6": "2001:db8::/64",
"mtu": "1500",
"default-gateway": "10.20.1.1", # 默认网关
"default-gateway-v6": "2001:db8:abcd::89",
"dns": ["10.20.1.2","10.20.1.3"]
}
常见的隔离方式
隔离:在空间内拥有独立的机制。
# wordpress搭建请参考https://www.cnblogs.com/wang-yy/p/14502718.html
$ docker-compose up -d # 启动wordpress
$ docker inspect ID(wordpress)
$ docker run --name test -d hub.c.163.com/public/centos:6.7-tools
$ docker exec -it test /bin/bash
$ ping 172.19.03 # inspect 获取查看的ip,不通,是因为网卡放在了不同的广播域下。
基础命令说明
# 查看当前可用的网络类型
$ docker network ls
NETWORK ID # ID号
NAME # 网络名称
DRIVER # 驱动类型
SCOPE # 作用域
# 网络空间名称
$ docker network create -d 类型
# 类型分为:
# overlay network 全覆盖网络,可跨主机控制地址ping通
# bridge network Docker默认方式,网桥模式
独立至不同的网络命名空间进行隔离
# 创建网桥
$ docker network create -d bridge --subnet "172.26.0.0/16" --gateway "172.26.0.1" my-bridge-network
# 给容器指定网桥
$ docker run -d --network=my-bridge-network --name test1 hub.c.163.com/public/centos:6.7-tools
# 给容器指定网桥
$ docker run -d --name test2 hub.c.163.com/public/centos:6.7-tools
使用 Linux 桥接器进行主机间的通讯
# 删除 ens33 网络地址,(若有其他网卡先关闭)
$ ip addr del dev ens33 192.168.66.112/24
# 新建网桥 br0 ,并将 ens33 网卡桥接至 br0
$ ip link add link ens33 dev br0 type macvlan mode bridge
# 给网桥 br0 设置 ip
$ ip addr add 192.168.66.112/24 dev br0
# 启用 br0
$ ip link set dev br0 up
# 给 br0 设置默认网关
$ ip route add default via 192.168.66.1 dev br0
# 为 Docker 容器指定 IP 地址
$ pipework br0 cmv3-manager 192.168.66.101/24@192.168.66.1
# 还原方案
$ ip link delete br0
$ service network restart
$ systemctl restart docker
# pipework下载地址
git clone https://github.com/jpetazzo/pipework