作为更大设置的一部分,我有一个带有 Docker Compose 的多阶段 Docker 构建,它有一个builder
容器,其中包含一些/var/www
中的数据。当我构建名为application
的第二阶段容器时,我的 Dockerfile 有这些指令
ARG APPLICATION_BUILDER
FROM $APPLICATION_BUILDER as builder
FROM busybox
COPY --from=builder --chown=www-data:www-data /var/www /var/www
VOLUME /var/www
ENTRYPOINT ["tail"]
CMD ["-f", "/dev/null"]
Dockerfilebuilder
是:
FROM ubuntu:16.04
ARG APPLICATION_SOURCE_FOLDER
COPY --chown=www-data:www-data ${APPLICATION_SOURCE_FOLDER} /var/www
当我启动builder
容器时,它按预期/var/www
了所有数据。但是,当我使用以下命令启动application
容器时:docker run -it <IMAGE>
它不包含任何/var/www
如果我删除Dockerfile
中的VOLUME /var/www
行,则数据将按预期显示。但是我不明白为什么VOLUME
指令会使数据消失,我以为这是为了将/var/www/
的内容导出为卷?
除了VOLUME
指令外,我是否需要在执行docker run
时指定-v
?
VOLUME
指令不会"导出目录的内容"。它说"创建一个卷并将其挂载到此路径上"。所以当你写:
COPY --from=builder --chown=www-data:www-data /var/www /var/www
VOLUME /var/www
你是说:
- 首先,将一堆文件复制到
/var/www
- 接下来,在
/var/www
上装载一个空卷
卷挂载发生在构建时(影响任何后续RUN
语句(和运行时(影响您在docker run
中看到的环境(。
如果从Dockerfile
中删除VOLUME
指令,然后按如下所示运行映像:
docker run -v /var/www yourimage ...
然后 Docker 将创建一个新卷,并在挂载之前将/var/www
的内容复制到其中。
同样,如果您有命名卷,则可以执行相同的操作:
docker run -v myvolume:/var/www yourimage ...
Docker 仅在您挂载的卷为空时执行此自动复制操作。如果卷具有现有内容,则只需将其装载到指定的路径上,隐藏该装入点下的任何内容。
例如。。。
我有一个名为kos
的图像,其中/var/www
有几个文件。我们可以通过运行ls /var/www
来查看它们:
bash-5.0$ docker run kos ls /var/www
index.html
testing.jpg
如果我使用docker run -v
在/var/www
上挂载匿名卷,我们可以看到它填充了底层/var/www
目录中的内容:
bash-5.0$ docker run -v /var/www kos ls /var/www
index.html
testing.jpg
如果我们创建一个命名卷并将其挂载到/var/www
上,我们会看到相同的行为:
bash-5.0$ docker volume create kos_testing
kos_testing
bash-5.0$ docker run -v kos_testing:/var/www kos ls /var/www
index.html
testing.jpg
bash-5.0$
我怀疑正在发生的事情是,当您指定 VOLUME 时,它实际上是用空卷挂载覆盖您之前复制的内容。
您不想删除该卷,因为看起来您希望保留此数据。所以你能做的,也许是切换指令。
首先声明卷,然后将数据复制到卷中。