Uncategorized

個人開発で感じたNixの可能性と実務導入の距離感

はじめに

はじめまして。社内唯一のVimmer西川です。

最近、個人開発で Nix を使い始めて、開発環境をコードで管理できる体験に感動しています。

私は個人の OSS 開発で Rust / TypeScript / JavaScript / Python などを使っており、Cargo クレートや npm パッケージを作ることがあります。複数の言語やツールを扱っていると、Node、Rust、Python、CLI ツール、Vim 周りの設定などが少しずつローカル環境に積み重なっていきます。

さらに、昔使っていた MacBook Pro と M4 Mac mini を併用していることもあり、複数マシン間で環境を揃える難しさも感じていました。

今振り返ると、M4 Mac mini を購入したタイミングで、NixOS 的な「環境全体を宣言的に管理する考え方」をもっと早く取り入れていればよかったと思っています。

一方で、個人開発で便利だったものを、そのまま実務プロジェクトに持ち込めるとは限りません。

そこで今回は、Docker + Docker Compose をベースにした既存プロジェクトに対して、Nix を活かすならどこまで現実的なのかを整理してみました。

今回のテーマは、

Nixを導入するかどうかではなく、Dockerベースの実務開発でどこまで活かせそうか

です。


これまでの開発で感じていた課題

※ この章は、これまで関わった複数プロジェクトでの経験をまとめたものです。本プロジェクト固有の問題ではありません。

これまでの開発では、以下のような環境差分に悩むことがありました。

  • Mac / Windows で Docker ビルドが通らない
    • Apple Silicon と x86 の差異
  • Windows 環境で Docker 周りが不安定になる
    • WSL2 上の Docker と Docker Desktop の構成差
  • ホスト側パッケージの差異
    • Node / Composer / npm / pnpm / cargo などのバージョン差
  • README 通りに進めても環境によって結果が変わる

ここから感じたのは、

Dockerがあっても、ホスト環境の差分は残る

ということです。

Docker はアプリケーションの実行環境を揃えるには強力ですが、Docker を起動する前のホスト側ツールや OS 設定までは完全には管理してくれません。


AI開発時代に環境をコード化する意味

最近は AI を使ってコードを書く機会も増えています。

AI は構文やライブラリの使い方をかなり補助してくれます。一方で、プロジェクトが前提としている実行環境やツールチェインが曖昧だと、生成されたコードを動かす段階で詰まることがあります。

たとえば、以下のような情報です。

  • Node / Rust / Python / Go のバージョン
  • npm / pnpm / Composer / cargo の使い分け
  • 必要な CLI ツール
  • ローカル証明書や hosts 設定

こうした情報が README や個人の記憶に依存していると、人間にも AI にも扱いづらい状態になります。

その点で、Nix の価値は単なるパッケージ管理ではなく、

開発環境そのものをプロジェクトの一部として管理できること

にあると感じています。


本プロジェクトの現状

本プロジェクトでは、Docker + Docker Compose により、以下の実行環境がコンテナ化されています。

  • MySQL
  • NestJS
  • React + Vite
  • nginx

そのため、アプリケーションの実行環境は基本的に再現可能です。

一方で、セットアップ手順やコードを見ると、Docker の外側に以下の依存が残っていました。

依存用途
Docker / Docker Composeコンテナ起動
mkcertローカル証明書生成
bashスクリプト実行
hosts編集ドメイン解決
loopback設定ローカルIPバインド
gitclone

※ 本プロジェクトでは Node.js はコンテナ内で完結しており、ホスト側の Node バージョン差異は基本的に問題になりません。

つまり、本プロジェクトでの論点は Docker を置き換えることではなく、

Dockerの外側に残っているホスト依存を、Nixでどこまで減らせるか

です。


Dockerで解決できていない部分

Docker により実行環境は統一されていますが、ローカル開発では以下のようなホスト依存の操作が残ります。

  • hosts ファイルの編集
  • mkcert による証明書生成と OS ストアへの登録
  • loopback 設定
  • .env の作成
  • ポート競合の確認
  • Docker Desktop / WSL2 などのローカル構成差

つまり、

Dockerは実行環境を揃えるが、OSレイヤーの操作までは揃えない

という整理になります。

これは Docker の欠点というより、責務の違いです。


Nixでできること

Nix を使うと、開発に必要なツールを flake.nix に宣言できます。

本プロジェクトで直接効果がありそうなのは、以下のようなホスト側 CLI の固定です。

  • mkcert
  • curl
  • bash
  • MySQL 接続確認用ツール
  • その他、開発補助 CLI

一方で、別プロジェクトのように Node や Composer をホスト側で使う構成では、Nix の効果はさらに大きくなります。

