COW机制是运行时临时写入隔离策略,非持久化方案;它仅在容器生命周期内有效,删除容器后upperdir变更即丢失,必须通过Volume、Bind Mount或tmpfs显式挂载才能实现数据持久化。
容器层的 Copy-on-Write(COW)机制不是数据持久化方案,而是运行时临时写入的隔离策略。它只保证容器生命周期内的修改可见性,一旦容器删除,upperdir 里的所有变更就彻底丢失。想靠它存配置、日志或数据库文件,等于把数据放在易失内存里——看起来能写,实则毫无保障。
COW 是联合文件系统(如 overlay2)的底层行为:镜像所有层都是只读的,启动容器时动态叠加一个空的可写层(upperdir)。这个层专属于当前容器,不共享、不继承、不跨重启存活。
echo "x" > /app/config.txt)→ 触发复制:原始文件从某镜像层完整拷到 upperdir,再写入rm /var/log/app.log)→ 也触发复制:该文件被“白名单遮蔽”,实际仍占 upperdir 空间/tmp/cache → 各自 upperdir 独立,互不可见,也不影响镜像层这些操作看似在“存数据”,实则全部落在易失的容器层:
data/ 目录直接挂载在镜像内路径(如 /var/lib/mysql),没用 volume 或 bind mountdocker commit 把运行中容器的 upperdir 打包成新镜像——镜像体积暴增,且无法复用原有层缓存/app/logs/*.log),以为“文件还在”就是持久化了/etc/environment 或修改 /app/.env,期望下次 docker run 还在COPY 或 ADD 把运行时生成的证书、密钥塞进构建层——既不安全,也无法更新只有显式将路径映射到容器外,才能绕过 COW 的临时性限制:
/var/lib/docker/volumes/mydb/_data),适合数据库、缓存等需要 Docker 自动维护的场景-v /opt/myapp/conf:/app/conf:ro),适合配置热更新、开发调试--tmpfs /run/secrets),仅用于敏感临时数据,重启即清,不落盘关键原则:所有需保留的数据路径,必须在 docker run 或 docker-compose.yml 中明确声明挂载,不能依赖容器内默认路径。
别信“文件还在”,要动手验证:
docker stop myapp,再 docker rm myapp
docker run -d --name myapp ...,不加 --volumes-from 或 -v
docker exec -it myapp sh,检查原路径下数据是否还在——如果没了,说明此前完全依赖 COW,必须补挂载只要没显式挂载,容器重启或重建后,一切写入都归零。这不是 bug,是设计使然。