Docker核心功能详解:从资源管控到镜像构建
在容器化技术飞速发展的今天,Docker凭借其轻量、灵活、可移植的特性,成为了开发者和运维人员的必备工具。Docker的强大之处不仅在于容器的创建与运行,更在于其丰富的核心功能,这些功能能帮助我们更精准地管控容器、高效地管理数据、便捷地实现容器间通信以及快速构建自定义镜像。本文将详细介绍Docker中5个核心功能——资源限制、数据卷容器、端口映射、容器互联、镜像创建,并结合具体示例说明其用法,助力大家更好地应用Docker。
一、资源限制:给容器划好“边界”
默认情况下,Docker容器会尽可能占用宿主机的资源(CPU、内存、磁盘I/O等),这可能导致单个容器过度消耗资源,影响其他容器或宿主机的正常运行。通过资源限制功能,我们可以为每个容器分配固定的资源配额,保障系统整体的稳定性。
1.1 核心限制维度
CPU限制:限制容器可使用的CPU核心数、CPU使用率上限等。
内存限制:限制容器可使用的最大内存、交换空间大小等,避免内存溢出。
磁盘I/O限制:限制容器对磁盘的读写速率,防止单个容器占用过多磁盘带宽。
1.2 查看 CPU / 内存整体使用(top/htop)
1.2.1 基础版(系统自带)
**top**

**htop** 为top增强版(需yum安装,更直观)
yum install htop
htop

* 简洁查询内存 / CPU(free/mpstat)
# 查看内存使用(带单位,更易读)
free -h
# 查看CPU整体使用率
mpstat
# 查看每个CPU核心的使用率
mpstat -P ALL

1.2.2 Docker 自带命令(关联容器与宿主机资源)
# 查看宿主机上所有容器的资源占用(间接反映宿主机负载)
docker stats
# 只看宿主机层面的Docker系统信息(含总内存/CPU核心数)
docker info | grep -E 'CPU|Memory|Total'

