2026/4/18 5:35:58
网站建设
项目流程
湛江网站建设策划,自动写作网站,怎么给网站做 360快照,做网站在厦门排前5名前几天在公司部署服务的时候#xff0c;发现一个nodejs应用的镜像居然有2.5G#xff01;我当时就懵了#xff0c;这不科学啊#xff0c;一个简单的web应用怎么可能这么大。同事开玩笑说是不是把整个node_modules都打包进去了…结果还真被他说中了一部分。
这种情况在实际工…前几天在公司部署服务的时候发现一个nodejs应用的镜像居然有2.5G我当时就懵了这不科学啊一个简单的web应用怎么可能这么大。同事开玩笑说是不是把整个node_modules都打包进去了…结果还真被他说中了一部分。这种情况在实际工作中真的太常见了很多时候我们构建的镜像莫名其妙就变得很大但是又不知道问题出在哪里。直到我发现了dive这个工具才算是找到了分析镜像的利器。dive是什么为什么要用它dive是一个用Go语言开发的Docker镜像分析工具它可以让你深入了解镜像的每一层结构看到每一层添加了什么文件删除了什么内容甚至可以计算出镜像的效率指标。你可能会问docker history命令不也能看镜像的层信息吗确实可以但是dive的优势在于交互式的界面操作起来更直观可以浏览每一层的文件系统变化显示每个文件的大小信息计算镜像的浪费空间和效率评分支持CI/CD集成可以设置镜像大小阈值说白了docker history只能告诉你发生了什么而dive能告诉你具体发生了什么影响有多大。安装dive的几种方式直接下载二进制文件最简单的方式就是从GitHub releases页面下载对应系统的二进制文件# Linuxwgethttps://github.com/wagoodman/dive/releases/download/v0.12.0/dive_0.12.0_linux_amd64.tar.gztar-xzfdive_0.12.0_linux_amd64.tar.gzsudomvdive /usr/local/bin/# macOSbrewinstalldive使用Docker运行dive这种方式比较适合不想在本地安装的情况dockerrun--rm-it\-v/var/run/docker.sock:/var/run/docker.sock\wagoodman/dive:latest镜像名我个人更喜欢直接安装因为用起来更方便一些。从源码编译如果你想体验最新的功能可以从源码编译goinstallgithub.com/wagoodman/divelatest不过说实话直接用release版本就足够了我用了这么久也没遇到什么bug。dive的基本使用方法安装完成后使用dive分析镜像非常简单dive镜像名比如分析一个nginx镜像dive nginx:latest启动后你会看到一个分屏的界面左边显示镜像的各个层右边显示当前选中层的文件系统内容。界面操作说明上下箭头键选择不同的镜像层Tab键在左右窗格之间切换焦点空格键展开/收起文件夹CtrlC退出程序深入分析一个臃肿的镜像让我用一个真实的例子来演示。我之前构建了一个Python应用的镜像Dockerfile是这样的FROM python:3.9 WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD [python, app.py]看起来很正常对吧但是构建出来的镜像有1.2G。用dive分析一下dive myapp:latest通过dive分析我发现了几个问题1. 基础镜像选择不当python:3.9这个镜像本身就很大包含了很多我不需要的系统工具和库。dive显示这个基础层就有900多MB。在dive界面中可以看到第一层基础镜像层的大小占了整个镜像的大部分。通过Tab键切换到右侧窗格可以浏览基础镜像包含的文件发现里面有gcc、各种开发工具等等。2. pip缓存没有清理RUN pip install这一层显示增加了300多MB但实际的Python包应该没这么大。进入这一层的文件系统发现/root/.cache/pip目录占用了很大空间。3. 不必要的文件被复制COPY . . 这一层虽然只有几MB但是包含了.git目录、pycache、测试文件等不需要的内容。优化后的Dockerfile基于dive的分析结果我重新编写了DockerfileFROM python:3.9-slim WORKDIR /app # 只复制requirements文件利用Docker缓存 COPY requirements.txt . # 安装依赖并清理缓存 RUN pip install --no-cache-dir -r requirements.txt \ rm -rf /root/.cache/pip # 只复制需要的应用文件 COPY src/ ./src/ COPY app.py . CMD [python, app.py]还添加了一个.dockerignore文件.git .gitignore README.md Dockerfile .dockerignore __pycache__ *.pyc *.pyo *.pyd .Python .pytest_cache .coverage test/ docs/重新构建后用dive分析镜像大小降到了180MB效果非常明显。dive的高级功能效率评分dive会给你的镜像打一个效率分数。在界面底部可以看到类似这样的信息Image efficiency score: 95% Potential wasted space: 12MB这个评分主要基于重复文件的数量每层的大小合理性文件的实际利用率CI/CD集成dive支持在CI/CD流水线中使用可以设置镜像大小和效率的阈值# 设置镜像最大500MB效率最低80%dive myapp:latest--ci\--lowestEfficiency80\--highestWastedBytes500MB如果镜像不符合要求dive会返回非0退出码可以让构建失败。我在公司的Jenkins流水线中就加了这个检查避免有人提交过大的镜像。输出格式dive支持多种输出格式方便集成到其他工具中# JSON格式输出dive myapp:latest--jsonoutput.json# 只显示汇总信息dive myapp:latest--ci--quiet-ci一些实用的分析技巧1. 对比不同版本的镜像经常需要对比优化前后的镜像差异可以分别分析两个镜像dive myapp:v1.0 dive myapp:v2.0通过对比两个版本的层结构和大小变化可以快速定位问题。2. 查看多阶段构建的效果对于多阶段构建的Dockerfiledive特别有用。可以清楚地看到哪些文件被复制到了最终镜像哪些留在了构建阶段。FROM node:16 AS builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:alpine COPY --frombuilder /app/dist /usr/share/nginx/html用dive分析这种镜像时可以看到builder阶段的文件没有进入最终镜像这样确保了镜像的精简。3. 识别安全风险文件在分析镜像时注意查看是否包含了敏感文件比如SSH密钥配置文件中的密码开发工具和调试信息dive可以帮你浏览整个文件系统确保不会意外泄露敏感信息。常见的镜像优化策略通过长期使用dive分析各种镜像我总结了一些常见的优化策略选择合适的基础镜像优先使用slim或alpine版本避免使用latest标签根据实际需要选择版本比如python:3.9-slim 比 python:3.9 小很多node:16-alpine 比 node:16 更精简golang的编译完成后可以用scratch作为运行镜像合并RUN指令每个RUN指令都会创建一个新层合并相关的RUN指令可以减少层数# 不好的写法 RUN apt-get update RUN apt-get install -y git RUN apt-get install -y curl RUN apt-get clean # 好的写法 RUN apt-get update \ apt-get install -y git curl \ apt-get clean \ rm -rf /var/lib/apt/lists/*使用.dockerignore这个真的很重要很多人容易忽略。就像.gitignore一样.dockerignore可以避免把不需要的文件复制到镜像中。清理临时文件在同一个RUN指令中安装软件并清理RUN apt-get update \ apt-get install -y python3-pip \ pip3 install -r requirements.txt \ apt-get remove -y python3-pip \ apt-get autoremove -y \ apt-get clean \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*实际应用中的一些坑1. 删除文件不会减小镜像大小这是很多新手会遇到的问题。如果在一个RUN指令中创建了文件然后在另一个RUN指令中删除文件还是会占用空间。# 错误的做法 RUN wget https://example.com/largefile.tar.gz RUN tar -xzf largefile.tar.gz rm largefile.tar.gz # 正确的做法 RUN wget https://example.com/largefile.tar.gz \ tar -xzf largefile.tar.gz \ rm largefile.tar.gzdive可以清楚地显示这种情况你会看到删除操作创建了一个新层但总大小没有减少。2. COPY指令的顺序很重要Docker的缓存机制是基于层的如果把经常变化的文件放在前面会导致后续的层都需要重新构建。# 不好的顺序 COPY . . RUN pip install -r requirements.txt # 好的顺序 COPY requirements.txt . RUN pip install -r requirements.txt COPY . .3. 多阶段构建的层共享使用多阶段构建时注意不同阶段之间不会共享层每个FROM都会开始新的层计算。dive的一些局限性用了这么久dive也发现了一些局限性对于压缩层的分析不够详细有时候显示的大小与实际略有差异界面操作需要一定的学习成本特别是对于习惯图形界面的同学分析特别大的镜像时加载速度会比较慢不支持直接分析tar格式的镜像文件不过这些问题相对于它带来的价值来说都是小问题。其他类似工具的对比除了dive还有一些其他的镜像分析工具docker-slim这个工具不仅能分析镜像还能自动优化docker-slim build myapp:latest但是自动优化有时候会过于激进可能会删掉必要的文件。container-diffGoogle开源的工具主要用于对比两个镜像的差异container-diffdiffdaemon://image1:tag daemon://image2:tag功能比较专一适合做镜像对比分析。skopeo主要用于镜像的复制和检查也有一些分析功能skopeo inspect docker://nginx:latest相比之下dive在交互性和详细程度方面还是有明显优势的。写在最后镜像优化这个事情说起来简单做起来却需要很多细节的把控。dive这个工具真的帮了我很大忙让镜像分析变得直观和高效。记得第一次用dive的时候那种终于知道问题出在哪里的感觉真的很爽。就像医生给病人做CT扫描一样能清楚地看到镜像的内脏结构。当然工具只是手段关键还是要养成好的构建习惯。合理选择基础镜像、善用.dockerignore、及时清理临时文件…这些看似简单的操作日积月累下来效果是很明显的。如果你也经常被镜像大小困扰强烈建议试试dive。相信我用过之后你就回不去了。最后如果这篇文章对你有帮助的话别忘了点个赞和转发。有任何问题也欢迎留言交流我看到会及时回复的。关注运维躬行录一起在运维的路上精进技艺让每一次部署都更加优雅