1. 概述
在需要将容器资源与宿主机进行绑定时,我们会使用 Docker 卷。我们可以使用命名卷(named volumes)或绑定挂载(bind mounts),也可以选择本地或远程资源,持久化与否均可。
但在实际挂载过程中,我们可能会希望排除一些不必要的文件或文件夹。比如日志文件、临时文件、node_modules 等。
本文将通过 Docker Compose 示例,演示如何在挂载卷时排除某些子目录或文件。
2. 构建一个 Node.js Docker 镜像
在介绍如何排除文件之前,我们先来简单构建一个 Node.js 的 Docker 镜像作为示例。
通常,构建镜像时我们会将本地代码复制到容器中。以下是一个基础的 Dockerfile
示例:
FROM node:12.18.1
ENV NODE_ENV=production
WORKDIR /app
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production
COPY . .
CMD [ "node", "server.js" ]
使用如下命令构建镜像:
$ docker build -t node-docker .
该命令会将当前目录下的所有内容作为上下文发送给 Docker 服务,用于构建镜像。构建完成后,我们可以使用 docker history
查看镜像的构建层:
$ docker history --format "ID-> {{.ID}} | Created-> {{.CreatedSince}} | Created By-> {{.CreatedBy}} | Size: {{.Size}}" e870a50eed97
输出类似如下内容:
ID-> e870a50eed97 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) CMD ["node" "server.js"] | Size: 0B
ID-> 708a43cd0ef2 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) COPY dir:7cc2842dd32649457… | Size: 11.3MB
ID-> d49b84f48e41 | Created-> 36 hours ago | Created By-> /bin/sh -c npm install --production | Size: 14.7MB
ID-> a351be0717a1 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) COPY multi:9959dc16241ba60… | Size: 80.7kB
ID-> 56b22d35f315 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) WORKDIR /app | Size: 0B
ID-> c28b64493ce8 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) ENV NODE_ENV=production | Size: 0B
ID-> f5be1883c8e0 | Created-> 2 years ago | Created By-> /bin/sh -c #(nop) CMD ["node"] | Size: 0B
3. 构建镜像时排除文件和目录
假设我们项目中有一些敏感文件(如 secret.txt
)或大文件(如日志、压缩包),不希望它们被包含在镜像中。此时,我们可以使用 .dockerignore
文件来排除这些资源。
它的工作方式与 .gitignore
类似。例如,创建一个 secret.txt
文件:
$ echo 'password' >secret.txt
然后在 .dockerignore
中添加:
# 排除密码文件
secret.txt
也可以排除整个目录:
# 排除日志目录
logs/
这样构建的镜像就不会包含这些文件。使用如下命令启动容器验证:
$ docker run -d --publish 8000:8000 node-docker
或者使用 Docker Compose:
services:
node-app:
image: node-docker:latest
ports:
- 8080:8080
进入容器后,使用 ls
检查,你会发现 secret.txt
并不存在。
4. 使用卷挂载时排除文件或目录
除了构建镜像时排除资源,我们还可以在容器运行时通过卷挂载的方式排除某些文件或目录。
4.1 排除单个文件
假设我们不希望容器中某个文件影响宿主机,可以使用 /dev/null
进行绑定:
services:
node-app:
build: .
ports:
- 8080:8080
volumes:
- .:/app/
- /dev/null:/app/secret.txt
这样,容器中的 secret.txt
就是一个空文件,不会影响宿主机。
4.2 排除目录
更常见的是我们希望排除某个子目录,比如 node_modules
。可以通过挂载匿名卷或命名卷来实现:
services:
node-app:
build: .
ports:
- 8080:8080
volumes:
- .:/app
- /app/node_modules/
✅ 注意顺序:先挂载整个项目目录,再单独挂载要排除的子目录。
如果希望保留命名卷,可以这样写:
services:
node-app:
build: .
ports:
- 8080:8080
volumes:
- .:/app
- my-vol:/app/node_modules/
volumes:
my-vol:
driver: local
这样,容器中 node_modules
目录的修改不会同步到宿主机。
5. 总结
本文介绍了在使用 Docker 构建镜像和运行容器时,如何排除不需要的文件或目录:
- 使用
.dockerignore
排除构建上下文中的资源 - 使用
/dev/null
排除特定文件 - 使用匿名或命名卷排除子目录(如
node_modules
)
这些方法可以帮助我们优化镜像体积、保护敏感信息、避免误操作影响宿主机。
完整代码示例请参考 GitHub 仓库。