たとえば、以下のような差分です。

  • Node バージョン差異
  • Composer の依存解決差異
  • Rust / Python / Go など複数言語のツールチェイン差異
  • npm / pnpm / cargo などの CLI 差異

こうした問題は、Nix によって減らせる可能性があります。

個人開発では、nix develop でプロジェクトごとに必要なツールを切り替えられる点が特に便利だと感じています。グローバル環境を汚さず、プロジェクト単位で開発環境を持てるのは大きなメリットです。


Nixでも解決できないこと

一方で、Nix を入れても解決できないこともあります。

  • hosts 編集の権限問題
  • OS の証明書ストアへの CA 登録
  • Docker Desktop / WSL2 の構成差
  • OS ごとのネットワーク設定
  • .env のシークレット値管理

.env.example から .env を生成する補助はできますが、シークレット値や各自のローカル設定値をどう管理するかは、Nix だけで完結する話ではありません。

また、Windows で Nix を利用する場合、現実的には WSL2 上での運用が前提になりやすいです。そのため、WSL2 と Docker Desktop の構成に起因する問題は、Nix を導入してもそのまま残る可能性があります。

つまり、

Nixはホスト側ツールチェインの再現性を高めるが、OS設定まですべて抽象化するものではない

という理解が必要です。


設計としての落としどころ

Dockerベースの実務プロジェクトにNixを当てはめるなら、以下のような役割分担が現実的だと考えました。

上記を整理すると、Docker・Nix・OS設定の役割は以下のように分けられます。

※ ここに図を差し込む想定です。

領域管理方法
アプリ実行環境Docker
DB / nginx などDocker
開発ツールNix
OS設定手動

もし小さく試すなら、まずは以下のようなツールをNix管理の候補にできそうです。

  • mkcert
  • curl / bash などの CLI
  • 必要に応じた DB 接続確認用ツール

一方で、Docker CLI や Compose は Docker Desktop / Docker Engine 側に寄せ、Nix の管理対象からは外します。

重要なのは、

NixはDockerの代替ではなく、Dockerの外側を補う選択肢

ということです。

Docker がすでに担っている領域まで Nix で置き換える必要はありません。Docker の外側に残っているホストツール管理を Nix で補う方が、導入コストと効果のバランスが良いと考えています。


flake.nixの最小例

以下は、開発ツールを Nix で管理するための最小例です。

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";

  outputs = { self, nixpkgs, ... }: {
    devShells.x86_64-linux.default =
      let
        pkgs = nixpkgs.legacyPackages.x86_64-linux;
      in
      pkgs.mkShell {
        packages = [
          pkgs.mkcert
          pkgs.curl
          pkgs.bash
          # DB接続確認用ツールは利用するnixpkgsに応じて別途追加
        ];
      };
  };
}
この例は x86_64-linux 前提です
Mac で使う場合は aarch64-darwin / x86_64-darwin の追加または flake-utils などを使った複数 platform 対応を検討します
docker-compose  Compose v2 の扱いを考慮しこの例では Nix 管理対象から外しています

ただし、会社のプロジェクトでは最初から広げすぎず、まずは flake.nix による devShell から始めるのが現実的だと思います。


結論

今回整理してみて、Dockerベースの実務開発に対してNixを活かすなら、いきなり全面導入するよりも、ホスト側ツール管理から小さく試すのが現実的だと感じました。

Dockerは実行環境の再現性を担保してくれます。一方で、mkcert、curl、bash、DB接続確認用ツールなど、Dockerの外側にある開発補助ツールはホスト環境に依存しがちです。

Nixはその領域をコード化し、開発者間の差分を減らす手段になり得ます。

ただし、hosts編集、CA登録、Windows / WSL2 の構成差、.env のシークレット管理まではNixだけでは解決できません。

そのため、現時点では、

Dockerを置き換えるのではなく、Dockerの外側に残るホストツール管理をNixで補う

くらいの距離感が、実務導入の第一歩としてちょうどよさそうです。


おわりに

個人開発で Nix を使ってみて、環境を宣言的に管理できることには大きな可能性を感じています。

特に、複数マシンを使う場合や、Rust / TypeScript / Python / Go など複数言語を扱う場合、プロジェクトごとに環境を固定できるのは非常に便利です。

一方で、実務プロジェクトでは「便利だから全部入れる」ではなく、

どこに導入すると効果があり、どこから先は運用コストが高いのか

を見極める必要があります。

今回の結論は、Docker と Nix のどちらが優れているかではありません。

  • Docker → 実行環境
  • Nix → 開発ツール環境
  • OS → 最後に残る依存レイヤー

このように役割を分けることで、無理なく開発環境の再現性を高められると感じました。

おすすめ記事

Recommend