Dockerfile 中的Volume有什么意义,光用docker run -v效果相同吗?

Dockerfile 中有一个 VOLUME 命令,可以把挂载一个目录到主机目录,但是在主机目录下的名字是随机的,除非用户用 -v 指定,但是如果在 Dockerfile 中不用 VOLUME,只在运行时用 -v 指定也能达到效果,那么就有一个问题,VOLUMEDockerfile 中到底有多少用,在 Host 下创建了几个用户一般找不到的文件到底有多少使用价值,大部分情况下用户都是要手动使用 -v 重新指定挂载目录,那 VOLUME 命令就显得很鸡肋。

VOLUME 是否有什么比较重要的用处我没有理解呢?

阅读 43.9k
4 个回答

我也对此有些疑问,所以找了一些资料,说下我的看法。

找到了官方的userguide: https://docs.docker.com/engine/userguide...

从中了解了一点:VOLUME并非只是声明,它会把指定路径重新加载一遍,我通过inspect容器也发现了这一点。

这是在Dockerfile指定了VOLUME,并没有指定-v,查看容器的Mounts信息:

"Mounts": [
        {
            "Name": "b3e2dcacd3f9f40b43ccd5773d45ca74f0f49b02d3da17749cb378ff9f59bb67",
            "Source": "/var/lib/docker/volumes/b3e2dcacd3f9f40b43ccd5773d45ca74f0f49b02d3da17749cb378ff9f59bb67/_data",
            "Destination": "/etc",
            "Driver": "local",
            "Mode": "",
            "RW": true
        }
    ],

这是在上一个的基础上,指定了-v,查看容器的Mounts信息:

 "Mounts": [
        {
            "Source": "/etc",
            "Destination": "/etc",
            "Mode": "",
            "RW": true
        }
    ],

然后你去/var/lib/docker/volumes/b3e2dcacd3f9f40b43ccd5773d45ca74f0f49b02d3da17749cb378ff9f59bb67/_data目录下看一下,大致就清楚了。

你可以把VOLUME理解为,从镜像中复制指定卷的文件夹到本地/var/lib/docker/volumes/xxxxxxxxx/文件夹,然后把本地的该文件夹挂载到容器里面去。

本质上还是相当于一个本地文件夹挂载而已。

继续补充,因为VOLUME实际上就是在本地新建了一个文件夹挂载了,那么实际上容器内部的文件夹有三种情况:
1、没有指定VOLUME也没有指定-v,这种是普通文件夹。
2、指定了VOLUME没有指定-v,这种文件夹可以在不同容器之间共享,但是无法在本地修改。
3、指定了-v的文件夹,这种文件夹可以在不同容器之间共享,且可以在本地修改。

那就列举一种需要在不同容器之间共享且不需要在本地修改的情况。

首先,我们先了解容器中获取动态数据的方式:
1、本地提供,挂载到容器
2、远程提供,从远程下载
3、生成提供,在容器内部生成

后面两种命令都不需要在本地修改,但是他们生成的动态数据却可能需要共享。
下载命令,比如git clone直接从git服务器拉取代码,不需要挂载本地文件夹。
生成命令,比如jekyll(静态网站生成器),你可能挂载一个代码文件夹,然后build目录里生成的静态网页文件需要提供给Apache服务器,那么你需要指定build目录为VOLUME。

VOLUME 命令主要是在开发环境下非常有用:

  1. 编辑代码的时候,直接在宿主机里进行编辑,然后在 docker 里同步跑,无需反复启动关闭,这能发挥开发环境的最高性能。

  2. 对于 VOLUME 我更喜欢使用 docker-compose 进行指定:

db:
  image: postgres
web:
  build: .
  command: python manage.py runserver 0.0.0.0:8000
  volumes:
    - .:/code
  ports:
    - "8000:8000"
  links:
    - db

docker-compose 可以将多个服务进行捆绑了跑,上面的示例就是 web 服务和 db 服务分开来跑,非常适合组建复杂的环境。

年代久远啊,致敬前辈....当前版本docker-ce-17.12

docker数据共享有2种方式:
一种是: volume, 操作符号: -v 或 --volume。 官网:使用 volume
另一种是:bind mount, 操作符号: --mount。 官网:使用 bind mount

volume方便统一管理,不能自定义主机共享目录。
bind mount 不好管理,但是能自定义主机共享目录,开发编码推荐

-v 和 --mount 可以实现挂载volume 也可以实现 bind mount。有些命令只支持这个。

docker run -v /home/user/works/:/home/docker/container/works
和
docker run --mount source=/home/user/works/,target=/home/docker/container/works

这2个命令一样的,都是bind mount 方式,自定义挂载目录。 

docker run -v  volume_name:/home/docker/container/works
和
docker run --mount source=volume_name,target=/home/docker/container/works

这2个命令也是一样的, 都是 volume 方式。

楼上对挂载得理解是不是有什么偏差……
Docker可以通过数据卷(volume)与捆绑挂载(bind-mount)两个方式与外部共享数据。
不管是数据卷还是捆绑挂载,都可以和本机共享目录。但是前一种方法需要提前创建一个数据卷容器,略麻烦一些。

Docker run命令参数-v和--mount都是挂载,也都可以对数据卷和捆绑挂载进行操作。Docker官方没有推荐使用-v还是--mount,只是说-v要短很多。非要说推荐的话,Docker官方推荐使用数据卷而非捆绑挂载。只有在三种情况下才建议使用捆绑挂载。

lz的问题是Dockerfile里的VOLUME命令,这个命令实际上跟在docker run -v创建一个捆绑挂载一样。它会在/var/lib/docker/volumes/目录下随机创建一个文件夹,然后把容器内的镜像和这个文件夹进行捆绑挂载。个人感觉没什么卵用,虽然说由这一个Dockerfile创建的多个容器会共享同一个目录,能让他们之间共享文件……但是明明有更优雅的方式不是么?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