在Dockerfile中“删除”一个卷

52

我有一个Dockerfile,它使用FROM指令扩展了一个声明了VOLUME的镜像。是否有一种方式可以覆盖VOLUME指令,以便"删除"VOLUME


请参见重置从父图像继承的属性(撰写时为开放问题)。 - saaj
5
我遇到了同样的问题,不得不花费几个小时来弄清楚为什么一个特定的子目录不能持久保存写入。最终发现,在它的某些上级目录中,有人“聪明地”将一个 VOLUME 分配给了那个特定的目录 :/ - BjornW
如果您只想更改图像(而不是通过Dockerfile派生),则导出/配置编辑/导入方法可能适合。https://stackoverflow.com/a/50051739/4729 - Ivan Hamilton
5个回答

39

不行。

唯一的方法是,克隆您使用的基础映像FROM中的Dockerfile并手动删除VOLUME指令。然后构建它,并将其用作您的FROM基础映像。


2
有这个限制的原因吗?我认为可能与安全有关,但我想不出在子Dockerfile中如何滥用卷删除。 - Mitja
4
不,只是Dockerfile指令的编写方式使得你无法覆盖父级声明的卷。这里明确写着:如果任何构建步骤在声明卷后更改了卷内的数据,则这些更改将被丢弃。详见链接:https://docs.docker.com/engine/reference/builder/#notes-about-specifying-volumes - Kevin Kopf
8
谢谢!我认为在编译时应该有一个警告来提示这种情况的发生。 - Mitja

9

有时你无法修改原始的Dockerfile——比如我这种情况,需要使用生产环境中的镜像。唯一的机会是修改元数据(使用docker save/load操作)。因为我经常需要这样做,所以我写了一个小脚本来帮助处理,可以看看docker-copyedit是否能对你有所帮助。


谢谢 - 非常有用的工具! - KolaB

2

您可以覆盖文件。 使用多阶段构建和COPY(docker 19.03)。 第一阶段 在VOLUME文件夹之外创建文件。或者在添加/修改文件的同一RUN步骤中将其复制到该文件夹之外。 下一阶段将文件从上一个阶段复制到VOLUME文件夹中。


1

不,无法覆盖父Docker镜像中的VOLUME指令以“删除”该VOLUME。

Dockerfile中的VOLUME指令用于创建卷的挂载点,这是一种在容器文件系统之外存储持久数据的方法。当您在Dockerfile中使用FROM指令扩展声明了VOLUME的父镜像时,VOLUME指令会被子镜像继承。

如果您想从子镜像中删除VOLUME指令,则需要基于父镜像创建一个新的Docker镜像,但不包含VOLUME指令。您可以通过创建一个新的Dockerfile来实现这一点,该文件使用FROM指令指定父镜像,然后省略VOLUME指令。

例如,如果父镜像的Dockerfile中有如下的VOLUME指令:

VOLUME /data

如果您想创建一个不包含该 VOLUME 的子镜像,可以创建一个新的 Dockerfile,如下所示:

dockerfile

FROM parent-image:tag
# Omit the VOLUME directive
enter code here

然后,使用docker build命令构建新的Docker镜像:
bash
docker build -t child-image:tag .

生成的子镜像将基于父镜像,但不会有VOLUME指令。请注意,之前存储在父镜像定义的卷中的任何数据将无法在子镜像中使用。

请记住,删除VOLUME指令可能会对您的应用程序产生意想不到的后果,例如使跨容器实例持久化数据更加困难。在从Docker镜像中删除VOLUME指令之前,请务必仔细考虑其影响。


1
忽略VOLUME指令并不会阻止生成的容器具有卷。请参阅讨论https://github.com/moby/moby/issues/3465,并且每个人都要求一个VOLUME重置指令。 - undefined

0

假设源图像被命名为original_image,并且是从包含VOLUME /data指令的Dockerfile构建的。要构建带有内容的最终镜像,只需在辅助的Dockerfile中执行docker build -t final_image_with_data_in_volume_dir .,该文件仅包含这两行:

FROM original_image
COPY data_dir /data

其中data_dir是本地准备好的数据文件夹,旨在位于/data目录中。

(这与@a b的答案类似,但文本过长,无法仅作为评论。)

背景:我使用docker化的Neo4j图形数据库技术。原始镜像声明数据文件目录为VOLUME。因此,不可能通过docker commit进行任何更改,以获得具有更改数据的全新镜像(有时希望将数据放在容器内,例如用于TestContainer测试)。然后可以使用docker build来解决这个问题。


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