饮墨

子安饮墨馀三斗,留与卿儿作赋来

Devbox 实战:用 Nix 打造可复现开发环境,彻底告别"在我电脑上能跑"

痛点

运维团队最怕的场景之一:新人入职花两天配环境,CI 流水线因为系统库版本不一致挂掉,开发说"我本地没问题"但生产环境 Python 3.11 和 3.12 行为差异导致故障。

传统方案各有缺陷:

方案 问题
Dockerfile 开发环境 启动慢、磁盘占用大、IDE 集成差
Vagrant 资源消耗大、启动分钟级
asdf/mise 版本管理 只管语言版本,不管系统依赖
直接装 Nix 学习曲线陡峭,nix expression 语法劝退

Devbox 是 Jetify 开源的工具,基于 Nix 包管理但完全隐藏 Nix 复杂语法,用一个 devbox.json 声明所有依赖,一条命令进入隔离环境。

核心方案

Devbox 的设计思路:Nix 的可复现性 + 零学习成本的 CLI 体验

  • 每个项目一个 devbox.json,声明式定义所需工具和版本
  • 基于 Nix Store 实现依赖隔离,不污染宿主系统
  • 自动生成 devbox.lock 锁定依赖哈希,确保跨机器一致性
  • 支持 init hooks 和 scripts,可替代 Makefile 常用任务
  • 原生支持生成 Dockerfile 和 Devcontainer 配置

实操步骤

第一步:安装 Devbox

# Linux/macOS 一键安装
curl -fsSL https://get.jetify.com/devbox | bash

# 验证安装
devbox version

安装仅添加一个二进制文件,Nix 会在首次使用时自动安装。

第二步:初始化项目环境

以一个典型的 Python + PostgreSQL + Redis 运维项目为例:

cd /path/to/your-ops-project

# 初始化 devbox 配置
devbox init

# 添加依赖包(自动从 Nixpkgs 搜索)
devbox add python@3.12 postgresql_16 redis nodejs@20 awscli2 kubectl

# 查看当前配置
cat devbox.json

生成的 devbox.json

{
  "packages": [
    "python@3.12",
    "postgresql_16",
    "redis",
    "nodejs@20",
    "awscli2",
    "kubectl"
  ],
  "shell": {
    "init_hook": [
      "echo '🚀 Ops environment ready!'",
      "python -m venv .venv --prompt ops 2>/dev/null || true",
      "source .venv/bin/activate"
    ],
    "scripts": {
      "test": ["pytest -v"],
      "lint": ["ruff check . --fix"],
      "db:start": ["pg_ctl -D .devbox/pgdata -l .devbox/pg.log start"],
      "db:stop": ["pg_ctl -D .devbox/pgdata stop"]
    }
  }
}

第三步:进入隔离环境并使用

# 进入 devbox shell(首次会下载 Nix 包,后续秒开)
devbox shell

# 验证版本隔离 — 这些命令只在 devbox shell 内可用
python --version   # Python 3.12.x
psql --version     # psql (PostgreSQL) 16.x
redis-server --version
kubectl version --client

# 运行定义的 scripts
devbox run test
devbox run db:start

# 退出环境
exit

关键点:宿主系统完全不受影响。退出 shell 后,这些工具"消失"(实际在 Nix Store 中但不在 PATH)。

第四步:集成到 CI/CD

Devbox 在 CI 中可直接复用同一份配置,确保 CI 和本地环境完全一致:

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: jetify-com/devbox-install-action@v0.12.0
        with:
          enable-cache: true
      - run: devbox run test
      - run: devbox run lint

也可以生成 Devcontainer 配置供 VS Code Remote 使用:

# 自动生成 .devcontainer/devcontainer.json
devbox generate devcontainer

# 生成 Dockerfile(用于生产构建基础镜像)
devbox generate dockerfile

避坑指南

1. 首次安装 Nix Store 下载慢

Devbox 首次使用会安装 Nix 并下载包到 /nix/store,国内网络可能较慢。

解决: 配置 Nix 二进制缓存镜像或使用 Jetify Cloud 缓存:

# 设置国内镜像(如 USTC)
mkdir -p ~/.config/nix
echo 'substituters = https://mirrors.ustc.edu.cn/nix-channels/store https://cache.nixos.org/' > ~/.config/nix/nix.conf
echo 'trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=' >> ~/.config/nix/nix.conf

2. devbox.lock 必须提交到 Git

devbox.lock 文件记录了每个包的精确 Nix hash,不提交会导致团队成员拿到不同版本。

# 确保 lock 文件被跟踪
git add devbox.json devbox.lock

类似 package-lock.json 的逻辑 — json 声明意图,lock 锁定事实

3. 与现有 Docker 工作流并存

Devbox 不取代 Docker 用于生产部署,它解决的是开发和 CI 环境一致性。推荐分层使用:

  • 开发环境:Devbox(快速、轻量、IDE 友好)
  • CI 构建:Devbox(确保与本地一致)
  • 生产部署:Docker/K8s(隔离性、编排能力)

可以用 devbox generate dockerfile 生成的 Dockerfile 作为生产镜像的 build stage,复用同一份依赖声明。

与其他方案对比

维度 Devbox Docker Dev mise/asdf 原生 Nix Flake
启动速度 秒级(缓存后) 秒~分钟 秒级 秒级
系统依赖管理 ✅ 全覆盖 ✅ 全覆盖 ❌ 仅语言 ✅ 全覆盖
学习成本 低(JSON配置) 中(Dockerfile) 高(Nix 语法)
IDE 集成 原生支持 需 Remote 原生支持 需插件
可复现性 强(Nix hash) 中(层缓存)
磁盘占用 中(Nix Store 共享) 高(每镜像独立)

总结

Devbox 解决了一个老生常谈但始终恼人的问题:开发环境的可复现性。它的核心价值在于:

  1. 零摩擦采用 Nix — 不需要学 Nix 语法,一个 JSON 文件搞定
  2. 全栈依赖管理 — 不只是语言版本,系统库、CLI 工具全部声明式管理
  3. CI/本地一致 — 同一份 devbox.json 在本地和 CI 跑出相同结果
  4. 团队协作友好 — 新人 clone 仓库后 devbox shell 一条命令就绑

适合场景:多人协作项目、涉及多语言/多工具的运维项目、需要精确控制依赖版本的 CI 流水线。不适合:纯容器化的微服务生产部署(这仍是 Docker/K8s 的主场)。

项目地址:github.com/jetify-com/devbox

您还没有登录,请登录后发表评论。