提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言


Docker网络模式总结

网络模式 核心特点 适用场景
host 共享宿主机网络栈,无端口映射 对网络性能要求高,无端口冲突风险的场景
container 共享其他容器网络,隔离其他资源 容器间紧密协作(如应用+日志收集)
none 无网络配置,仅lo网卡 离线任务、高安全性需求
bridge 默认模式,独立网络栈+docker0网桥 单主机容器通信,常规场景
自定义 支持DNS、跨主机、MAC模拟 集群部署、复杂网络隔离

二、Docker资源控制(Docker优化)

避免单容器占用过多宿主机资源(如CPU、内存),Docker基于Linux的cgroups(Control Groups)机制实现资源限制。

cgroups是Linux内核提供的资源管理工具,支持限制、统计、优先级分配等功能。

cgroups 的 4 大功能(简要):

  • 资源限制:限制任务使用的总资源量。
  • 优先级分配:如通过 cpu 时间片和 IO 带宽分配优先级。
  • 资源统计:统计 cpu 时长、内存用量等。
  • 任务控制:对 cgroup 中的进程执行挂起/恢复等操作。

2.1 CPU资源控制

2.1.1 设置CPU使用率上限(–cpu-period / --cpu-quota)

  • 原理:Linux使用CFS(完全公平调度器)调度CPU,通过两个参数控制容器CPU使用率:

    –cpu-period:调度周期(单位:微秒,默认100000,即100ms);
    –cpu-quota:容器在一个周期内可使用的CPU时间(单位:微秒,默认-1,即无限制);
    计算公式:可用CPU核心数 = cpu-quota / cpu-period(如50000/100000=0.5,即50%的单核CPU)。
    实战示例:

# 方式1:使用--cpu-quota(限制为50%单核CPU)
docker run -itd --name test6 --cpu-quota 50000 centos:7 /bin/bash

# 方式2:使用--cpus(更直观,Docker 1.13+支持)
docker run -itd --name cputest --cpus="0.5" centos:7 /bin/bash
# 说明:--cpus="0.5" 等价于 --cpu-period=100000 --cpu-quota=50000

# 进行压测并在宿主机查看cpu使用率
docker stats
  • 注意:若宿主机有4个逻辑核,0.5个CPU相当于整机CPU能力的12.5%(0.5/4=0.125)。

  • 最小值/范围:–cpu-period 有效范围通常 1000 ~ 1000000(单位 us)。–cpu-quota 必须 >= 1000(1 ms)或者 -1(不限制)。

2.1.2 设置CPU占用比(权重 — --cpu-shares)

  • 原理:–cpu-shares指定CPU使用的相对权重(默认1024),仅在CPU资源紧张(容器争用CPU)时生效,并非硬限制。例如:
    容器A(–cpu-shares 512)与容器B(–cpu-shares 1024)争用CPU时,分配比约为1:2。
# 创建两个不同权重的容器
docker run -itd --name c1 --cpu-shares 512 centos:7
docker run -itd --name c2 --cpu-shares 1024 centos:7
# 验证:在容器内运行压力测试工具stress
# 1. 进入容器安装stress(先在容器内设置阿里源)
docker cp CentOS-Base.repo c1:/etc/yum.repos.d/
docker exec -it c1 bash
yum install -y epel-release && yum install -y stress

# 2. 每个容器启动4个CPU压力进程
stress -c 4  # 在c1和c2中分别执行

# 3. 宿主机查看CPU分配(倾向于1:2)
docker stats

2.1.3 绑定指定CPU(–cpuset-cpus)

原理:将容器进程绑定到宿主机的指定CPU核心(硬亲和性),避免进程在不同核心间切换,提升性能稳定性。

实战示例:

# 将容器绑定到宿主机第1、3个核心(核心编号从0开始)
docker run -itd --name test7 --cpuset-cpus "1,3" centos:7 /bin/bash

# 验证:宿主机查看核心利用率
top  # 按键盘1键,查看CPU1和CPU3的使用率
# 或进入容器运行 taskset -p <pid>

2.1.4 CPU压力测试与验证示例

在容器内创建一个繁忙循环脚本:

# /cpu.sh
#!/bin/bash
i=0
while true; do let i++; done

在容器内运行 ./cpu.sh,在宿主机观察 top 与 docker stats:

docker exec -it <container> bash
./cpu.sh

分别进入容器,进行压力测试

yum install -y epel-release
yum install -y stress
stress -c 4				#产生四个进程,每个进程都反复不停的计算随机数的平方根
yum install -y epel-release && yum install -y stress

修改 cgroups 手工测试(示例):

