「Docker」关于 Docker volume 挂载时文件或文件夹不存在的问题

摘要:
背景:Dockervolume允许我们在启动Docker容器时动态装载一些文件以覆盖图像中的原始文件。然而,当我们将主机上不存在的文件夹或文件装载到容器时会发生什么?由于文件装载仅覆盖单个文件,而不会影响容器中同一文件夹中的其他文件,因此通常用于装载配置文件,以在运行时动态修改默认配置。如果您尝试提前在主机/文件夹路径/A中放置一些内容,您会发现在容器启动后,原始文件和容器启动后生成的文件共存。

背景介绍

docker volume 可以使我们在启动docker容器时,动态的挂载一些文件(如配置文件), 以覆盖镜像中原有的文件,但是,挂载一个主机上尚不存在的文件夹或者文件到容器中会怎样呢?这里特意做了一下实践,记录实验结果如下:

文件夹挂载

docker在文件夹挂载上的行为是统一的,具体表现为:

  • 若文件夹不存在,则先创建出文件夹(若为多层文件夹,则递归创建)
  • 用host上的文件夹内容覆盖container中的文件夹内容
docker run -v /path-to-folder/A:/path-to-folder/B test-image

详细说明如下:

host上文件夹存在,且非空

hostcontainermount result
存在的非空文件夹A不存在的文件夹B先在contanier中创建文件夹B,再将A文件夹中的所有文件copy到B中
存在的非空文件夹A存在的非空文件夹B先将container中文件夹B的原有内容清空,再将A中文件copy到B中

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

host上文件夹存在,但为空

hostcontainermount result
存在的空文件夹A存在的非空文件夹Bcontainer中文件夹B的内容被清空

container中对应的文件夹内容被清空

host上文件夹不存在

hostcontainermount result
不存在的文件夹A存在的非空文件夹B在host上创建文件夹A,container中文件夹B的内容被清空
不存在的文件夹A/B/C存在的非空文件夹B在host上创建文件夹A/B/C,container中文件夹B的内容被清空

container中对应的文件夹内容被清空

总结

host上文件夹一定会覆盖container中文件夹:

hostcontainermount result
文件夹不存在/文件夹存在但为空文件夹不存在/存在但为空/存在且不为空container中文件被覆盖(清空)
文件夹存在且不为空文件夹不存在/存在但为空/存在且不为空container中文件夹内容被覆盖(原内容清空, 覆盖为host上文件夹内容)

文件挂载

文件挂载与文件夹挂载最大的不同点在于:

  • docker 禁止用主机上不存在的文件挂载到container中已经存在的文件
  • 文件挂载不会对同一文件夹下的其他文件产生任何影响

除此之外, 其覆盖行为与文件夹挂载一致,即:

  • 用host上的文件的内容覆盖container中的文件的内容
docker run -v /path-to-folder/non-existent-config.js:/path-to-folder/config.js test-image # forbidden

详细说明如下:

host上文件不存在

hostcontainermount result
不存在的文件configA.js已经存在的文件congfigB.js报错,Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. 同时会在host上生成两个空目录 configA.js 和 configB.js, 但是container无法启动

host上文件存在

hostcontainermount result
存在的文件configA.js存在的文件congfigB.jscontainer中文件名configB.js保持不变,但是文件内容被congfigA.js的内容覆盖了
存在的文件configA.js不存在的文件congfigB.jscontainer中新建一个文件configB.js,其内容为configA.js的文件内容, configB.js所在文件下的所有其他文件维持不变

总结

host上文件一定会覆盖container中文件夹

hostcontainermount result
不存在的文件已经存在的文件禁止行为
存在的文件不存在的文件/已经存在的文件新增/覆盖 (若目录不存在则会创建目录)

结论

文件夹挂载

  • 允许不存在的文件夹或者存在的空文件夹挂载进container, container中对应的文件夹将被清空
  • 非空文件夹挂载进container将会覆盖container中原有文件夹

文件挂载

  • 禁止将不存在的文件挂载进container中已经存在的文件上
  • 存在的文件挂载进container中将会覆盖container中对应的文件, 若文件不存在则新建

应用场景

  1. 从上面的分析可知,文件夹挂载以整个文件夹为单位进行文件覆盖,故可在需要将大量文件挂载进container时使用,另外,如果挂载一个空文件夹或者不存在的文件夹,一般是做逆向使用: 即容器启动后,可能会在容器内挂载点的文件夹下生成一些文件(如日志),此时,在对应的host上的文件夹内就能直接看到。
  2. 文件挂载由于只会覆盖单个文件而不会影响container中同一文件夹下的其他文件,常常被用来挂载配置文件,以在运行时,动态的修改默认配置。

特别注意

  1. 容器中类似mysql,redis这样的数据目录可以映射到宿主机目录的原因是,目录里的内容不是在容器启动前就存在的,而是在容器启动后生成的。如果试着在宿主机/path-to-folder/A中事先放一些东西,那么你会发现容器启动后,原来的文件和容器启动后生成的文件是并存的。

免责声明:文章转载自《「Docker」关于 Docker volume 挂载时文件或文件夹不存在的问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Oracle创建用户并给用户授权查询指定表或视图的权限谷歌浏览器中预览海康大华等监控视频的思路与方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

JS全局添加token

全局添加token var token = sessionStorage.getItem("UserTocken"); if(token){ $.ajaxSetup({ //发送请求前触发 beforeSend: function(xhr) { //可以设置自定义标头 xhr....

misconfiguration : kubelet cgroup driver: "systemd" is different from docker cgroup driver: "cgro

/* vim /etc/docker/daemon.json { "registry-mirrors": [ "https://a8qh6yqv.mirror.aliyuncs.com", "http://hub-mirror.c.163.com" ], "exec-opts": ["native.cgroupdriver=sy...

Docker-ce运用一:创建虚拟机

1、从远程仓库查看所需镜像 [root@localhost docker]# docker search centos8 NAME                                 DESCRIPTION                                     STARS               OFFICIAL     ...

SSM整合redis

准备工作: jedis连接 添加jar支持: <!--redis依赖 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</a...

25 Zabbix系统数据表结构介绍

点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 25 Zabbix系统数据表结构介绍自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表、Hosts_groups表、Interface表自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表自学Zabbix之...

(三)轻量级文件服务器filebrowser

既然资料都热备好了,那在外面还想看看资料,怎么办呢? 机器好的,上个nextcloud或者owncloud,我的需求只要能下载能上传即可,要不了那么多的功能,所以此处推荐一个轻量级文件服务器filebrowser。 filebrowser在GitHub上也有6.6K的star,虽然不维护了,但论基本功能却已足够。 依然是熟悉的docker化部署: 选择哪...