You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker镜像拉取与Volume、Bind Mount行为疑问及验证

Docker卷与绑定挂载的行为差异解析

问题背景

我正在理解Docker镜像的工作机制,参考了一个包含VOLUME指令且有RUN命令修改该路径内容的Containerfile,有以下疑问:

  1. 从Docker Hub拉取该镜像时,Volume中的数据会如何处理?是否包含在拉取的镜像中?RUN命令仅在启动容器时执行吗?
  2. 运行容器时,将本地目录绑定挂载到VOLUME指令指定的挂载点上会发生什么?

实验与行为观察

实际测试发现,绑定挂载会覆盖容器内原有数据,导致RUN命令生成的数据丢失;但使用命名卷时数据会保留。同时我有疑问:若拉取更新版本的容器镜像,命名卷中的原有数据会不会被镜像里Volume的新内容修改?

查阅Docker文档得知:

使用容器填充卷
若启动创建新卷的容器,且容器中待挂载目录存在文件或目录,该目录内容会被复制到卷中。容器随后挂载并使用该卷,其他使用该卷的容器也能访问预填充的内容。

但该机制在绑定挂载已存在目录时不生效。我做了以下对比实验:

测试用Dockerfile

FROM alpine
RUN mkdir /test \
    && echo 'echo "start `date`" >>/test/log' >/runtest \
    && echo 'echo "/log:"' >>/runtest \
    && echo 'cat /log' >>/runtest \
    && echo 'echo "/test/log:"' >>/runtest \
    && echo 'cat /test/log' >>/runtest \
    && echo 'sleep 99999999' >>/runtest \
    && chmod +x /runtest \
    && echo "build `date`" >/test/log \
    && echo "build `date`" >/log \
    && cat /runtest \
    && cat /log \
    && cat /test/log
CMD /runtest
VOLUME "/test"

该Dockerfile通过RUN命令创建/test/log并写入构建日期,CMD命令会在每次容器启动时向该文件追加启动日期。需注意VOLUME指令要放在RUN之后,因为VOLUME会将目录当前内容复制到卷中,之后的RUN命令仅影响容器镜像内的原目录,不会同步到卷中。

命名卷方式测试(docker-compose配置)

version: "3"

services:
  tester:
    build: .
    volumes:
      - test:/test

volumes:
  test:

首次运行结果

tester_1  | /log:
tester_1  | build Mon Feb 20 08:53:29 UTC 2023
tester_1  | /test/log:
tester_1  | build Mon Feb 20 08:53:29 UTC 2023
tester_1  | start Mon Feb 20 08:53:45 UTC 2023

停止后再次运行结果

tester_1  | /log:
tester_1  | build Mon Feb 20 08:54:28 UTC 2023
tester_1  | /test/log:
tester_1  | build Mon Feb 20 08:53:29 UTC 2023
tester_1  | start Mon Feb 20 08:53:45 UTC 2023
tester_1  | start Mon Feb 20 08:54:33 UTC 2023

可以看到,不在卷中的/log每次启动都会被镜像内的新内容覆盖,而卷中的/test/log会保留历史内容,每次启动时追加新的日志。

绑定挂载方式测试

将docker-compose中的卷替换为绑定挂载配置- /test:/test,首次运行报错:Service "tester" is using volume "/test" from the previous container.。删除原有Docker卷后再次运行,结果如下:

tester_1  | /log:
tester_1  | build Mon Feb 20 09:00:50 UTC 2023
tester_1  | /test/log:
tester_1  | start Mon Feb 20 09:01:03 UTC 2023

可见RUN命令生成的构建日期数据没有被复制到绑定挂载的本地目录中。

结论

  1. 拉取镜像时,VOLUME指定路径下的内容是包含在镜像中的;RUN命令是在镜像构建阶段执行的,并非容器启动时执行。首次使用命名卷挂载该路径时,镜像里的内容会被复制到卷中;后续启动容器时,卷的内容会覆盖容器内该路径的内容,镜像里的对应内容不再生效。
  2. 使用绑定挂载时,本地目录的内容会直接覆盖容器内VOLUME指定的路径,镜像构建阶段RUN生成的该路径下的内容不会被复制到本地目录中。
  3. 对于已存在的命名卷,拉取更新版本的镜像后启动容器,镜像里VOLUME路径的新内容不会覆盖原有卷的数据——只有首次创建卷时才会执行从镜像到卷的内容复制。

内容的提问来源于stack exchange,提问作者Nikki Locke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 19:29:44