# 找到容器对应的 cgroup 路径(容器ID替换)
cd /sys/fs/cgroup/cpu/docker/<container-id>/
cat cpu.cfs_period_us
cat cpu.cfs_quota_us
echo 50000 > cpu.cfs_quota_us   # 设置配额(临时生效)

2.1.5 CPU资源控制注意事项

cpu-shares是权重,非硬限制(CPU空闲时,容器可使用超过权重的资源);
–cpu-quota/–cpus是硬限制,容器无法突破设定的CPU上限(quota = -1 表示无限制);
–cpuset-cpus适合对性能稳定性要求高的场景(避免与其他进程抢核)(如数据库容器)。
在多核宿主机上理解 quota/period 的含义(单位是 “相对于 1 个 CPU 的份额”)。

通过自定义脚本模拟CPU高负载,验证资源限制效果:

2.2 内存使用限制

内存限制通过-m/–memory和–memory-swap参数实现,避免容器耗尽宿主机内存。

2.2.1 --memory与–memory-swap规则

–memory:限制容器可使用的物理内存(如-m 512m表示512MB);
–memory-swap:限制容器可使用的物理内存+交换分区(swap) 总量,需与–memory配合使用

  • 核心规则:
    1.示例-m 300m --memory-swap=1g:物理内存300MB,swap可用700MB(1G-300M);
    2.不设置–memory-swap:默认swap为–memory的2倍(如-m 512m,swap默认1024MB);
    3.–memory-swap=-1:swap无限制(使用宿主机所有可用swap);
    4.–memory-swap=–memory:容器不可使用swap(物理内存用尽触发OOM)

2.2.2 内存限制示例命令

# 1. 限制物理内存512MB(swap默认1024MB)
docker run -itd --name memtest -m 512m centos:7 /bin/bash

# 2. 限制物理内存300MB,swap总量1GB(swap可用700MB)
docker run -itd --name memtest2 -m 300m --memory-swap=1g centos:7 /bin/bash

2.2.3 内存限制验证与OOM行为

  • 验证内存限制:
# 1. 宿主机查看容器内存限制(替换为容器ID)
cd /sys/fs/cgroup/memory/docker/<容器ID>/
cat memory.limit_in_bytes  # 输出内存限制(单位:字节,512MB=536870912字节)
cat memory.usage_in_bytes  # 输出当前内存使用量

# 2. 容器内模拟内存高负载(使用stress)
docker exec -it memtest bash
stress --vm 1 --vm-bytes 600m  # 尝试使用600MB内存(超过512MB限制)
  • OOM行为:若容器内存超过限制且无swap可用,内核会触发OOM Killer杀死容器,可通过docker logs查看日志或者 dmesg 来确认 OOM 事件。

2.3 磁盘IO(blkio/io)控制

Docker基于cgroups的blkio控制器(cgroup v1)或io控制器(cgroup v2)限制容器的磁盘读写速率和IOPS(每秒输入输出次数)。

2.3.1 常用Docker磁盘IO限制参数

参数说明表格

参数 作用 示例
--device-read-bps 限制设备读速率(单位:B/s、KB/s、MB/s) --device-read-bps /dev/sda:1M
--device-write-bps 限制设备写速率 --device-write-bps /dev/sda:1M
--device-read-iops 限制设备读IOPS(次数) --device-read-iops /dev/sda:100
--device-write-iops 限制设备写IOPS(次数) --device-write-iops /dev/sda:100

实战示例:限制容器对/dev/sda(宿主机磁盘)的写速率为1MB/s

docker run -it --name iotest --device-write-bps /dev/sda:1MB centos:7 /bin/bash

2.3.2 磁盘IO限制验证(dd测试)

通过dd命令(跳过文件系统缓存)测试写速率:

# 容器内执行dd命令(写入10个1MB的块)跳过文件系统缓存
dd if=/dev/zero of=test.out bs=1M count=10 oflag=direct

# 输出示例(写速约1MB/s,符合限制):
# 10485760 bytes (10 MB) copied, 10.0028 s, 1.0 MB/s

在这里插入图片描述

2.3.3 磁盘IO控制注意事项

1.限制需指定具体块设备路径(如/dev/sda),路径错误会导致限制失效;
2.云环境或虚拟化环境中,底层存储(如AWS EBS、阿里云云盘)可能有自身IO限制,容器层限制需结合底层限制配置;
3.cgroup v2环境中,IO限制参数不同(如使用–device-io-max),需参考对应Docker版本文档。

2.4 清理Docker占用的磁盘空间

Docker运行一段时间后,会积累停止的容器、未使用的镜像、网络和构建缓存,可通过以下命令清理

# 清理所有未使用的资源(停止的容器、未使用的镜像、网络、缓存)
docker system prune -a
# 注意:此命令会删除所有未活跃的资源,执行前确认无需保留!

在这里插入图片描述

2.5 Docker资源控制常见命令速查

# CPU相关
docker run -itd --name c1 --cpu-shares 512 centos:7  # 权重512
docker run -itd --name c2 --cpu-quota 50000 centos:7  # 50%单核
docker run -itd --name c3 --cpuset-cpus "1,3" centos:7  # 绑定核心1、3
docker run -itd --name c4 --cpus="0.5" centos:7  # 直观指定0.5核

# 内存相关
docker run -itd --name memtest -m 512m centos:7  # 512MB物理内存
docker run -itd --name memtest2 -m 300m --memory-swap=1g centos:7  # 300M+700M swap

# 磁盘IO相关
docker run -it --name iotest --device-write-bps /dev/sda:1MB centos:7  # 写速1MB/s

# 监控与验证
docker stats  # 实时监控容器资源使用
docker exec -it <容器ID> bash  # 进入容器操作
cat /sys/fs/cgroup/cpu/docker/<容器ID>/cpu.cfs_quota_us  # 查看CPU配额
cat /sys/fs/cgroup/memory/docker/<容器ID>/memory.limit_in_bytes  # 查看内存限制

# 清理资源
docker system prune -a  # 清理未使用资源

2.6 Docker资源控制常见陷阱与建议

权重vs限额:–cpu-shares是相对权重(争用时生效),–cpu-quota/–cpus是硬限额(强制限制);
cgroup版本差异:CentOS 7默认用cgroup v1,CentOS 8+或新内核可能用cgroup v2,控制器名称和参数不同(如blkio→io);
IO 限制依赖底层设备:在云/虚拟机上测试时,注意底层虚拟磁盘的行为。
生产环境监控:建议搭配Prometheus+Grafana+cAdvisor监控容器资源,及时发现资源瓶颈;
权限控制:修改/sys/fs/cgroup目录下的配置需root权限,优先使用docker run参数配置,避免直接修改系统文件。

三、Docker数据卷容器(Data Volumes Containers)

容器文件系统临时的——容器删除后,内部数据会丢失。
Docker的数据卷(Data Volumes)机制解决问题,实现数据持久化;而数据卷容器则进一步简化了多容器间的数据共享。

3.1 数据卷

数据卷是容器内的特殊目录,可与宿主机目录或其他容器共享,具备以下特性:

  • 数据持久化:容器删除后,数据卷中的数据不会丢失;
    -双向同步:宿主机与容器对数据卷的修改实时同步;
    -跨容器共享:多个容器可挂载同一个数据卷。

3.1.1 创建与挂载数据卷

通过docker run的-v或–mount参数挂载数据卷,格式:-v 宿主机目录:容器内目录。

# 挂载宿主机/var/www目录到容器内/data1目录
docker run -v /opt/www:/data1 --name web1 -it centos:7 /bin/bash
# 参数说明:
# /var/www:宿主机目录(不存在会自动创建);
# /data1:容器内目录(不存在会自动创建);
# web1:容器名称。
  • -v /var/www:/data1: 将宿主机上的 /var/www 目录挂载到容器中的 /data1 目录。
    这样容器内 /data1 的修改会同步到宿主机上的 /var/www。

  • -it centos:7 /bin/bash: 使用 centos:7 镜像启动容器并进入交互式 shell。

在这里插入图片描述

3.1.2 在数据卷中写入数据

进入容器后,在数据卷目录(/data1)中创建文件,数据会同步到宿主机:

# 容器内执行(写入数据到/data1/abc.txt)
echo "this is web1" > /data1/abc.txt
exit

此时,容器中的 /data1/abc.txt 文件与宿主机中的 /var/www/abc.txt 文件是同步的。即使容器退出,宿主机上的数据依然存在。

3.1.3 查看宿主机同步的数据

退出容器后,查看宿主机/var/www目录,数据已同步:

# 宿主机执行
cat /opt/www/abc.txt  # 输出:this is web1

在这里插入图片描述

3.2 数据卷容器

专门用于提供数据卷的容器,不运行应用程序,仅作为“数据载体”,供其他容器通过–volumes-from挂载其数据卷。适用于多容器共享数据的场景(如微服务中的配置共享、日志存储)。

3.2.1 创建数据卷容器

