假设我的主机 /hostFolder
上有一个 Docker 容器和一个文件夹。现在,如果我想将此文件夹作为卷添加到 Docker 容器中,则可以通过使用 Dockerfile
中的 ADD
或将其安装为卷来执行此操作。
到目前为止,一切都很好。
现在 /hostFolder
包含一个子文件夹 /hostFolder/subFolder
。
我想将 /hostFolder
挂载到 Docker 容器中(无论是读写还是只读,都对我有用),但我确实不希望包含它/hostFolder/subFolder
.我想排除它,并且我还希望 Docker 容器能够对这个子文件夹进行更改,而不会在主机上对其进行更改。
这可能吗?如果是这样,怎么做?
使用 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_modules
在 docker-compose up
运行之间持续存在,这可能是所需的行为。
docker-compose down
将删除容器,但卷将持续存在,直到您运行类似 docker system prune
node_modules:
命名卷“忽略” docker 容器中的 /app/node_modules
,可能会发现这篇文章很有用How docker handles multiple mount types?
对于那些试图在 node_modules
未被本地覆盖的情况下获得良好工作流程的人来说,这可能会有所帮助。
更改您的 docker-compose 以将匿名持久卷挂载到 node_modules 以防止您的本地覆盖它。这已在此线程中概述了几次。
services:
server:
build: .
volumes:
- .:/app
- /app/node_modules
这是我们缺少的重要一点。启动堆栈时,请使用 docker-compose -V。如果没有这个,如果你添加了一个新包并重建了你的镜像,它将使用你初始 docker-compose 启动中的 node_modules。
-V, --renew-anon-volumes Recreate anonymous volumes instead of retrieving
data from the previous containers.
--renew-anon-volumes
的注释是一个重要的补充。在某些情况下,您想挂载源代码文件夹并通过将 node_modules 文件夹挂载为匿名卷来排除它。该标志避免重复使用先前创建的匿名卷,以便正确反映对 package.json
的更改。
node_modules
目录。我们怎样才能避免呢?
要排除文件,请使用以下命令
volumes:
- /hostFolder:/folder
- /dev/null:/folder/fileToBeExcluded
Cannot start service xxx: OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:402: container init caused \"rootfs_linux.go:58: mounting \\\"/dev/null\\\" to rootfs \\\"/var/lib/docker/overlay2/d15ed56ad020d408c63a1f6a6365dbb88d5d3b78a4605980d3faa9861102ef21/merged\\\" at [...] unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
。添加尾部斜杠没有帮助。
/dev/null
作为设备文件复制到容器中。
Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
。这不是 OP 所要寻找的,但它对我非常有用,因为我需要排除单个文件。
使用 docker 命令行:
docker run \
--mount type=bind,src=/hostFolder,dst=/containerFolder \
--mount type=volume,dst=/containerFolder/subFolder \
...other-args...
也可以使用 -v
选项(归功于 Bogdan Mart),但 --mount
更清晰且 recommended。
首先,在 Dockerfile 中使用 ADD
指令非常不同于使用卷(通过 docker run
的 -v
参数或 Dockerfile 中的 VOLUME
指令)。 ADD
和 COPY
命令只是在 docker build
运行时获取文件的副本。在使用 docker build
命令创建新映像之前,不会更新这些文件。相比之下,使用卷本质上是在说“这个目录不应该存储在容器镜像中;而是使用主机上的目录”;每当卷中的文件发生更改时,主机和容器都会立即看到它。
我不相信你可以使用卷来实现你想要的,如果你想这样做,你将不得不重新考虑你的目录结构。
但是,使用 COPY
(应该优先于 ADD
)来实现非常简单。您可以使用 .dockerignore
文件排除子目录,或者您可以 COPY
所有文件然后执行 RUN rm bla
删除子目录。
请记住,您使用 COPY
或 ADD
添加到映像的任何文件都必须在构建上下文中,即在您运行 docker build
的目录中或目录下。
.dockerignore
文件以排除子目录(甚至是目录)的示例。鉴于这是该文件的既定目的,这很奇怪。
squash
层的选项。一个是 github.com/goldmann/docker-squash,另一个是使用 openshift 项目中的 oc ex dockerbuild
。
对于那些也有 node_modules 文件夹仍然会从您的本地系统覆盖的问题的人,反之亦然
volumes:
node_modules:
services:
server:
volumes:
- .:/app
- node_modules:/app/node_modules/
这是解决方案,在 node_modules 之后的尾随 /
是修复。
node_modules
文件夹映射到容器中的 /app/node_modules
文件夹内?所以在容器内部,我们有 /app/node_modules/node_modules
?为什么?
看起来旧的解决方案不再起作用(至少对我来说)。不过,创建一个空文件夹并将目标文件夹映射到它会有所帮助。
volumes:
- ./angularApp:/opt/app
- .empty:/opt/app/node_modules/
docker-compose 1.25.0-rc3
,文件语法 v3。
要排除计算机卷中包含的已安装文件,您必须通过将卷分配给同一文件来覆盖它。在您的配置文件中:
services:
server:
build : ./Dockerfile
volumes:
- .:/app
dockerfile 中的一个示例:
# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file
/opt/app/node_modules/
替换为另一个具有相同名称的目录。发生错误:“音量忙”/opt/app/node_modules/
下有文件,如果您将其挂载在父目录之后,它们将被忽略。例如,如果您想在映像中包含模块,但以后能够刷新它,您可以按以下顺序列出卷:- /opt/app/node_modules/
然后父- './angularApp:/opt/app'
-v $(pwd):/build/ -v /build/node_modules
If you start a container which creates a new volume, as above, and the container has files or directories in the directory to be mounted (such as /app/ above), the directory’s contents are copied into the volume.