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

Add a volume to Docker, but exclude a sub-folder

假设我的主机 /hostFolder 上有一个 Docker 容器和一个文件夹。现在,如果我想将此文件夹作为卷添加到 Docker 容器中,那么我可以通过在 Dockerfile 中使用 ADD 或将其作为卷安装来执行此操作。

到目前为止,还不错。

现在 /hostFolder 包含子文件夹 /hostFolder/subFolder

我想将 /hostFolder 挂载到 Docker 容器中(无论是读写还是只读都无所谓,对我来说都适用),但我这样做 NOT 想要包含它 /hostFolder/subFolder。我想排除这一点,我还希望 Docker 容器能够对此子文件夹进行更改,而不会在主机上也进行更改。

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

首先,在 Dockerfile 中使用 ADD 指令与使用卷 非常 不同(通过 -v 参数 docker run 或 Dockerfile 中的 VOLUME 指令)。 ADDCOPY 命令仅在 docker build 为 运行 时复制文件。在使用 docker build 命令创建新图像之前,这些文件不会更新。相比之下,使用卷本质上是说 "this directory should not be stored in the container image; instead use a directory on the host";每当卷内的文件发生更改时,主机和容器都会立即看到它。

我不相信你可以使用卷实现你想要的,如果你想这样做,你将不得不重新考虑你的目录结构。

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

请记住,您使用 COPYADD 添加到图像的任何文件都必须在构建上下文中,即在您 运行 docker build 所在的目录中或目录下。

使用 docker-compose 我可以在本地使用 node_modules,但在 docker 容器中使用 docker-compose.yml[= 中的以下语法忽略它16=]

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 选项(归功于 ), but --mount is clearer and recommended

对于同样遇到 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.