【问题标题】:Difference between VOLUME declaration in Dockerfile and -v as docker run parameterDockerfile 中的 VOLUME 声明和 -v 作为 docker run 参数之间的区别
【发布时间】:2016-10-20 19:34:39
【问题描述】:

谁能帮我理解以下之间的区别:

Dockerfile(图像构建层)中的VOLUME 命令

发出docker run-v/xyz/bla命令时的-v参数(容器构建层)。

-v 参数对我来说很清楚,它只是将一个目录从主机公开到容器,反之亦然,但是Dockerfile 中的VOLUME 的行为有何不同?

【问题讨论】:

    标签: docker dockerfile


    【解决方案1】:

    -v 参数和VOLUME 关键字几乎相同。您可以使用-v 来获得与VOLUME 相同的行为。

    docker run -v /data
    

    VOLUME /data
    

    而且 -v 还有更多用途,其中之一就是映射到卷的位置:

    docker run -v data:/data # Named volumes
    docker run -v /var/data:/data # Host mounted volumes, this is what you refer to -v use, but as you can see there are more uses,
    

    所以问题是:VOLUMEDockerfile 中有什么用?

    容器文件系统是由层组成的,所以写在那里,比普通文件系统慢且有限(因为层数固定)。

    您在 Dockerfile 中声明 VOLUME 以表示您的容器将写入应用程序数据的位置。例如一个数据库容器,无论你在docker run 中放入什么,它的数据都会进入一个卷中。

    如果你为 JBoss 创建了一个 docker 容器,并且你想通过 libaio 使用快速文件系统访问,你需要将数据目录声明为 VOLUME 否则 JBoss 将在启动时崩溃。

    总而言之,VOLUME 声明一个卷,无论您在 docker run 中做什么。事实上,在 docker run 中,您无法撤消在 Dockerfile 中所做的 VOLUME 声明。

    问候

    【讨论】:

    • 谢谢,只是为了确定,我的理解是,VOLUME 将在容器目录中创建一个新卷,就像使用 -v 时一样,无需指定主机上的路径。但是这个过程很慢,因此在某些情况下我不能使用 VOLUME 并且我必须使用 -v 因为我需要准确指定我想在主机上保存文件的位置,或者只是为了获得更好的性能。这就是你所说的总结,对吗?
    • 嗯,不。如果您定义了一个没有卷的容器并且您的应用程序在一个目录中写入了很多内容。这个过程不仅比在任何容器外运行应用程序要慢,而且容易出错。所以解决办法就是把这个目录声明为一个volume,这样就直接在文件系统中写入,就好像应用在容器外运行一样
    • 所以 VOLUME 路径参数是主机上的目录对吧?那么这意味着容器会将它的整个文件系统写入该目录吗?即,我会在那个指定的目录中找到 /root /boot /etc /var .......?
    • 否 VOLUME 路径参数是容器中的目录。例如/数据。 Docker 在主机中创建一个目录,用于将您在容器中写入的所有内容存储在 /data 目录中。检查 docker inspect 是否有正在运行的带有卷的容器。
    • 是的,这是与 -v 的区别,您可以确定目标或状态它将存储在命名卷中的内容。但是使用 VOLUME,您可以强制创建目录,无论用户使用 docker run 做什么
    【解决方案2】:

    简而言之

    Dockerfile 中的VOLUME [PATH] 指令相当于

    $ docker run -v $(docker volume create):[PATH] [IMAGE_NAME]
    

    详解

    容器文件系统由层组成,因此与普通文件系统相比,在其中写入速度较慢且受限(因为层数固定)。

    在 Docker 中使用卷主要不是速度问题,而是独立于容器生命周期的数据持久性问题。 从更快的磁盘挂载卷显然会提高性能,但 Docker 的默认行为VOLUME 是在主机系统上创建一个命名卷,与容器的可写层相比,速度几乎没有提高。

    -v 参数对我来说很清楚,它只是将一个目录从主机公开到容器,反之亦然

    虽然这部分正确,但-v 也可用于将named volumes 挂载到您的Docker 容器而不是目录中。 这个小细节对于理解VOLUME 是什么很重要做。一个例子:

    $ docker volume create my_volume
    $ docker run -v my_volume:[PATH] [IMAGE_NAME]
    

    这里创建了一个名为 my_volume 的卷。它的行为与“正常”安装所期望的一样。对容器内[PATH] 的任何更改都将保留在此卷中。不同之处在于 Docker 管理卷的位置,因此您无需担心(如果您有兴趣,它是 /var/lib/docker/volumes/my_volume/_data)。你为什么要这个?你可以有一个测试数据库。虽然您不需要直接访问文件,但您可能希望保存当前状态以将其挂载到其他数据库容器中。

    VOLUME [PATH] 指令基本上是将上述指令保存到图像的元信息中。所以每次你从这个镜像启动一个容器时,Docker 都知道你想将[PATH] 持久化到一个卷中并处理它。

    【讨论】:

    • 我的朋友。第一:VOLUME [PATH] 等价于 docker run -v [PATH]。它不会创建命名卷。检查文档:docs.docker.com/engine/reference/builder/#/volume。在 Dockerfile 中使用第二个 VOLUME 来强制创建一个卷独立于持久性的意图。尝试在 JBoss 的数据目录上没有 VOLUME 的情况下激活 libaio 来运行 Jboss。
    • 当然你是对的,我应该更准确一点:如果你从docker inspect --format="{{json .ContainerConfig.Volumes}}" [IMAGE] 不是null 的任何镜像启动容器,Docker 将创建一个具有随机 ID 的卷作为在docker volume ls 中可以看到你的名字。简而言之:我从 OP 的问题中感觉到,提出一个例子会很有帮助。我并不是说VOLUME 创建了一个named 卷。我只是使用命名卷作为安装点的示例,其位置由 Docker 管理。
    【解决方案3】:

    对于看到这篇文章并想知道 dockerfile 中的 VOLUME /docker/dirdocker run 命令中的 -v /host/dir:/docker/dir 之间的区别的人:

    VOLUME 只能将我们在容器中指定的一个目录映射到默认的(系统分配的,通​​常是/var/lib/docker/....)主机目录中。而docker run -v可以同时指定主机目录和容器目录。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-06
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      • 2021-09-25
      • 1970-01-01
      • 1970-01-01
      • 2020-03-09
      相关资源
      最近更新 更多