修改从父图像继承的卷数据

时间:2017-09-14 20:08:23

标签: docker

假设有以下Dockerfile描述的图像CMD <webserver-start-script>

A

我想指定一个从FROM bash RUN mkdir "/data" && echo "FOO" > "/data/test" VOLUME "/data" 继承并修改B的图片A。我不想挂载卷,我希望它有一些我在/data/test中指定的默认数据:

B

问题是测试文件将保留FROM A RUN echo "BAR" > "/data/test" Dockerfile中VOLUME指令时的内容。 A图像测试文件将包含B而不是FOO,如我所料。

以下Dockerfile演示了这种行为:

BAR

构建Dockerfile将打印FROM bash # overwriting volume file RUN mkdir "/volume-data" && echo "FOO" > "/volume-data/test" VOLUME "/volume-data" RUN echo "BAR" > "/volume-data/test" RUN cat "/volume-data/test" # prints "FOO" # overwriting non-volume file RUN mkdir "/regular-data" && echo "FOO" > "/regular-data/test" RUN echo "BAR" > "/regular-data/test" RUN cat "/regular-data/test" # prints "BAR" FOO

是否可以修改BAR Dockerfile中的文件/data/test

3 个答案:

答案 0 :(得分:2)

似乎这是intended behavior

  

更改Dockerfile中的卷:如果任何构建步骤在声明后更改了卷中的数据,那么这些更改将被丢弃。

答案 1 :(得分:0)

有一些非显而易见的方法可以做到这一点,而且所有这些方法都有明显的缺陷。

劫持父码头文件

也许最简单但最不可重用的方法是简单地使用父Dockerfile并对其进行修改。一个快速的docker <image-name:version> source谷歌应该找到托管父图像Dockerfile的github。这有利于优化最终图像,但会破坏使用图层的重点。

使用on start script

虽然Dockerfile无法对卷进行进一步修改,但正在运行的容器可以。向图像添加脚本,并更改​​Entrypoint以调用该脚本(并使该脚本调用原始入口点)。如果您使用的是单件式容器,则需要执行此操作,并且需要部分重置&#39;启动时的音量。当然,由于卷在容器外部持久存在,请记住1)您的更改可能已经完成,2)同时启动的另一个容器可能已经在进行这些更改。

由于卷(实际上)是永远的,所以我在第一次启动容器后只使用一次设置脚本。这样我可以轻松控制何时设置/重置默认数据。 (如果需要,可以使用docker inspect <volume-name>获取卷的主机位置)

这个的共同中间点似乎是有一个一次性图像,其唯一目的是运行一次来​​进行音量配置,然后将其清理干净。

绑定到新卷

将旧卷的内容复制到新卷,并配置所有内容以使用新卷。

最后......重新考虑Docker是否适合你

你可能已经浪费了更多的时间而不是它的价值。 (根据我的经验,Docker的维护难度总是远远超过它的好处。但是,Docker是一个工具,使用任何工具,你需要花一点时间来反映你是否正确使用它,如果有更好的这项工作的工具。)

答案 2 :(得分:0)

音量不属于您的IMAGE。那么将数据植入其中的用例是什么?将图像推入另一个位置时,它在开始时使用空卷。 dockerfile行为确实会提醒您。

基本上,如果您想将数据与应用程序代码一起保存,则不应使用VOLUME。如果父图像中确实存在卷声明,则需要在开始自己的图像构建之前删除该卷。 (docker-copyedit)。