找回密码
 立即注册

QQ登录

只需一步,快速开始

peUfSYR.png
查看: 50|回复: 0

Day 13 .dockerignore 文件:不可忽视的构建优化利器

[复制链接]

876

主题

13

回帖

2808

积分

管理员

积分
2808
发表于 2026-3-29 16:17:10 | 显示全部楼层 |阅读模式
前言

你有没有遇到过这样的情况:明明 Dockerfile 只有几行,
  1. docker build
复制代码
却慢得离谱?或者构建出来的镜像莫名其妙地膨胀到好几个 GB?

问题很可能不在 Dockerfile 本身,而在你忽略了一个不起眼的小文件——
  1. .dockerignore
复制代码


这是 Docker 30 天实战系列的第 13 天。读完这篇文章,你将理解
  1. .dockerignore
复制代码
的工作原理,掌握它的语法规则,并学会在真实项目中用它大幅提升构建效率。

构建上下文:理解问题的根源

要理解
  1. .dockerignore
复制代码
的价值,首先要理解一个关键概念:构建上下文(Build Context)

当你执行
  1. docker build .
复制代码
时,Docker 并不是直接在当前目录运行构建。它的实际流程分两步:

  • Docker CLI 将命令末尾指定的路径(这里是
    1. .
    复制代码
    ,即当前目录)下的所有文件打包成一个 tar 归档,发送给 Docker 守护进程。
  • Docker 守护进程在收到的归档中执行 Dockerfile 中的指令。

    这个被打包发送的文件集合就是构建上下文。

    关键点在于"所有文件"。假设你的项目目录下有 500 MB 的
    1. node_modules
    复制代码
    、200 MB 的
    1. .git
    复制代码
    历史记录、几百兆的测试数据和日志文件——它们统统会被打包发送,即使你的 Dockerfile 里从未用
    1. COPY
    复制代码
    1. ADD
    复制代码
    引用过它们。

    这就是构建缓慢和镜像臃肿的根源之一。
    1. .dockerignore
    复制代码
    的作用很简单:在打包构建上下文之前,告诉 Docker CLI 哪些文件不需要发送。它从源头上解决问题。

    基本语法
    1. .dockerignore
    复制代码
    文件放在构建上下文的根目录下(通常是项目根目录),每行写一条匹配规则。语法与
    1. .gitignore
    复制代码
    类似但不完全相同。

    核心规则
    1. # 这是注释,会被忽略
    2. # 忽略所有 .log 文件
    3. *.log
    4. # 忽略 node_modules 目录
    5. node_modules
    6. # 忽略所有 markdown 文件
    7. *.md
    8. # 但保留 README.md(! 表示例外)
    9. !README.md
    10. # 忽略根目录下的 temp 目录(不影响子目录中的 temp)
    11. temp
    12. # 忽略任意层级下的 __pycache__ 目录
    13. **/__pycache__
    14. # 忽略所有 .env 开头的文件
    15. .env*
    复制代码

    通配符说明

    | 通配符 | 含义 | 示例 |
    |--------|------|------|
    |
    1. [i]
    复制代码
    | 匹配任意非分隔符字符 |
    1. [/i].log
    复制代码
    匹配所有
    1. .log
    复制代码
    文件 |
    |
    1. ?
    复制代码
    | 匹配单个非分隔符字符 |
    1. temp?
    复制代码
    匹配
    1. temp1
    复制代码
    1. tempA
    复制代码
    |
    |
    1. [b]
    复制代码
    | 匹配任意层级目录 |
    1. [/b]/test
    复制代码
    匹配所有
    1. test
    复制代码
    目录 |
    |
    1. !
    复制代码
    | 例外规则,取消前面的忽略 |
    1. !README.md
    复制代码
    保留该文件 |

    规则的顺序很重要
    1. .dockerignore
    复制代码
    逐行匹配,后面的规则会覆盖前面的。来看一个例子:
    1. *.md
    2. !README.md
    复制代码

    这表示:忽略所有
    1. .md
    复制代码
    文件,但保留
    1. README.md
    复制代码
    。如果你把两行顺序颠倒:
    1. !README.md
    2. *.md
    复制代码

    结果是所有
    1. .md
    复制代码
    文件都被忽略,包括
    1. README.md
    复制代码
    。因为
    1. *.md
    复制代码
    是最后生效的规则。

    一份实用的 .dockerignore 模板

    不同技术栈的项目需要忽略的内容不同,但以下文件几乎在所有项目中都应该被排除:
    1. # 版本控制
    2. .git
    3. .gitignore
    4. .svn
    5. # Docker 相关(避免递归和干扰)
    6. Dockerfile
    7. docker-compose*.yml
    8. .dockerignore
    9. # IDE 和编辑器配置
    10. .vscode
    11. .idea
    12. *.swp
    13. *.swo
    14. # 操作系统生成的文件
    15. .DS_Store
    16. Thumbs.db
    17. # CI/CD 配置
    18. .github
    19. .gitlab-ci.yml
    20. Jenkinsfile
    21. # 文档(通常构建不需要)
    22. docs
    23. *.md
    24. LICENSE
    25. # 环境和密钥文件(安全考量)
    26. .env
    27. .env.*
    28. *.pem
    29. *.key
    30. # 测试相关
    31. test
    32. tests
    33. coverage
    34. .nyc_output
    复制代码

    针对特定技术栈,还需要补充:
    1. # Node.js 项目追加
    2. node_modules
    3. npm-debug.log
    4. yarn-error.log
    5. # Python 项目追加
    6. __pycache__
    7. *.pyc
    8. *.pyo
    9. .venv
    10. venv
    11. *.egg-info
    12. # Java 项目追加
    13. target
    14. *.class
    15. *.jar
    16. # Go 项目追加
    17. vendor
    复制代码

    真实效果对比

    为了让你对
    1. .dockerignore
    复制代码
    的效果有直观感受,我用一个典型的 Node.js 项目做了测试。

    项目结构:源代码约 2 MB,
    1. node_modules
    复制代码
    约 450 MB,
    1. .git
    复制代码
    目录约 180 MB,其余文件约 20 MB。

    | 指标 | 无 .dockerignore | 有 .dockerignore |
    |------|-----------------|-----------------|
    | 构建上下文大小 | 652 MB | 2.3 MB |
    | 上下文传输时间 | 12.8 秒 | 0.1 秒 |
    | 总构建时间 | 38 秒 | 22 秒 |

    构建上下文从 652 MB 缩减到 2.3 MB,降幅超过 99%。构建时间节省了约 40%。在 CI/CD 环境中每天构建几十次的场景下,这个优化的累积效果非常可观。

    三个容易踩的坑

    坑一:忽略了 Dockerfile 需要的文件

    一个典型错误是写了过于激进的忽略规则,把 Dockerfile 中
    1. COPY
    复制代码
    依赖的文件也排除了。
    1. # .dockerignore 中写了
    2. *.json
    复制代码
    1. # Dockerfile 中需要 package.json
    2. COPY package.json .
    3. RUN npm install
    复制代码

    构建会直接报错:
    1. COPY failed: file not found
    复制代码
    。解决方法是用例外规则精确放行:
    1. *.json
    2. !package.json
    3. !package-lock.json
    复制代码

    坑二:误以为语法和 .gitignore 完全一样

    两者的主要区别:
    1. .dockerignore
    复制代码
    不支持
    1. #
    复制代码
    开头的转义(不能用
    1. \#
    复制代码
    匹配以
    1. #
    复制代码
    开头的文件),也不支持在目录名后面加
    1. /
    复制代码
    来特指目录。
    1. node_modules
    复制代码
    1. node_modules/
    复制代码
    1. .dockerignore
    复制代码
    中效果相同。

    坑三:.dockerignore 放错了位置
    1. .dockerignore
    复制代码
    必须位于构建上下文的根目录。如果你的
    1. docker build
    复制代码
    命令指定了不同的上下文路径,
    1. .dockerignore
    复制代码
    要跟着上下文走,而不是跟着 Dockerfile。
    1. # 上下文是 ./app 目录,.dockerignore 应放在 ./app/.dockerignore
    2. docker build -f ./docker/Dockerfile ./app
    复制代码

    安全层面的价值

    除了性能优化,
    1. .dockerignore
    复制代码
    还有一个常被忽视的作用:防止敏感信息泄露到镜像中

    即使 Dockerfile 没有显式
    1. COPY
    复制代码
    敏感文件,构建上下文中包含的文件理论上可以被中间层缓存捕获。更常见的风险是:团队成员后续修改 Dockerfile 时,不小心用了
    1. COPY . .
    复制代码
    这样的宽泛语句,把
    1. .env
    复制代码
    、私钥、配置文件等一股脑复制进镜像。

    1. .dockerignore
    复制代码
    中排除敏感文件,等于加了一道安全兜底。这是防御性编码的思维方式。

    与多阶段构建配合
    1. .dockerignore
    复制代码
    和多阶段构建(Multi-stage Build)是两个互补的优化手段:

    1. .dockerignore
    复制代码
    优化的是"发送给 Docker 守护进程的内容"——缩小输入。
  • 多阶段构建优化的是"最终镜像中保留的内容"——缩小输出。

    两者结合使用效果最佳。先用
    1. .dockerignore
    复制代码
    减少构建上下文体积,加快传输速度;再用多阶段构建确保最终镜像只包含运行时必需的文件。

    总结
    1. .dockerignore
    复制代码
    是 Docker 生态中最容易被忽视、但投入产出比最高的优化工具之一。创建它只需要两分钟,但能带来三个层面的收益:

  • 性能:大幅缩小构建上下文,加快构建速度。
  • 安全:防止敏感文件意外进入镜像。
  • 可维护性:明确声明了"哪些文件与构建无关",让项目结构更清晰。

    建议从今天起,把"创建
    1. .dockerignore
    复制代码
    "加入每个新项目的初始化清单,和
    1. .gitignore
    复制代码
    同等对待。

    下一篇我们将深入探讨 Docker 的网络模型。到时见。
  • 您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    扫码关注微信公众号

    Archiver|手机版|小黑屋|风叶林

    GMT+8, 2026-5-8 21:41 , Processed in 0.162653 second(s), 20 queries .

    Powered by 风叶林

    © 2001-2026 Discuz! Team.

    快速回复 返回顶部 返回列表