文章

Docker挂载之谜:为什么我的媒体目录内容会丢失

Docker挂载之谜:为什么我的媒体目录内容会丢失

背景介绍

Docker的volume功能允许我们在启动容器时,动态挂载一些文件(如配置文件),以覆盖镜像中原有的文件。但如果你挂载一个在主机上尚不存在的文件夹或文件到容器中,会发生什么呢?本文将详细探讨这一问题,并记录实验结果。

文件夹加载

Docker文件夹挂载行为

Docker在文件夹挂载上的行为是统一的,具体如下:

  1. 若文件夹不存在,则先创建出文件夹(若为高层文件夹,则高层创建)。
  2. 用主机上的文件夹内容覆盖容器中的文件夹内容。

详细说明

主机上文件夹存在,且非空

主机 容器 挂载结果
存在的非空文件夹A 不存在的文件夹B 先在容器中创建文件夹B,再将A文件夹中的所有文件复制到B中
存在的非空文件夹A 存在的非空文件夹B 先将容器中文件夹B的原有内容清空,再将A中文件复制到B中

结论:无论容器中的文件夹B是否存在,A都会完全覆盖B的内容。

主机上文件夹存在,但为空

主机 容器 挂载结果
存在的空文件夹A 存在的非空文件夹B 容器中文件夹B的内容被清空

结论:容器中对应的文件夹内容被清空。

主机文件夹不存在

主机 容器 挂载结果
不存在的文件夹A 存在的非空文件夹B 在主机上创建文件夹A,容器文件夹中B的内容被清空
不存在的文件夹A/B/C 存在的非空文件夹B 在主机上创建文件夹A/B/C,容器中文件夹B的内容被清空

结论:容器中对应的文件夹内容被清空。

文件夹总结

主机上文件夹一定会覆盖容器中文件夹:

主机 容器 挂载结果
文件夹不存在/文件夹存在但为空 文件夹不存在/存在但为空/且存在不为空 容器中文件被覆盖(清空)
文件夹存在且不为空 文件夹不存在/存在但为空/且存在不为空 容器中文件夹内容被覆盖(原内容清空,覆盖为主机上文件夹内容)

文件挂载

文件挂载与文件夹挂载的区别

  1. Docker禁止用主机上不存在的文件挂载到容器中已经存在的文件。
  2. 文件挂载不会对同一文件夹下的其他文件产生任何影响。

详细说明

主机上文件不存在

主机 容器 挂载结果
不存在的文件configA.js 已经存在的文件configB.js 报错,提示检查主机路径是否存在且为预期类型。同时会在主机上生成两个空目录configA.js和configB.js,但容器无法启动

主机上文件存在

主机 容器 挂载结果
存在的文件configA.js 存在的文件configB.js 容器中文件名configB.js保持不变,但文件内容被configA.js的内容覆盖
存在的文件configA.js 不存在的configB.js 容器中新建一个文件configB.js,其内容为configA.js的文件内容,configB.js所在文件夹下的所有其他文件保持不变

文件总结

主机上文件一定会覆盖容器中文件:

主机 容器 挂载结果
不存在的文件 已经存在的文件 禁止行为
存在的文件 不存在的文件/已经存在的文件 新增/覆盖(若目录不存在则创建目录)

结论

文件夹加载

  1. 允许不存在的文件夹或者存在的空文件夹挂载进容器,容器中对应的文件夹将被清空。
  2. 非空文件夹挂载进容器将覆盖容器中原有文件夹。

文件加载

  1. 禁止将不存在的文件挂载到容器中已经存在的文件上。
  2. 存在的文件挂载进容器中将会覆盖容器中对应的文件,若文件不存在则新建。

应用场景

  • 文件夹挂载:适用于需要将大量文件挂载进容器的情况。挂载空文件夹或不存在的文件夹常用于逆向使用,如在容器内生成日志文件,主机上可直接查看。
  • 文件挂载:常用于挂载配置文件,以在运行时动态修改默认配置。

希望本文能帮助你更好地理解Docker的挂载行为,避免在实际操作中遇到类似的问题。

本文由作者按照 CC BY 4.0 进行授权