我用 Nix 重写 Docker 镜像构建,把镜像从 1.2GB 压到 80MB 且可复现
我用 Nix 重写 Docker 镜像构建把镜像从 1.2GB 压到 80MB 且可复现说实话我一开始是拒绝用 Nix 的。那天我们项目的 Node.js 镜像在生产环境又出问题了——同样是node:20-slim基础镜像同样是package.json没变但 CI 流水线今天编出来 1.2GB昨天编出来 1.18GB。我换了一台机器本地点 build又变成 1.31GB。包版本没动Dockerfile 没动。这一行行拍着脑袋写的RUN apt-get install npm install组合压根就不可复现。最后我赌气把整个构建换成了 Nix。结果镜像 80MB构建时间从 9 分钟压到 4 分 10 秒hash 准准地锁住每次构建的字节级产物。今天聊聊我踩过的坑。为什么默认 Dockerfile 不可复现Dockerfile 不可复现不是玄学是它在三层上都漂浮。第一层基础镜像漂移。node:20-slim每次 pull 拿到的 debian 层都不完全一样apt 源里包的版本每天都在动。apt-get update apt-get install -y libssl-dev这一行今天编出的libssl-dev是 3.0.11明天可能是 3.0.13。它们的依赖链不一致最终镜像 layer 就漂了。第二层包管理器漂移。npm install拿到的依赖版本受package-lock.json约束但npm自身的 patch 版本差异 平台差异glibc vs musl 缓存命中状态都会让node_modules树在字节级别不一致。第三层构建时间漂移。Docker 构建中的RUN步骤是有 side effect 的你装包时多安了个wget改 Dockerfile 删掉但 layer cache 没失效下一次 build 镜像里仍然有wget。这个问题叫 “layer cache poisoning”CI 上半年能炸一次。Nix 解决的就是这三点所有依赖显式声明、源文件哈希校验、构建无副作用。第一次试水把一个 Node.js 服务迁到 Nix我们项目是常见的 Node.js TypeScript 服务目录结构很标准. ├── package.json ├── package-lock.json ├── tsconfig.json ├── src/ └── Dockerfile原来的 Dockerfile 长这样简化版FROM node:20-slim RUN apt-get update apt-get install -y \ python3 python3-pip build-essential \ libssl-dev libffi-dev \ rm -rf /var/lib/apt/lists/* WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build CMD [node, dist/server.js]编出来 1.2GB看一眼 layerdockerhistorymyapp:latest# 1.2GB 总计# - node_modules 占了 540MB# - apt-get 装的 build-essential python3 占了 380MB# - 基础镜像 180MB# - 剩下的产物代码痛点python3和build-essential只是为了node-gyp编译原生模块用的运行时根本不需要但多阶段构建我们没做历史债。我用 Nix 重写后flake.nix是这样的{ description MyApp production image; inputs.nixpkgs.url github:NixOS/nixpkgs/nixos-24.05; outputs { self, nixpkgs }: let pkgs import nixpkgs { system x86_64-linux; }; nodejs pkgs.nodejs_20; # 关键用 mkDerivation 显式声明所有依赖 appEnv pkgs.mkDerivation { name myapp-env; src ./.; nativeBuildInputs [ pkgs.makeWrapper ]; buildInputs [ nodejs pkgs.python3 pkgs.libffi pkgs.openssl pkgs.pkg-config ]; # 关键明确说不需要 devDependencies 在运行时 npmBuildScript build; npmDepsHash sha256-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; # 只把 dist node_modules/production 拷进 $out installPhase mkdir -p $out/lib/myapp cp -r dist $out/lib/myapp/ cp -r node_modules $out/lib/myapp/ # 排除 .map / .ts / 测试文件 find $out/lib/myapp -name *.map -delete find $out/lib/myapp -name *.ts -not -path */node_modules/* -delete find $out/lib/myapp -name test -type d -exec rm -rf {} 2/dev/null || true ; }; # 运行时只保留真正的运行时依赖 runtimeImage pkgs.dockerTools.buildLayeredImage { name myapp; tag latest; contents [ appEnv pkgs.cacert ]; config { Cmd [ /bin/myapp-server ]; Env [ NODE_ENVproduction PATH/bin:/nix/store/.../bin ]; }; maxLayers 100; }; in { images.x86_64-linux runtimeImage; }; }编出来 80MB。看着缩水 93%但请注意这里有个关键点npmDepsHash必须准确。踩坑记录4 条坑 1npmDepsHash 怎么都对不上第一次编Nix 提示error: hash mismatch in fixed-output derivation specified: sha256-xxxxxx got: sha256-yyyyyy原因是npmDepsHash是把package-lock.jsonnode_modules整棵树哈希算出来的。你改了 package.json 没改 hash 必然对不上。但另一个坑是lock 文件里有 install script 的必须给npmDepsHash而不是npmConfigHook。解决办法先随便填一个伪 hash让 Nix 报错并打印真实 hash复制过去# 错误信息里会有一行# got: sha256-abcdef1234567890# 把这个填到 npmDepsHash坑 2原生模块编译失败我们用了sharp图像处理它在 install 时会下载预编译的二进制而不是本地编译。这种包在 Nix 里特别麻烦因为 Nix 默认 sandbox 不开网络。解法用nodePackages.sharp而不是 npm 装。Nixpkgs 里有现成的sharp包装buildInputs [ pkgs.nodejs_20 pkgs.nodePackages.sharp # 用 Nix pkgs 的 sharp不要 npm install sharp ];然后从package.json里删掉sharp依赖运行时从node_modules/sharp改成引用 nix store 路径。坑 3构建时间反而变长了第一次编 12 分钟比原来 9 分钟还慢。原因是 Nix 默认从源代码编译一切连 openssl 都要自己编。解法用官方 binary cache# 用户级配置mkdir-p~/.config/nixcat~/.config/nix/nix.confEOF substituters https://cache.nixos.org https://my-company-cache.example.com trusted-public-keys cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY experimental-features nix-command flakes EOF打开 binary cache 后构建时间直接压到 4 分 10 秒且大部分步骤是下载预编译产物。坑 4Docker 镜像怎么 push 到 KubernetesNix 生成的镜像是一个 tarballdockerTools.buildLayeredImage输出result用docker load加载nix build.#images.x86_64-linuxdockerloadresult# Loaded image: myapp:latest# 或者直接 skopeoskopeo copy docker-archive:result docker://registry.example.com/myapp:v1.0.0CI 集成时改成nix build.#images.x86_64-linux --json | jq -r .[0].outputs.out | xargs -I {} skopeo copy docker-archive:{} docker://registry.example.com/myapp:$CI_COMMIT_SHA复现性验证三个机器编出来 hash 一致这是 Nix 最爽的地方。我让三个工程师在三个不同的机器macOS M2、Ubuntu 22.04、CentOS Stream 9上同时编同一个 commitnix build.#images.x86_64-linux --print-out-paths# macOS M2: /nix/store/xxx-myapp.drv - sha256:abc123# Ubuntu 22.04: /nix/store/xxx-myapp.drv - sha256:abc123# CentOS 9: /nix/store/xxx-myapp.drv - sha256:abc123三条命令输出完全相同的 hash。Dockerfile 时代这是不可能完成的每个机器的 glibc 版本、kernel headers、默认 locales 都不一样编出来的镜像在字节级别必然漂。谁适合用 Nix谁不适合最后聊点大实话。适合用 Nix 的场景安全敏感的供应链金融、密码学、加密通信复现性是硬指标的研究/科学计算monorepo 多语言构建同时有 Go、Node.js、Python、Rust团队被 “works on my machine” 折磨得痛不欲生不适合用 Nix 的场景团队没人懂 Nix学习曲线陡峭Flake 是另一门语言只是小项目、Dockerfile 够用对镜像大小没那么敏感、能接受 1GB 镜像如果你只是想在 Dockerfile 基础上优化distroless 多阶段构建 npm ci --omitdev就够了不必上 Nix。但当你需要signature build——同一个 commit 永远编出同一个字节序列——Nix 几乎是唯一靠谱的解。写在最后Nix 不是银弹但它解决了 Dockerfile 三个根本问题基础镜像漂移、构建副作用、版本不可复现。换完之后我们 CI 出错率从每月 3-4 次降到了 0因为我这跑得好好的这种问题在 hash 一致的前提下根本不存在。完全迁移到 Nix 用了 2 周包括踩坑ROI 大概 3 个月回本节省的 disk 节省的为什么我 build 出来不一样调试时间。有问题评论区交流看到就回。

相关新闻

Spring Boot + Shiro 等保三级复测实战:12行代码修复高危漏洞

Spring Boot + Shiro 等保三级复测实战:12行代码修复高危漏洞

1. 项目背景与核心挑战最近,我们团队负责维护的一套基于Spring Boot和Shiro的医疗信息系统,迎来了等保三级(网络安全等级保护第三级)的年度复测。对于非技术出身的同事可能不太清楚,等保三级是国内非银行机构的最高安全…

2026/7/28 17:05:45 阅读更多 →
Prompt 工程十大误区:从过度设计到缺少评测

Prompt 工程十大误区:从过度设计到缺少评测

Prompt 工程十大误区:从过度设计到缺少评测 基础设施不需要漂亮话。 Prompt 工程被很多人当成一门玄学,也有人觉得它是调参的艺术。实际上 Prompt 工程的核心矛盾是两个:过度设计和缺少评测。过度设计让 Prompt 变得不可维护,缺少…

2026/7/28 17:05:45 阅读更多 →
CollectivIQ推出AI成本管控平台,助力企业精细化管理智能体使用

CollectivIQ推出AI成本管控平台,助力企业精细化管理智能体使用

总部位于波士顿的初创公司CollectivIQ Inc.推出了一款旨在帮助企业管控AI使用成本的平台,让管理者对模型的调用方式拥有更清晰的掌控力。该公司将其产品定位为"AI共识平台"。通过这一平台,管理员可根据员工的职能角色、所属部门、业务需求及预…

2026/7/28 17:05:45 阅读更多 →

最新新闻

终极指南:浏览器端离线语音识别技术深度解析与Vosk-Browser实战

终极指南:浏览器端离线语音识别技术深度解析与Vosk-Browser实战

终极指南:浏览器端离线语音识别技术深度解析与Vosk-Browser实战 【免费下载链接】vosk-browser A speech recognition library running in the browser thanks to a WebAssembly build of Vosk 项目地址: https://gitcode.com/gh_mirrors/vo/vosk-browser 在…

2026/7/28 17:14:47 阅读更多 →
HS2-HF补丁:10分钟打造你的专属Honey Select 2游戏体验

HS2-HF补丁:10分钟打造你的专属Honey Select 2游戏体验

HS2-HF补丁:10分钟打造你的专属Honey Select 2游戏体验 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 你是否曾经因为语言障碍而错过了Honey Selec…

2026/7/28 17:14:47 阅读更多 →
安卓项目测试环境搭建

安卓项目测试环境搭建

文章目录项目简介项目功能为什么要给app客户端签名安装部署后台(后台开发人员负责)数据初始化(后台开发人员负责)运行后台(服务端软件)(后台开发人员负责)修改安卓客户端的配置&…

2026/7/28 17:14:47 阅读更多 →
linux系统的python3.6安装

linux系统的python3.6安装

准备:1.提前配置网络,配置yum源2.提前准备安装包,或者从官网下载(www.python.org)3.安装依赖包4.解压到指定目录编译安装路径及加密方式安装make && make install测试是否能使用(必须进入指定目录)…

2026/7/28 17:14:47 阅读更多 →
SpringMVC整合Mybatis的对象别名设置方式

SpringMVC整合Mybatis的对象别名设置方式

1.在mybatis_config.xml中Mybatis别名设置 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> &…

2026/7/28 17:14:47 阅读更多 →
Outfit字体终极指南:免费开源字体如何解决你的设计一致性难题?

Outfit字体终极指南:免费开源字体如何解决你的设计一致性难题?

Outfit字体终极指南&#xff1a;免费开源字体如何解决你的设计一致性难题&#xff1f; 【免费下载链接】Outfit-Fonts The most on-brand typeface 项目地址: https://gitcode.com/gh_mirrors/ou/Outfit-Fonts 还在为每个项目寻找不同字体而烦恼吗&#xff1f;还在为品牌…

2026/7/28 17:13:47 阅读更多 →

日新闻

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿&#xff01;3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:43 阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑&#xff1a;把几百页的财报、法规、技术手册扔给向量库&#xff0c;问一个具体问题&#xff0c;搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了&#xff0c;要么藏在几十条结果的最下面。语义相似≠真正相关&#xff0c;这个…

2026/7/28 0:00:43 阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营&#xff0c;从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候&#xff0c;每天刷半小时抖音&#xff0c;手动把爆款视频的口播敲进备忘录&#xff0c;一条2分钟的视频得花十来分钟&#xff0c;碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:43 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档&#xff0c;可以直接使用&#xff01;系统支持图片、视频、摄像头等多种方式检测裂缝&#xff0c;功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像&#xff01; pubg绝地求生目标检测数据集 1分类&#xff1a;e_body&#xff0c;14905个标签&#xff0c;txt格式 共计14244张图&#xff0c;99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别&#xff1a; allies enemy tag图片总量&#xff1a;7247张训练集&#xff1a;5139张验证集&#xff1a;1425张测试集&#xff1a;683张标注状态&#xff1a;全部已标注&#xff0c;即拿即用数据格式&#xff1a;支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