docker网络
docker 技术不是凭空而来,而是站在linux技术基础上发起来的
chroot
将进程限定到指定的目录下,防止因程序异常对系统造成影响。在rsync-daemon / named 等程序中都有应用
cgroup
可以通过cgroup 来限制容器对资源的使用,主要时对cpu 和 内存
查询cgroup 内核对cpu的支持grep -i cgroup /boot/config-3.10.0-957.el7.x86_64
查询cgroup 内核对内存的支持grep -i mem /boot/config-3.10.0-957.el7.x86_64 |grep -i cg
查看系统对各种资源的限制 ls /sys/fs/cgroup/
当主机不够分配时。linux 会为每一个进程算一个分数,最终它会kill掉得分最高的进程(OOM Killer(Out of Memory Killer))
/proc/[pid]/oom_score_adj 范围 -1000 ~ 1000 值越高越容易被kill掉 如果设置为 -1000 则进程永远不会被内核kill
/proc/[pid]/oom_adj 范围 -17 ~ 15 值越高越容易被kill掉 如果设置为 -17 则进程永远不会被内核kill
/proc/[pid]/oom_score 综合计算内存、cpu、存活时间和 oom_adj得分。值越高越容易被kill掉
namespace
隔离类型 | 功能 | 系统调用参数 | 内核版本 |
---|---|---|---|
Mnt NameSpace(mount) | 提供磁盘挂载点和文件系统的隔离能力 | CLONE_NEWNS | 2.4.19 |
Ipc NameSpace(inter-process communication) | 提供进程间通讯的隔离能力 | CLONE_NEWIPC | 2.6.19 |
Uts NameSpace(unix timesharing system) | 主机名的隔离能力 | CLONE_NEWUTS | 2.6.19 |
Pid NnameSpace(process identification) | 提供进程的隔离能力 | CLONE_NEWPID | 2.6.24 |
Net NameSpace(nework) | 提供网络隔离能力 | CLONE_NEWNET | 2.6.29 |
User NameSpace(user) | 提供用户隔离能力 | CLONE_NEWUSER | 3.8 |
下面我们单独列出容器的网络名称空间的实现隔离的过程
docker run --net=host --rm -it alpine ip a docker run --net=bridge --rm -it alpine ip a docker run --net=none --rm -it alpine ip a docker run --net=container:pause --rm -it alpine ip a # mutil 自定义网络 可以是bridge 类型 也可以是 overlay 网络类型 docker run --net=mutil --rm -it alpine ip a
Docker创建一个容器的时候﹐就网络名称空间来说会执行如下操作∶
-
创建一对虚拟接口,分别放到宿主机和新容器中
-
虚拟网络接口一端桥接到默认的docker0或指定网桥上﹐并具有一个唯一的名字﹐如veth65f9
-
虚拟网络接口另一端放在容器网络名称空间中﹐并修改名字为eth0
-
从docker0网桥中获取一个空闲地址分配给容器的eth0,并配置默认路由到桥接网卡veth65f9
-
创建一对虚拟接口,分别放到宿主机和新容器中
# 创建名称空间,模拟一个容器 ip netns add netns0 # 创建虚拟网络对 ip link add A type veth peer name B # 把虚拟网络对的一端放置到新建的名称空间 并命名为 eth0 ip link set A name eth0 netns netns0 # 进入虚拟网络名称空间配置网络 nsenter --net=/var/run/netns/netns0 bash ip link set eth0 up ip link set lo up ip address add 172.17.100.1/24 dev eth0 # 宿主机配置虚拟网络对 ip link set B up ip address add 172.17.100.2/24 dev B ip neigh 以上已经完成了跨网络名称空间的通讯
-
在第一步的基础上我们继续学习多网络名称空间网络通讯
# 创建两个名称空间,模拟两个新建的容器 ip netns add netns0 ip netns add netns1 ip link add A type veth peer name B ip link add C type veth peer name D ip link set A name eth0 netns netns0 ip link set C name eth0 netns netns1 nsenter --net=/var/run/netns/netns0 bash -c "ip link set eth0 up ;ip link set eth0 up; ip address add 172.17.100.1/24 dev eth0" nsenter --net=/var/run/netns/netns1 bash -c "ip link set eth0 up ;ip link set eth0 up; ip address add 172.17.100.2/24 dev eth0" 主要区别在这里了,在宿主机创建了一个网桥,类似docker0
ip link add br172 type bridge ip link set br172 up ip link set B up ip link set D up ip link set B master br172 ip link set D master br172 此时两个名称空间已经可以互相访问,如果需要与宿主机通讯,此时已经涉及到iso 网络模型的的三层,需要配置ip 和 路由,下面我们继续学习。
ip address add 172.17.100.254/24 dev br172 # netns0 和 netns1 中设置默认路由为网桥 nsenter --net=/var/run/netns/netns0 bash ip r add default via 172.17.100.254/24 # nsenter --net=/var/run/netns/netns1 bash ip r add default via 172.17.100.254/24 此时你的容器已经可以与宿主机的网络互通了,如果需要在容器内访问互联网,这是你应该想到了 iptables 的SNAT 功能
iptables -t nat -I POSTROUTING -s 172.17.100.0/24 ! -o br172 -j MASQUERADE iptables -P FORWARD ACCEPT 此时你的容器已经可以上网了,如果希望容器可以对外提供服务,比如希望对外提供httpd ,你需要配置DNAT的功能
# 外部访问名称空间内网络 iptables -t nat -I PREROUTING -d 10.4.7.10 -m tcp -p tcp --dport 65535 -j DNAT --to-destination 172.17.100.1:8000 # iptables -t nat -A OUTPUT -d 10.4.7.10 -p tcp -m tcp --dport 65535 -j DNAT --to-destination 172.17.100.1:8000
以上是docker0网桥模式下单个宿主机各个容器通讯的过程,如果我们希望不同宿主机的容器能够互相通讯就需要是有overlay 网络模型
-
启动一个注册中心
docker run --rm -d -p8500:8500 consul
-
修改dockerd的配置文件
[root@master ~]# cat /etc/docker/daemon.json { "cluster-store": "consul://10.4.7.12:8500", "cluster-advertise": "eth0:2376", "registry-mirrors": ["https://o957bhxb.mirror.aliyuncs.com"] } systemctl daemon-reload systemctl restart docker -
创建overlay类型的网络驱动
docker network create -d overlay multi -
在不同的宿主机上分别启动容器
docker run --rm -it --net=multi alpine sh
最后我想总结下docker network命令的使用。docker 支持CNM(container network model) 的网络模型在docker中具体实现方式就是通过docker network
命令实现
删除没有用的网络 docker network prune
列出当前网络docker network ls
创建一个网桥
docker network create -d bridge my-bridge-network docker network create bbb --attachable --driver bridge --subnet "192.168.0.1/24" docker network create -d overlay my-multihost-network
连接到网桥 docker network connect my-bridge-network busybox
断开连接 docker network disconnect my-bridge-network busybox
删除网桥 docker network rm my-bridge-network
查看网桥的具体内容 docker network inspect my-bridge-network
QA
下面这个问题是有一天启动了一个容器但是忘记了使用 --publish
将端口暴露出去,于是回想docker--publish
的原理是通过iptables 实现的,于是使用iptables 的防火墙验证下这个想法
iptables -t nat -A PREROUTING -d 172.21.160.147 -p tcp --dport 10000 -j DNAT --to-destination 172.7.200.2:80 iptables -t nat -A POSTROUTING -s 172.7.200.2 -p tcp --sport 80 -j MASQUERADE
你知道macvlan么,在docker中如何创建一个macvlan的网桥
- macvlan是kernel新支持的特性之一,需要Linux kernel v3.9–3.19和4.0+的支持。
- 这种模式所配置的网络同主机网络在同一个LAN里面,可以具有和主机一样的网络能力。
在linux环境中手工创建macvlan 的网桥模式
1993 ip link add link ens33 name ens33.1 type macvlan mode bridge 1995 ethtool -i ens33.1 1996 ip a a 10.4.7.199/24 dev ens33.1
docker network create -d macvlan -subnet=10.4.7.0/24 --gatway=10.4.7.254 -o parent=eht0 -o macvlan_mode=private testmacvlan
[root@allinone ~]# docker run -it --net=testmacvlan alpine sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 29: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN link/ether 02:42:0a:04:07:01 brd ff:ff:ff:ff:ff:ff inet 10.4.7.1/24 brd 10.4.7.255 scope global eth0 valid_lft forever preferred_lft forever / #
给容器添加一个网卡,再次观察容器的网卡信息
docker network connect bridge 4902552c6e64
/ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 29: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN link/ether 02:42:0a:04:07:01 brd ff:ff:ff:ff:ff:ff inet 10.4.7.1/24 brd 10.4.7.255 scope global eth0 valid_lft forever preferred_lft forever 30: eth1@if31: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:07:c8:02 brd ff:ff:ff:ff:ff:ff inet 172.7.200.2/24 brd 172.7.200.255 scope global eth1 valid_lft forever preferred_lft forever
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