Docker 容器资源限制,防止被恶意占用
为什么需要限制容器资源?
当多个容器共享一台服务器时,
单个容器可能因程序Bug或恶意代码无限占用CPU、
内存、
磁盘,
导致其他服务瘫痪甚至主机死机。Docker容器资源限制是防止被恶意占用的第一道防线,
通过给每个容器设定资源上限,
确保一台机器的资源被公平分配。
准备工作
- 已安装Docker(版本不低于19.03,cgroup v2需20.10+)
- 拥有sudo或root权限
- 一个测试容器(如nginx:alpine)用于验证
核心操作:限制CPU和内存
1. 通过docker run参数限制
最直接的方式是在启动容器时加入资源参数:
docker run -d --name myapp \
--memory=512m \
--memory-swap=1g \
--cpus=1.5 \
nginx:alpine
--memory=512m:容器最多使用512MB内存。--memory-swap=1g:内存+swap总上限为1GB,超过则OOM杀死进程。--cpus=1.5:容器最多使用1.5个CPU核心(按100%利用率计算)。
2. 用Docker Compose管理
在docker-compose.yml的deploy.resources段配置:
version: '3.8'
services:
web:
image: nginx:alpine
deploy:
resources:
limits:
cpus: '1.5'
memory: 512M
reservations:
cpus: '0.5'
memory: 128M
reservations表示预留资源,swarm模式下自动生效;
单机使用docker-compose up时也遵循limits。
限制磁盘读写与容量
限制磁盘IO
给容器设置读写带宽上限,防止一个容器把磁盘IO占满:
docker run -d --name app \
--device-read-bps /dev/sda:50mb \
--device-write-bps /dev/sda:30mb \
--device-read-iops /dev/sda:1000 \
--device-write-iops /dev/sda:800 \
nginx:alpine
/dev/sda需改为实际磁盘设备名,可用lsblk查看。bps限制每秒字节数,iops限制每秒操作次数。
限制容器磁盘大小(使用overlay2)
Docker默认使用overlay2存储驱动,可通过--storage-opt限制容器可写层大小:
docker run -d --name size-limited \
--storage-opt size=10G \
nginx:alpine
容器可写层最多10GB,超出后无法写入新文件。注意: 此功能依赖存储驱动版本,Docker 20.10+没问题。
限制进程数:防止进程爆炸
一个恶意脚本可能大量fork进程耗尽服务器资源。
用--pids-limit限制容器内最大进程数:
docker run -d --name safe-app \
--pids-limit 100 \
nginx:alpine
如果容器内进程数超过100,fork将返回Resource temporarily unavailable。
效果验证与常见问题
验证限制是否生效
- 查看实时资源使用:
docker stats显示所有容器的CPU、内存、IO等。 - 压力测试内存: 在容器内运行
stress --vm 1 --vm-bytes 600M,若超过512M会被OOM kill。 - 验证IO限制: 容器内执行
dd if=/dev/zero of=/tmp/test bs=1M count=500,观察docker stats的磁盘IO是否被限。
常见避坑
- swap注意事项:
--memory-swap不设置时默认为--memory的两倍,如果不想让容器用swap,可设为--memory-swap=0(需Docker 20.10+)。 - cgroup版本问题: 新系统(如Ubuntu 22.04)默认cgroup v2,某些旧参数可能不支持,升级Docker到最新版即可。
- 磁盘设备名: 在云服务器上可能是
/dev/vda或/dev/xvda,务必先用lsblk确认。 - overlay2 size限制不被所有存储驱动支持: 如果用
devicemapper则无效,建议统一使用overlay2。
配置完以上限制后,即使容器内跑恶意程序也无法突破设定的上限,服务器稳定性大幅提升。
建议结合实际业务,从保守值开始逐步微调。