Docker Swarm更新时卷行为与磁盘占用过高问题咨询
Docker Swarm部署中「设备空间不足」问题排查与疑问
问题现象
在Docker Swarm集群通过CI/CD部署应用时,频繁触发「设备空间不足」错误,但所有镜像大小均小于500MB,服务器初始存储占用也不多。
排查操作
执行以下命令定位空间占用:
sudo du -a -h / | sort -n -r | head -n 5
输出结果:
5G /var/lib/docker/overlay2/ec1a3324f4cb66327ff13907af28b101ab15d1a0a27a04f0adedf50017f1612e/merged/etc 6G /var/lib/docker/overlay2/98f9e5f2c28a7ee7972cadfeaa069210238c06b5f806c2f5e039da9d57778817/merged/etc 2G /var/lib/docker/overlay2/7fe5364228810e035090c86448b5327150f7372c9d2216b8ab4f8c626e679ba0/merged/etc 1G /var/lib/docker/overlay2/5f80f0b1a72b83553c9089a54226c260b2e695dbba69b9e06ecc18fc18e3d107/merged/etc
发现/var/lib/docker/overlay2目录占用大量空间,随后执行清理命令:
docker system prune -a -f --volumes
核心疑问
- 怀疑部署新服务实例时,卷挂载切换到新容器后,旧容器仍向自身文件系统写入数据,导致overlay2目录膨胀。想明确Docker Swarm部署新镜像时,卷的实际行为:是否会断开旧节点的卷映射并连接到新容器,进而导致旧实例写入自身文件系统?
- 配置中
myApp.deploy.update_config.order: start-first是否是问题诱因? - 如何避免此类空间占用问题?
附deploy-stack.yml配置示例
version: "3.9" services: myApp: image: myRepo/myApp:latest depends_on: - db volumes: - /var/data/uploads:/app/uploads - /var/data/logs:/app/logs deploy: replicas: 1 update_config: parallelism: 1 order: start-first failure_action: rollback monitor: 30s restart_policy: condition: any ports: - "80:80" db: image: "postgres:15beta3-alpine" container_name: db_pg environment: POSTGRES_PASSWORD: XXXXXXXXXXXX PGDATA: /var/lib/postgresql/data volumes: - /var/data/db_pg:/var/lib/postgresql/data deploy: replicas: 1 update_config: parallelism: 1 failure_action: rollback monitor: 30s restart_policy: condition: any seq: image: datalust/seq:latest environment: ACCEPT_EULA: "Y" SEQ_FIRSTRUN_ADMINPASSWORDHASH: XXXXXXXXXXXXXXX ports: - 8888:80 volumes: - /var/data/seq:/data deploy: replicas: 1 update_config: parallelism: 1 failure_action: rollback monitor: 30s restart_policy: condition: any networks: default: external: true name: app-network
问题解答
1. Docker Swarm更新时的卷行为
你使用的是绑定挂载(主机目录直接映射到容器),而非Docker管理的命名卷。这种场景下:
- 新容器启动时会直接挂载主机上的
/var/data/uploads、/var/data/logs等目录,和旧容器共享同一主机目录资源,不存在「断开旧映射连新容器」的情况——旧容器的挂载依然有效,新旧容器会同时读写同一个主机目录。 - 只有当应用写入路径未正确指向挂载目录(比如代码写死向容器内
/app/logs写入,但挂载配置失效),才会导致数据写入容器自身的overlay2层,进而撑大空间。
2. start-first是否是诱因
是的,start-first是关键诱因之一:
- 默认更新顺序为
stop-first:先停止旧容器,再启动新容器。而start-first会先启动新容器,等新容器健康后再停止旧容器。 - 新旧容器共存期间,如果应用有大量写入操作(比如日志、临时文件)且部分写入未落到绑定挂载目录,会同时在两个容器的overlay2层产生数据,短时间内快速消耗磁盘空间。
- 若旧容器停止后未被及时清理(比如Swarm垃圾回收延迟),残留的overlay2层数据会持续占用空间。
3. 避免空间问题的措施
- 修正应用写入路径:确保所有持久化数据(日志、上传文件)的写入路径完全对应绑定挂载目录,禁止向容器内未挂载路径写入大量数据。
- 调整更新顺序:若应用允许短时间停机,将
update_config.order改回stop-first,避免新旧容器共存期间的双重写入。若必须用start-first,缩短monitor时间,确保旧容器能被快速停止清理。 - 开启Docker自动垃圾回收:配置Docker的
--storage-opt dm.min_free_space设置最低剩余空间阈值,或启用Swarm自动清理:
限制任务历史数量,旧容器会被更快清理。docker swarm update --task-history-limit 1 - 定期清理overlay2残留:在CI/CD流程中添加轻量清理步骤(避免
prune -a误删有用镜像):docker system prune -f --filter "until=24h" - 监控磁盘占用:给服务器配置磁盘告警,当空间占用超过80%时触发通知,提前处理。
内容的提问来源于stack exchange,提问作者user3620691
相关产品推荐
相关产品推荐

