向Docker添加卷,但排除子文件夹

假设我在主机/hostFolder上有一个Docker容器和一个文件夹。现在,如果我想将这个文件夹作为卷添加到Docker容器中,那么我可以通过在Dockerfile中使用ADD或将其作为卷挂载来做到这一点。

到目前为止,一切顺利。

现在/hostFolder包含了一个子文件夹/hostFolder/subFolder

我想将/hostFolder挂载到Docker容器中(无论是读写还是只读都不重要,对我来说都适用),但我确实希望包含它/hostFolder/subFolder。我想排除这个,我还希望Docker容器能够对这个子文件夹进行更改,而不需要在主机上更改它。

这可能吗?如果有,怎么做?

152513 次浏览

首先,在Dockerfile中使用ADD指令与使用卷的非常不同(无论是通过-v参数到docker run,还是通过Dockerfile中的VOLUME指令)。ADDCOPY命令只是在运行docker build时获取文件的副本。直到使用docker build命令创建了一个新的映像,这些文件才会更新。相比之下,使用卷实际上是在说“这个目录不应该存储在容器映像中;而是使用主机上的目录”;当卷中的文件被更改时,主机和容器都将立即看到它。

我不相信您可以使用卷来实现您想要的效果,如果您想这样做,您必须重新考虑您的目录结构。

然而,使用COPY(应该优先于ADD)来实现这一点非常简单。你可以使用.dockerignore文件来排除子目录,或者你可以COPY所有文件,然后使用RUN rm bla来删除子目录。

记住,使用COPYADD添加到image的任何文件必须在构建上下文中,即在运行docker build的目录中或下面。

使用docker-compose,我能够在本地使用node_modules,但在docker容器中使用下面的docker-compose.yml语法忽略它

volumes:
- './angularApp:/opt/app'
- /opt/app/node_modules/

所以./angularApp中的所有内容都映射到/opt/app,然后我创建另一个挂载卷/opt/app/node_modules/,现在是空目录-即使在我的本地机器./angularApp/node_modules不是空目录。

如果你想让子目录被docker-compose忽略但持久,你可以在docker-compose.yml中执行以下操作:

volumes:
node_modules:
services:
server:
volumes:
- .:/app
- node_modules:/app/node_modules

这将挂载您的当前目录作为共享卷,但挂载一个持久的docker卷代替您的本地node_modules目录。这与@kernix的答案类似,但这将允许node_modulesdocker-compose up运行之间持续存在,这可能是理想的行为。

要排除一个文件,请使用以下方法

volumes:
- /hostFolder:/folder
- /dev/null:/folder/fileToBeExcluded
看起来旧的解决方案已经不管用了(至少对我来说)。 不过,创建一个空文件夹并将目标文件夹映射到它会有所帮助
volumes:
- ./angularApp:/opt/app
- .empty:/opt/app/node_modules/

使用docker命令行:

docker run \
--mount type=bind,src=/hostFolder,dst=/containerFolder \
--mount type=volume,dst=/containerFolder/subFolder \
...other-args...

-v选项也可以使用(转换到Bogdan集市),但--mount更清晰,推荐

对于那些也有node_modules文件夹仍然会从本地系统覆盖的问题的人,反之亦然

volumes:
node_modules:
services:
server:
volumes:
- .:/app
- node_modules:/app/node_modules/


这是解决方案,node_modules后面的/是修复。

要排除机器卷中包含的挂载文件,您必须通过将卷分配给同一文件来覆盖它。 在你的配置文件中:

services:
server:
build : ./Dockerfile
volumes:
- .:/app

你dockerfile中的一个例子:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file

对于那些试图在node_modules不被局部覆盖的情况下获得一个良好的工作流的人来说,这可能会有所帮助。

  1. 更改docker-compose,将匿名持久卷挂载到node_modules,以防止本地覆盖它。在这篇文章中已经概述了几次。
services:
server:
build: .
volumes:
- .:/app
- /app/node_modules
  1. 这是我们忽略的重要部分。当你的堆栈旋转使用docker-compose -V。如果没有这个,如果你添加了一个新的包并重新构建你的映像,它将使用你最初的docker-compose启动时的node_modules
    -V, --renew-anon-volumes   Recreate anonymous volumes instead of retrieving
data from the previous containers.

我发现这个链接救了我:使用docker绑定挂载和node_modules.
这个工作解决方案将在docker卷管理器中创建一个名为卷的“exclude"。卷名“exclude"是任意的,因此可以自定义卷名,而不是exclude.

. 0
services:
node:
command: nodemon index.js
volumes:
- ./:/usr/local/app/
# the volume above prevents our host system's node_modules to be mounted
- exclude:/usr/local/app/node_modules/


volumes:
exclude:

你可以在官方文档-使用docker合成卷中看到更多关于卷的信息