当重新启动Docker容器时如何重用相同的卷?

14

我有一个Dockerfile,在末尾声明了一个卷,如下所示:

VOLUME /data

现在,当我构建并运行此容器时,确实会创建一个新的卷,并挂载到/data
这很好,但我希望能够停止该容器,然后再次运行它,并确保相同的卷及其数据被重新挂载。

我如何做到这一点?
理想情况下,如果卷不存在,则相同的命令将创建该卷,并在卷已存在时重用它。

2个回答

17

如果您希望将数据持久保存在容器的生命周期之外,则需要在容器之外创建卷。其中一种选项是创建“数据卷容器”,如文档中所述:

docker create -v /data --name my-data busybox /bin/true

这创建了一个名为my-data的容器。它基于busybox镜像,但因为我们使用的是create而不是run,所以实际上并没有启动任何东西。此容器仅存在以为其他容器提供卷。

然后,我们可以使用--volumes-from选项访问该卷,当我们启动另一个容器时使用docker run:

docker run --volumes-from my-data ...

现在你有一个在容器删除后仍然存在并且只要你的my-data容器没有被删除就会持久化的卷。

或者,你可以在容器中挂载主机目录到/data,例如:

docker run -v /path/on/host:/data ...

此选项在我上面链接的文档中同样有描述。


2
我已经测试了这个关于数据卷容器的过程,并且它按预期工作。但是我不理解的是,即使在Dockerfile中没有提供VOLUME语句,它仍然可以工作!那么VOLUME语句的目的是什么? - Barry NL
2
@BarryNL 卷可以在 Dockerfile 中定义,也可以使用 docker run -v 命令来定义。如果卷是在 Dockerfile 中指定的,则本地路径通常类似于 /var/lib/docker/vfs/...。您可以使用 docker inspect -f {{.Volumes}} name 命令来查找。但是,Dockerfile 卷和 run -v 卷之间存在差异。如果容器的基础镜像在指定的挂载点包含数据,则该现有数据将在卷初始化时复制到新卷中 - 但仅适用于 Dockerfile 卷。 - fnkr

10

在使用命名卷出现之前,Larsks的回答是应该遵循的方式(或者至少是解决方法)。
现在只需使用命名卷,这更加简单和标准。

这很好,但我想能否停止此容器然后再次运行它,确保相同的卷及其数据被挂载回来。

如果您停止一个正在运行的容器(使用docker stop id),然后再次启动它(使用docker start id),与容器关联的卷仍将存在,无需使用命名卷或任何技巧,因为它仍然使用相同的容器。
卷不持久存在的问题发生在同一镜像的不同运行之间(docker run fooImageName)。

匿名和命名卷

指定卷有两种形式:匿名和命名。
如果我们不指定名称,主机上的卷无法在下一次容器运行中重复使用,因为它是匿名的(但通过使用两个不同的容器:一个用于应用程序,另一个用于具有匿名卷的数据,可以解决这个问题,就像在Larsks的回答中一样)。 因此,由于卷是匿名的,Docker会为每个相同镜像的容器运行在主机上创建一个新的卷。

要使用命名卷,当我们运行容器时,只需在容器中挂载到文件/目录前缀名称(任何逻辑名称都可以)。
例如,在dockerfile中声明一个卷:

VOLUME /data

我们可以这样启动容器:

docker run -v my-volume:/data myImage

首次运行时创建卷。然后在任何下一次运行时,我们只需要指定已命名的卷 my-volume 以重用该卷。

这是文档中有趣的部分(重点是我的):

  

选择 -v 或 --mount 标记

     

...

     
      
  • -v--volume:由三个字段组成,由冒号字符(:)分隔。字段必须按正确顺序,每个字段的含义不是立即明显的。      
        
    • 对于命名的卷,第一个字段是卷的名称,并且在给定主机上是唯一的。对于匿名卷,省略了第一个字段。
    •   
    • 第二个字段是文件或目录在容器中挂载的路径。
    •   
    • 第三个字段是可选的,并且是选项的逗号分隔列表,例如 ro。
    •   
  •   

作为替代方案,如果出于某些原因您需要在不启动容器的情况下创建卷,可以使用 docker volume 命令。
您可以在卷文档中阅读:

  

创建和管理卷

     

与绑定挂载不同,您可以在任何容器范围之外创建和管理卷。

     

创建一个卷:

     

$ docker volume create my-vol

我们将像以前一样使用它:

docker run -v my-volume:/data myImage

在第一次运行时,会创建一个卷。然后对于任何下一次运行,我们只需要指定仍然命名为my-volume的卷来重用该卷。 - NoClue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接