关于使用docker volume挂载的注意事项
Content
在用Docker进行持久化的存储的时候,有两种方式:
使用数据卷(volume
)
-v 容器绝对路径
或者
-v 已经创建的volume名称:容器绝对路径
使用挂载点(共享宿主目录,bind mount
)
-v 宿主绝对路径:容器绝对路径
由于两种方法都可以使用-v
和--mount
参数,但是实际上两种方式的行为区别非常大。
目录兼容性
volume
只能映射容器的目录,而bind mount
方式可以是目录也可以是文件。
可移植性
volume
的文件系统由docker进行管理,对不同系统都可以通用兼容;bind mount
需要指定绝对路径,不同的操作系统,对路径的表述是有区别的,往往无法实现互通。
目录替代相关
如果使用volume,那么容器内的文件会被保留在volume中(对应的_data
文件夹)内部,也就是文件被复制到宿主机器上;使用bind mount时,如果宿主文件夹是空的,不光容器内的文件不会被复制到宿主机器上,容器的内容还会被覆盖为空,对于一些容器内路径文件夹存放config文件的情况,宿主目录为空会导致容器内的对应目录被清空,造成启动错误的问题。(详细对比可以看这篇文章)。
当然,映射完成之后,不管是哪一方面新建文件,都可以正常的反映到另一方的。
在宿主文件不为空的情况下,都会覆盖容器路径的文件。
指定位置
使用volume
不能指定的volume
存在的位置,这个是由docker管理的(默认/var/lib/docker/volumes/
),可以通过docker的daemon.json
文件进行配置,详情可以翻翻之前我写的文章;而使用bind mount的情况则必须指定位置。
--volume与--mount区别
在创建bind mount
的时候,使用--volume会自动创建宿主方的文件夹,而--mount不会,因此使用--mount映射不存在的目录,会报错。
镜像保存
之前写过一篇有关于docker export import相关的文章,想着是运行时候增加的配置文件等内容,可以直接保留。后来发现,不管是volume
还是bind mount
,两种方式都无法将文件保存到镜像中,因此需要进行单独的文件保存工作。
docker-compose
docker-compose指定的时候,有一些区别:
- 使用bind mount的时候,宿主这边可以使用相对路径了(./),不需要显示指定($PWD)
- 可以在指定volume名称的同时创建volume,需要使用
volume:
的配置项
podman兼容性
在CentOS类的发行版中,从8开始,已经使用podman
替代了docker
,直接安装docker的情况下会默认安装podman,并且将docker命令全部替换成podman命令,大多数命令是通用的。有几个地方需要注意:
- podman是无deamon程序的,也就是没有一个专门的守护进程,因此运行的权限要求也更低,存档volume的位置有区别,使用更加方便。
- podman使用-v进行bind mount时,如果宿主机器目录不存在,那么podman会直接报错,而不会自动创建文件。
实践指南
- 使用
docker-compose
创建可以移植的系统,请使用volume。 - 使用docker export方式导出文件的情况下,记住单独保存映射的volume或者bind mount。
- 如果替换某一个具体配置文件,只能使用bind mount形式;否则,建议使用volume,因为这样能够将容器内已经有的目录复制到volume中,防止空文件夹覆盖容器对应文件夹导致容器启动错误。
- 为了保障对
podman
的兼容性,请先创建宿主机需要mount的文件夹。 - 【不建议】实现bind mount形式在linux与windows下的兼容性,windows下的docker desktop可以正确解析
/c/windows
这样的路径,在linux下只需要创建相同的目录结构就也可以实现的文件绝对路径在不同系统的一致性。