文章目录
- Docker 网络
- Docker 网络实现原理
- 端口映射示例
- 查看容器的输出和日志信息
- Docker 的网络模式
- 查看 Docker 网络列表
- Docker 容器网络命名空间示例
- 创建并运行容器
- 查看容器列表
- 查看容器进程号
- 查看容器的命名空间编号
- 创建并运行共享网络命名空间的容器
- 查看容器列表
- 查看容器进程号
- 查看容器的命名空间编号
- Docker 资源控制
- 1. CPU 资源控制
- 1.1 设置 CPU 使用率上限
- 进行CPU压力测试
- 1.2 设置 CPU 资源占用比
- 1.3 设置容器绑定指定的 CPU
- 2. 内存使用限制
- 3. 磁盘 IO 配额控制
- 通过dd来验证写速度
- 清理 Docker 占用的磁盘空间
Docker 网络
Docker 网络实现原理
Docker 使用 Linux 桥接技术,在宿主机上虚拟一个名为 docker0
的 Docker 容器网桥。当 Docker 启动一个容器时,会根据 docker0
网桥的网段分配给容器一个 IP 地址(Container-IP)。由于同一宿主机内的容器都连接到同一个网桥,因此容器之间可以通过各自的 Container-IP 直接通信。
Docker 网桥是虚拟的,不是真实存在的网络设备,因此外部网络无法直接寻址到它,这意味着外部网络无法直接通过 Container-IP 访问容器。如果希望外部网络能够访问容器,可以通过端口映射将容器端口映射到宿主主机,即使用 docker run
命令的 -p
或 -P
参数。
端口映射示例
# 随机映射端口(从32768开始)
docker run -d --name test1 -P nginx
# 指定映射端口
docker run -d --name test2 -p 43000:80 nginx
通过 docker ps -a
可以查看容器的端口映射情况,例如:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d3c04f57a68 nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 0.0.0.0:43000->80/tcp test2
b04895f870e5 nginx "/docker-entrypoint.…" 17 seconds ago Up 15 seconds 0.0.0.0:49170->80/tcp test1
可以通过浏览器访问 http://192.168.80.10:43000
和 http://192.168.80.10:49170
来访问对应的容器。
查看容器的输出和日志信息
使用 docker logs
命令可以查看容器的输出和日志信息:
docker logs 容器的ID/名称
Docker 的网络模式
使用 --net
或 --network
选项指定容器的网络模式
- Host 模式
- 相当于 Vmware 中的桥接模式,与宿主机在同一个网络中,但没有独立 IP 地址。
- 容器与宿主机共享同一个 Network Namespace,使用宿主机的 IP 和端口。
- 使用
--net=host
指定。
- Container 模式
- 新创建的容器与已存在的容器共享一个 Network Namespace。
- 共享 IP、端口范围等,但文件系统、进程列表等仍然隔离。
- 使用
--net=container:NAME_or_ID
指定。
- None 模式
- 容器拥有自己的 Network Namespace,但不进行任何网络配置。
- 只有 lo 回环网络,没有其他网卡。
- 无法联网,但保证了容器的安全性。
- 使用
--net=none
指定。
- Bridge 模式
- Docker 的默认网络模式。
- 容器使用独立的 Network Namespace,并连接到
docker0
虚拟网卡。 - 通过
docker0
网桥和 iptables nat 表配置与宿主机通信。 - 为每个容器分配 IP,并通过 veth pair 设备与
docker0
网桥连接。 - 默认设置,可省略或使用
--net=bridge
指定。
- 自定义网络
- 允许用户自定义网络配置,如指定子网、网关等。
- 可以使用
docker network create
命令创建自定义网络。 - 示例:
# 创建自定义网络 docker network create --subnet=172.18.0.0/16 --opt "com.docker.network.bridge.name"="docker1" mynetwork #docker1 为执行 ifconfig -a 命令时,显示的网卡名,如果不使用 --opt 参数指定此名称,那你在使用 ifconfig -a 命令查看网络信息时,看到的是类似 br-110eb56a0b22 这样的名字,这显然不怎么好记。 #mynetwork 为执行 docker network list 命令时,显示的bridge网络模式名称。 # 使用指定 IP 运行容器 docker run -itd --name test4 --net mynetwork --ip 172.18.0.10 centos:7 /bin/bash
查看 Docker 网络列表
使用 docker network ls
或 docker network list
命令可以查看 Docker 网络列表:
docker network ls
# 或
docker network list
示例输出:
NETWORK ID NAME DRIVER SCOPE
2b4359d229c6 bridge bridge local
0fa580365d39 host host local
cc13aa84a223 none null local
总结
- Host:容器使用宿主机的 IP 和端口。
- Container:容器与另一个指定容器共享 IP 和端口范围。
- None:关闭容器的网络功能。
- Bridge:默认模式,为每个容器分配 IP 并连接到
docker0
虚拟网桥。 - 自定义网络:允许用户自定义网络配置。
Docker 容器网络命名空间示例
创建并运行容器
docker run -itd --name test1 centos:7 /bin/bash # 创建名为 test1 的容器
查看容器列表
docker ps -a
输出示例:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3ed82355f811 centos:7 "/bin/bash" 5 days ago Up 6 hours test1
查看容器进程号
docker inspect -f '{{.State.Pid}}' 3ed82355f811 # 查看 test1 容器的进程号
输出示例:
25945
查看容器的命名空间编号
ls -l /proc/25945/ns # 查看 test1 容器的进程、网络、文件系统等命名空间编号
输出示例:
lrwxrwxrwx 1 root root 0 1月 7 11:29 ipc -> ipc:[4026532572]
lrwxrwxrwx 1 root root 0 1月 7 11:29 mnt -> mnt:[4026532569]
lrwxrwxrwx 1 root root 0 1月 7 11:27 net -> net:[4026532575]
lrwxrwxrwx 1 root root 0 1月 7 11:29 pid -> pid:[4026532573]
lrwxrwxrwx 1 root root 0 1月 7 12:22 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 1月 7 11:29 uts -> uts:[4026532570]
创建并运行共享网络命名空间的容器
docker run -itd --name test2 --net=container:3ed82355f811 centos:7 /bin/bash # 创建名为 test2 的容器,并与 test1 共享网络命名空间
查看容器列表
docker ps -a
输出示例:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ff96bc43dd27 centos:7 "/bin/bash" 48 seconds ago Up 46 seconds test2
3ed82355f811 centos:7 "/bin/bash" 58 minutes ago Up 58 minutes test1
查看容器进程号
docker inspect -f '{{.State.Pid}}' ff96bc43dd27 # 查看 test2 容器的进程号
输出示例:
27123
查看容器的命名空间编号
ls -l /proc/27123/ns # 查看 test2 容器的进程、网络、文件系统等命名空间编号
输出示例:
lrwxrwxrwx 1 root root 0 1月 7 12:27 ipc -> ipc:[4026532692]
lrwxrmxrwx 1 root root 0 1月 7 12:27 mnt -> mnt:[4026532690]
lrwxrwxrwx 1 root root 0 1月 7 12:27 net -> net:[4026532575]
lrwxrwxrwx 1 root root 0 1月 7 12:27 pid -> pid:[4026532693]
lrwxrwxrwx 1 root root 0 1月 7 12:27 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 1月 7 12:27 uts -> uts:[4026532691]
Docker 资源控制
Docker 通过 Cgroups(Control Groups)机制来控制和限制容器使用的资源,包括 CPU、内存和磁盘 IO。以下是对这些资源控制的详细解释和示例。
1. CPU 资源控制
1.1 设置 CPU 使用率上限
- CFS(Completely Fair Scheduler):Linux 使用CFS来调度各个进程对CPU的使用,CFS默认的调度周期是100ms。
- –cpu-period:设置CPU调度周期(微秒),有效范围是1ms到1s(1000到1000000)。
- –cpu-quota:设置每个周期内容器能使用的CPU时间(微秒),值必须大于等于1000。
示例:
docker run -itd --name test6 --cpu-quota 50000 centos:7 /bin/bash
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3ed82355f811 centos:7 "/bin/bash" 5 days ago Up 6 hours test5
cd /sys/fs/cgroup/cpu/docker/3ed82355f81151c4568aaa6e7bc60ba6984201c119125360924bf7dfd6eaa42b/
cat cpu.cfs_quota_us
-1
cat cpu.cfs_period_us
100000
这将使容器 test6
在每个CFS周期中最多使用50%的CPU时间。
相关参数:
cpu.cfs_period_us
:cpu分配的周期(微秒,所以文件名中用 us 表示),默认为100000。
cpu.cfs_quota_us
:表示该cgroups限制占用的时间(微秒),默认为-1,表示不限制。 如果设为50000,表示占用50000/100000=50%的CPU。
进行CPU压力测试
docker exec -it 3ed82355f811 /bin/bash
vim /cpu.sh
#!/bin/bash
i=0
while true
do
let i++
done
chmod +x /cpu.sh
./cpu.sh
top #可以看到这个脚本占了很多的cpu资源
设置50%的比例分配CPU使用时间上限
docker run -itd --name test6 --cpu-quota 50000 centos:7 /bin/bash#可以重新创建一个容器并设置限额
或
cd /sys/fs/cgroup/cpu/docker/3ed82355f81151c4568aaa6e7bc60ba6984201c119125360924bf7dfd6eaa42b/
echo 50000 > cpu.cfs_quota_us
docker exec -it 3ed82355f811 /bin/bash
./cpu.sh
top #可以看到cpu占用率接近50%,cgroups对cpu的控制起了效果
在多核情况下,如果允许容器进程完全占用两个 CPU, 则可以将 cpu-period
设置为 100000( 即 0.1 秒), cpu-quota
设置为 200000(0.2 秒)。
1.2 设置 CPU 资源占用比
- –cpu-shares:指定CPU份额,默认值为1024,值为1024的倍数。当多个容器竞争CPU资源时,份额高的容器获得CPU时间片的几率更高。
示例:
#创建两个容器为 c1 和 c2,若只有这两个容器,设置容器的权重,使得c1和c2的CPU资源占比为1/3和2/3。
docker run -itd --name c1 --cpu-shares 1024 centos:7
docker run -itd --name c2 --cpu-shares 2048 centos:7
这将使容器 c2
在CPU资源竞争中获得比容器 c1
多一倍的机会。
#分别进入容器,进行压力测试
yum install -y epel-release
yum install -y stress
stress -c 4 #产生四个进程,每个进程都反复不停的计算随机数的平方根
#查看容器运行状态(动态更新)
docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c3ee18e65852 c2 66.50% 5.5MiB / 976.3MiB 0.56% 20.4MB / 265kB 115MB / 14.2MB 4
bb02d3b345d8 c1 32.68% 2.625MiB / 976.3MiB 0.27% 20.4MB / 325kB 191MB / 12.7MB 4
- 可以看到在 CPU 进行时间片分配的时候,容器 c2 比容器 c1 多一倍的机会获得 CPU 的时间片。
- 但分配的结果取决于当时主机和其他容器的运行状态, 实际上也无法保证容器 c1 一定能获得 CPU 时间片。比如容器 c1 的进程一直是空闲的,那么容器 c2 是可以获取比容器 c1 更多的 CPU 时间片的。极端情况下,例如主机上只运行了一个容器,即使它的 CPU 份额只有 50,它也可以独占整个主机的 CPU 资源。
- Cgroups 只在容器分配的资源紧缺时,即在需要对容器使用的资源进行限制时,才会生效。因此,无法单纯根据某个容器的 CPU 份额来确定有多少 CPU 资源分配给它,资源分配结果取决于同时运行的其他容器的 CPU 分配和容器中进程运行情况。
1.3 设置容器绑定指定的 CPU
- –cpuset-cpus:允许容器在指定的CPU上运行。
示例:
docker run -itd --name test7 --cpuset-cpus 1,3 centos:7 /bin/bash
这将使容器 test7
只能在CPU 1和CPU 3上运行。
#进入容器,进行压力测试
yum install -y epel-release
yum install stress -y
stress -c 4
然后退出容器,执行 top 命令再按 1 查看CPU使用情况。
2. 内存使用限制
- -m 或 --memory:限制容器可以使用的最大内存。
示例:
docker run -itd --name test8 -m 512m centos:7 /bin/bash
docker stats
- –memory-swap:正常情况下,–memory-swap 的值包含容器可用内存和可用 swap。
如果--memory-swap
设置为 0 或者 不设置,则容器可以使用的 swap 大小为 -m 值的两倍。
如果--memory-swap
的值和 -m 值相同,则容器不能使用 swap。
如果--memory-swap
值为 -1,它表示容器程序使用的内存受限,而可以使用的 swap 空间使用不受限制(宿主机有多少 swap 容器就可以使用多少)。
强调一下,--memory-swap
是必须要与--memory
一起使用的。
示例:容器 test8
最大使用512M内存,容器 test8_swap
可以使用300M内存和700M swap。
docker run -itd --name test8 -m 512m centos:7 /bin/bash
docker run -itd --name test8_swap -m 300m --memory-swap=1g centos:7 /bin/bash
所以 -m 300m --memory-swap=1g
的含义为:容器可以使用 300M 的物理内存,并且可以使用 700M(1G - 300)的 swap。
3. 磁盘 IO 配额控制
- –device-read-bps:限制某个设备上的读速度(bps),单位可以是kb、mb或gb。
- –device-write-bps(在Docker 25版本之后已无效):限制某个设备上的写速度(bps)。
- –device-read-iops:限制读某个设备的IOPS(每秒读次数)。
- –device-write-iops:限制写入某个设备的IOPS(每秒写次数)。
示例:
docker run -itd --name test9 --device-read-bps /dev/sda:1M centos:7 /bin/bash
docker run -it --name test10 --device-write-iops /dev/sda:1000 centos:7 /bin/bash
这将使容器 test9
对设备 /dev/sda
的读速度限制为1MB/s,容器 test10
对设备 /dev/sda
的写IOPS限制为1000次/秒。
通过dd来验证写速度
dd if=/dev/zero of=test.out bs=1M count=10 oflag=direct#添加oflag参数以规避掉文件系统cache
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 10.0025 s, 1.0 MB/s
清理 Docker 占用的磁盘空间
使用 docker system prune -a
命令可以清理关闭的容器、无用的数据卷和网络,释放磁盘空间。
docker system prune -a