# 创建数据卷容器web2,挂载两个数据卷/data1和/data2
docker run --name web2 -v /data1 -v /data2 -it centos:7 /bin/bash
# 说明:-v /data1 未指定宿主机目录,Docker会在宿主机/var/lib/docker/volumes/下创建匿名卷
  • –name web2: 给容器命名为 web2。
  • -v /data1 -v /data2: 在容器内部挂载了两个数据卷 /data1 和 /data2。这些数据卷不依赖于宿主机,而是仅仅存在于容器内。

在这里插入图片描述

3.2.2 在数据卷容器中写入数据

进入web2容器,在数据卷中写入测试数据:

# 进入web2容器
docker exec -it web2 bash

# 在/data1和/data2中写入数据
echo "this is web2" > /data1/abc.txt
echo "THIS IS WEB2" > /data2/ABC.txt

3.2.3 使用–volumes-from共享数据卷

创建新容器web3,通过–volumes-from挂载web2的数据卷:

# 创建web3,共享web2的所有数据卷
docker run -it --volumes-from web2 --name web3 centos:7 /bin/bash
# 说明:--volumes-from web2 表示继承web2的所有数据卷配置

–volumes-from web2: 这表示将容器 web2 中的所有数据卷挂载到新容器 web3 中。

3.2.4 在新容器中验证共享数据

进入web3容器,查看/data1和/data2目录,可看到web2中写入的数据:

# 进入web3容器
docker exec -it web3 bash

# 查看数据
cat /data1/abc.txt  # 输出:this is web2
cat /data2/ABC.txt  # 输出:THIS IS WEB2

在这里插入图片描述

3.3 数据卷与数据卷容器总结

1.数据卷 (Data Volumes):解决“容器数据持久化”问题,通过-v挂载宿主机目录;
2.数据卷容器(Data Volumes Containers):解决“多容器数据共享”问题,通过–volumes-from继承数据卷,无需每个容器都挂载宿主机目录;
3.注意:数据卷容器删除后,其数据卷(匿名卷)不会被删除,需手动清理(docker volume rm <卷ID>)。

在这里插入图片描述

四、Docker容器互联(使用CentOS镜像)

容器互联是指通过网络让两个或多个容器直接通信,Docker早期通过–link选项实现,适用于简单的单主机容器通信场景(复杂场景建议使用自定义网络)。

4.1 创建并运行源容器web1

首先创建“源容器”web1,作为通信的发起方:

# 启动web1容器(后台运行,随机端口映射)
docker run -itd -P --name web1 centos:7 /bin/bash
# 参数说明:
# -itd:交互式+后台运行;
# -P:随机映射端口;
# --name web1:指定容器名称(互联需依赖名称)。

4.2 创建并运行接收容器web2(–link互联)

创建“接收容器”web2,通过–link选项连接web1,格式:–link 源容器名称:源容器别名。

# 启动web2,通过--link连接web1(别名为web1)
docker run -itd -P --name web2 --link web1:web1 centos:7 /bin/bash
# 说明:--link web1:web1 表示将web1容器暴露给web2,web2中可通过“web1”这个别名访问web1。

4.3 在接收容器web2中测试连接

进入web2容器,通过ping命令测试与web1的通信(无需知道web1的Container-IP):

# 1. 进入web2容器
docker exec -it web2 bash

# 2. 测试与web1的连通性(使用别名web1)
ping web1
# 输出示例(ping通表示互联成功):
# PING web1 (172.17.0.2) 56(84) bytes of data.
# 64 bytes from web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.068 ms

在这里插入图片描述

4.4 Docker容器互联总结

  • 1.核心原理:–link会在接收容器的/etc/hosts文件中添加源容器的别名与Container-IP的映射,因此接收容器可通过别名通信;
  • 2.局限性:–link仅支持单主机容器互联,且不支持动态更新(源容器IP变化后,接收容器的/etc/hosts不会自动更新);
  • 3.替代方案:复杂场景(如跨主机、动态容器)建议使用Docker自定义网络(如overlay),支持DNS自动解析和动态IP更新。

源容器:通过 docker run 启动,并通过 --name 指定一个唯一名称,例如 web1 。
接收容器:通过 docker run 启动,并通过 --link 选项将其与源容器 web1 连接。 --link 会将
源容器暴露为别名,接收容器可以通过该别名与源容器进行通信。
容器间通信:接收容器可以通过源容器的名称进行通信,如在 web2 中通过 ping web1 测试与
web1 的连通性。

这种容器互联的方式适用于简单的容器间网络通信,但在较复杂的场景中,建议使用 Docker 网络(如
桥接网络或自定义网络)来管理容器间的通信。


总结

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