1.2.3 cpu使用率上限(–cpu-period/–cpu-quota)
原理:Linux 使用 CFS(Completely Fair Scheduler)。通过两个参数控制: cpu.cfs_period_us (周期,微秒)和 cpu.cfs_quota_us (配额,微秒)
示例:限制容器为 50% 的一个 CPU
docker run -itd --name test6 --cpu-quota 50000 centos:7 /bin/bash
解释:50000 / 100000 = 0.5 → 相当于 0.5 个 CPU(即 50% 的单核)。
另一种更直观的写法:
docker run -itd --name cputest --cpus="0.5" centos:7 /bin/bash
# --cpus=0.5 是 --cpu-quota /--cpu-period 的友好封装(要求较新版本 Docker)。
1.2.4 设置 CPU 占用比(权重 — – cpu shares )
原理:–cpu-shares 指定相对权重(默认 1024),仅在 CPU 争用时生效(不是硬限制)。
举例:两个容器 c1、c2,–cpu-shares 512 与 –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 -c N)后用 docker stats 观察 CPU % 倾向于 1:2(随系统负载和核心数而变化)
1.2.5 绑定指定 CPU(- cpuset cpus )
用途:把容器进程绑定到宿主机的指定 CPU 核上(硬亲和性)。
示例:将容器绑定到第 1 和第 3 个核
docker run -itd --name test7 --cpuset-cpus "1,3" centos:7 /bin/bash
验证:在宿主机运行 top 或 htop (按 1)查看各核利用率,或进入容器运行 taskset -p <pid> 。
1.2.6 压力测试与验证示例(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 # 产生四个进程,每个进程都反复不停的计算随机数的平方根
# 修改 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 # 设置配额(临时生效)
注意事项(CPU):
–cpu-shares 是权重,不是限额。
–cpu-quota /–cpu-period 是硬限制(quota = -1 表示无限制)。
使用 –cpuset-cpus 能提高性能稳定性(避免与其他进程抢核)。
在多核宿主机上理解 quota/period 的含义(单位是 “相对于 1 个 CPU 的份额”)。
1.3 内存使用限制
基础选项
-m, –memory :限制容器可用的物理内存(例如 :-m 512m)
–memory-swap: 限制容器可用的物理内存 + swap 总量 (必须与-m一起使用以明确swap上限)
1.3.1 — memory 与 — memory-swap 规则
示例:-m 300m --memory-swap=1g
含义:容器可用物理内存 = 300 MB;物理 + swap 总共 = 1 GB → swap 可用 = 700 MB(1G - 300M)。
默认行为:若不设置 --memory-swap ,通常容器可使用的 swap 为 -m 值的两倍(行为可能随Docker 版本/配置变化)。
若 --memory-swap = -1 :swap 不受限制(宿主机可用多少 swap 就用多少)。
若 --memory-swap = -m :容器不能使用 swap(物理内存用尽会触发 OOM)。
OOM 行为:如果容器超过允许内存且没有 swap 或无更多内存可用,会被内核 OOM killer 杀掉。
可查看容器日志与 dmesg 来确认 OOM 事件。
示例命令
docker run -itd --name test8 -m 512m centos:7 /bin/bash
# 或者设置 swap 总额
docker run -itd --name test8b -m 300m --memory-swap=1g centos:7
# 验证与观察
使用 docker stats 观察 MEM USAGE / LIMIT。
在宿主机查看 cgroup:
cd /sys/fs/cgroup/memory/docker/<container-id>/
cat memory.limit_in_bytes
cat memory.usage_in_bytes
建议与注意
为生产服务设置合理内存限制,避免单容器把宿主机内存耗尽。
对于内存敏感的应用,建议同时设置 -m 与 –memory-swap ,并配合健康检查/重启策略。
在 cgroup v2 环境下内存控制文件名/行为可能与 v1 略有不同(检查 /sys/fs/cgroup 结构)。
1.4 磁盘 IO(blkio / io)控制
说明
Docker 提供对块设备读写带宽与 IOPS 的限制选项(基于 cgroups 的 blkio 控制器)。
注意:在 cgroup v2 中,blkio 功能被 io 控制器取代,语义与文件名有所不同(如果你运行的是 较新内核/系统,请参考对应 cgroup 版本文档)
1.4.1 常用 Docker 参数(blkio)
--device-read-bps /dev/sda:1M :限制设备上读速率为 1 MB/s。
--device-write-bps /dev/sda:1M :限制写速率为 1 MB/s。
--device-read-iops /dev/sda:100 :限制读 IOPS(次数)。
--device-write-iops /dev/sda:100 :限制写 IOPS(次数).
示例
docker run -it --name test10 --device-write-bps /dev/sda:1MB centos:7 /bin/bash
验证(用 dd测试写速)
在容器内执行写入测试,使用 oflag=direct 跳过文件系统缓存:
dd if=/dev/zero of=test.out bs=1M count=10 oflag=direct
输出示例说明:
10485760 bytes (10 MB) copied, 10.0025 s, 1.0 MB/s → 写速被限为约 1 MB/s
1.4.2 清理 Docker 占用的磁盘空间
# 清理未使用的数据(可释放磁盘空间):
docker system prune -a
该命令会删除停止的容器、未使用的镜像、未使用的网络和构建缓存(要谨慎使用,会删除很多资源)。
常见命令速查(快速摘录)
总结命令 资源限制
# CPU
docker run -itd --name c1 --cpu-shares 512 centos:7
docker run -itd --name c2 --cpu-quota 50000 centos:7
docker run -itd --name c3 --cpuset-cpus "1,3" centos:7
docker run -itd --name c4 --cpus="0.5" centos:7
# 内存
docker run -itd --name memtest -m 512m centos:7
docker run -itd --name memtest2 -m 300m --memory-swap=1g centos:7
# blkio
docker run -it --name iotest --device-write-bps /dev/sda:1MB centos:7
# 监控/验证
docker stats
docker exec -it <container> bash
cat /sys/fs/cgroup/cpu/docker/<container-id>/cpu.cfs_quota_us
cat /sys/fs/cgroup/memory/docker/<container-id>/memory.limit_in_bytes
# 清理
docker system prune -a
二、数据卷容器:实现数据的“持久化”与“共享”
Docker容器中的数据默认存储在容器的可写层,当容器被删除时,数据也会随之丢失。数据卷(Volume)是Docker提供的独立于容器的数据存储机制,可实现数据持久化;而数据卷容器则是专门用于共享数据卷的容器,能让多个容器便捷地共享数据。
2.1 核心优势
数据独立于容器,容器删除后数据仍保留在宿主机。
多个容器可挂载同一个数据卷容器,实现数据共享与同步。
支持宿主机目录与容器目录映射,方便宿主机直接操作容器数据。
2.2 实操示例
步骤1:创建数据卷容器
docker run --name web2 -v /data1 -v /data2 -it centos:7 /bin/bash
–name web2 : 给容器命名为 web2 。-
v /data1 -v /data2: 在容器内部挂载了两个数据卷 /data1 和 /data2。这些数据卷不依赖宿主机,而是仅仅存在于容器内。
.步骤2: 在数据卷容器中写入数据
进入 web2 容器后,可以在 /data1 和 /data2 目录下写入数据:
echo "this is web2" > /data1/abc.txt
echo "THIS IS WEB2" > /data2/ABC.txt
步骤.3 使用 – volumes from 共享数据卷
创建一个新的容器 web3 ,并通过 –volumes-from 选项将web2 容器中的数据卷挂载到web3 容器中:
docker run -it --volumes-from web2 --name web3 centos:7 /bin/bash
最后,在新容器中查看数据:
cat /data1/abc.txt
cat /data2/ABC.txt
输出如下
this is web2
THIS IS WEB2
三、端口映射:打通容器与外部的“通信通道”
Docker容器默认处于独立的网络命名空间中,外部无法直接访问容器内的服务。端口映射功能可将容器内的服务端口映射到宿主机的端口上,使外部通过宿主机IP+端口就能访问容器内的服务。
3.1 映射方式
随机端口映射:Docker自动分配宿主机的空闲端口映射到容器指定端口。
指定端口映射:手动指定宿主机端口映射到容器指定端口(常用)。
3.2 实操示例
示例1:指定端口映射(将Nginx容器的80端口映射到宿主机的8080端口)
# 语法:docker run -d --name 容器名 -p 宿主机端口:容器端口 镜像名
docker run -d --name nginx-mapped -p 8080:80 nginx:latest
验证:在浏览器中访问 ,可看到Nginx默认页面。
http://宿主机IP:8080
示例2:随机端口映射(将Tomcat容器的8080端口随机映射到宿主机端口)
# 语法:docker run -d --name 容器名 -P 镜像名(-P为大写,自动映射容器暴露的端口)
docker run -d --name tomcat-random -P tomcat:latest # 查看映射的端口(通过docker ps可看到PORTS列,如0.0.0.0:32768->8080/tcp)
docker ps
四、容器互联:实现容器间的“内网通信”
在实际应用中,多个容器常需要协同工作(如Web容器与数据库容器),容器互联功能可让同一宿主机内的容器通过容器名或别名进行通信,无需依赖宿主机IP,简化了容器间的网络配置。
4.1 实现方式
–link参数:传统的互联方式,可在一个容器中直接通过容器名访问另一个容器。
Docker网络:创建自定义网络,将容器加入该网络,容器间可通过容器名或别名通信(推荐,功能更强大)。
4.2 实操示例
首先,创建并运行源容器 web1 ,它将作为通信的源容器。使用 CentOS 镜像启动容器,并让容器在后 台运行:
docker run -itd -P --name web1 centos:7 /bin/bash
-itd : 启动容器并使其在后台运行。
-P : 随机映射容器的端口到宿主机。
--name web1 : 给容器指定一个名称 web1 。
centos:7 : 使用 CentOS 7 镜像启动容器。
/bin/bash : 启动后进入容器的 bash shell。
接下来,创建并运行接收容器 web2 ,并使用 –link 选项来连接容器 web1 ,从而实现容器间的通信
docker run -itd -P --name web2 --link web1:web1 centos:7 /bin/bash
--link web1:web1 : 通过 --link 选项连接 web1 容器,将 web1 容器暴露给web2 容器,并在web2中将web1容器 显示为别名web1;这样 web2 容器就可以通过 web1 访问源容器的信息。
在接收容器 web2 中测试连接
进入容器 web2 ,然后尝试 ping web1 容器,验证是否可以与 web1 容器通信:
docker exec -it web2 bash
ping web1
**docker exec -it web2 bash**: 进入 web2 容器的 bash 环境。
**ping web1**: 测试 web2 是否能与 web1 通信。
结果:ping命令可正常执行,说明两个容器已成功互联。
五、镜像创建:打造专属的“容器模板”
Docker镜像是容器的基础,包含了运行应用所需的代码、依赖、环境变量等。除了使用Docker Hub上的官方镜像,我们还可以根据自身需求创建自定义镜像,常用方式有两种:通过docker commit命令基于容器创建,以及通过Dockerfile文件构建(推荐,可复现、易维护)。
5.1 两种创建方式对比
|
创建方式 |
优势 |
劣势 |
|---|---|---|
|
docker commit |
操作简单,可快速基于现有容器创建 |
镜像分层不清晰,无法复现构建过程,易产生冗余 |
|
Dockerfile构建 |
语法简洁,构建过程可复现,镜像分层清晰,易维护 |
需编写Dockerfile文件,对新手有一定门槛 |
5.2 实操示例
示例:通过Dockerfile构建一个自定义Nginx镜像(添加自定义首页)
步骤1:创建工作目录并编写Dockerfile
# 创建工作目录 mkdir -p my-nginx && cd my-nginx # 编写自定义首页(index.html) echo "<h1>My Custom Nginx</h1>" > index.html # 编写Dockerfile cat > Dockerfile << EOF # 基础镜像(基于官方Nginx镜像) FROM nginx:latest # 作者信息 MAINTAINER test@example.com # 将自定义首页复制到容器的Nginx默认目录 COPY index.html /usr/share/nginx/html/ # 暴露80端口 EXPOSE 80 # 启动Nginx服务(与官方镜像一致) CMD ["nginx", "-g", "daemon off;"] EOF
步骤2:构建自定义镜像
# 语法:docker build -t 镜像名:标签 构建上下文目录(.表示当前目录) docker build -t my-nginx:v1.0 .
说明:构建过程中,Docker会按Dockerfile中的指令逐步执行,生成新的镜像。
步骤3:基于自定义镜像创建容器并验证
# 创建容器并映射8090端口 docker run -d --name my-nginx-container -p 8090:80 my-nginx:v1.0
验证:访问 ,可看到自定义的首页内容“<h1>My Custom Nginx</h1>”。
http://宿主机IP:8090
六、总结
本文介绍的Docker核心功能——资源限制、数据卷容器、端口映射、容器互联、镜像创建,覆盖了容器从创建、运行到数据管理、通信、定制化的全流程。资源限制保障了系统稳定性,数据卷容器实现了数据持久化与共享,端口映射打通了容器与外部的通信,容器互联简化了容器间协作,镜像创建则让我们能打造专属容器模板。
熟练掌握这些功能,能帮助我们更高效地使用Docker,应对不同的业务场景,提升容器化部署与运维的效率。后续可进一步深入学习Docker的高级特性(如Docker Compose、Docker Swarm),实现更复杂的容器集群管理。



