🐙

Nixで始める再現可能な開発環境:DockerやIaCとの違い

に公開

概要

Nixについて、覚書も兼ねてまとめてみました。
Nixは強力なツールですが、その広範な適用範囲がかえって理解を難しくしています。
本記事では、Nixの中でも特にパッケージマネージャーとしてのNixに焦点を当て、DockerやIaC(Infrastructure as Code)と比較しながらその特徴や使い方を解説します。

Nixとは?

Nixは、ソフトウェアや環境構成を宣言型で管理するためのツールです。
「Nix」という名前が指す範囲は広く、以下のような機能が含まれます。

  1. Nix パッケージマネージャー
    ソフトウェアや開発環境を再現可能にするツール。たとえば、TypescriptやRubyの環境を同じ構成で複数の開発者が共有できます。
  2. NixOS
    Nixを基盤としたLinuxディストリビューション。OS設定を宣言型で管理し、簡単にロールバックが可能です。
  3. Nix Flakes
    プロジェクトや開発環境をさらに柔軟に管理するための拡張機能。依存関係の固定や環境の簡易共有に役立ちます。
  4. Home Manager
    ユーザーごとの設定(シェル、エディタ、テーマなど)をコードで一元管理できます。

Dockerとの違い

DockerとNixはどちらも開発環境の分離や再現可能性を提供しますが、その適用対象とアプローチには大きな違いがあります。

DockerとNixの役割

  • Dockerは、アプリケーションやサービスを実行するための仮想化コンテナを提供します。これにより、ホストシステムと独立した環境を構築し依存関係の衝突を防ぎます。
  • Nixは、ソフトウェアや開発環境を構成する依存関係をコード化して管理します。環境全体を再現可能な形でホストシステム上で直接動作させるのが特徴です。

目的の違い

  • Docker:
    仮想化コンテナを活用し、アプリケーションやその依存関係を完全に独立した環境で動作させます。
    例えばNode.jsアプリケーションをDockerで動かす場合、DockerfileにNode.jsランタイムや必要なライブラリを記述し、コンテナを作成して実行します。

  • Nix:
    ソフトウェアや開発環境をコードで定義し、再現可能な形でホストシステム上で直接動作させます。
    flake.nixを使えば、Node.jsとRubyが共存する環境を簡単に定義し、全員が同じ環境を共有できます。

比較表

特徴 Docker Nix
分離方法 仮想化コンテナでホストシステムから独立 /nix/storeを使用して環境を分離
再現可能性 Dockerfileで定義したイメージ Nixファイルで環境全体を宣言
軽量性 仮想化によるオーバーヘッドあり 仮想化なしで直接動作し軽量
利用範囲 アプリケーションやサービスの動作環境 開発ツール、依存関係、システム全体の管理
切り替えの容易さ コンテナごとに手動で起動・停止が必要 nix developで瞬時に切り替え可能

IaCとの違い

NixはIaC(Infrastructure as Code)と同様にインフラストラクチャの管理をコードで行いますが、適用対象が異なります。

比較表

特徴 Terraform / Ansible Nix
適用対象 仮想マシンやネットワークなどのインフラ 開発環境やソフトウェアの依存関係
宣言型 インフラのリソースの状態を記述 コードでソフトウェアや環境を記述
自動化対象 インフラリソースの作成・運用・削除 開発環境の構築・切り替え
再現可能性 仮想リソース単位で再現可能 環境全体を再現可能

違いの具体例

  • TerraformやAnsible:
    AWSやGCPで仮想マシンやネットワークを管理するために使用します。
    例えばTerraformでEC2インスタンスを作成し、Ansibleでその上にNginxをインストールする。

  • Nix:
    仮想マシン上で動作するソフトウェアや開発環境を再現可能に管理します。
    例えば、EC2インスタンス上でNixを使用して、Node.jsやRuby環境を正確に構築します。

Nixパッケージマネージャー

Nixを使ってNode.jsやRubyの開発環境を構築する例になります。

構成ファイル: flakes.nix

以下の例では、Node.js、Ruby、Git、Yarnを含む開発環境を構築しています。

{
  description = "Development environment for Node.js and Ruby";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.05";
    
  outputs = { self, nixpkgs }: {
    devShell = nixpkgs.mkShell {
      buildInputs = [
        nixpkgs.nodejs # Node.js
        nixpkgs.ruby   # Ruby
        nixpkgs.git    # Git
        nixpkgs.yarn   # Yarn
      ];
    };
  };
}

環境の利用

nix develop

このコマンドを実行すると、Node.jsやRubyを含む環境に入ることができます。
環境を切り替える場合も、flake.nixを別のプロジェクトで作成すれば簡単に実現可能です。

Nixのメリットと限界

メリット

  1. 再現可能性: すべての依存関係をコードで管理し、どの環境でも同じ状態を再現可能。
  2. 柔軟性と分離性: 仮想化を使わずに環境を分離し、軽量で高速に動作。
  3. 柔軟性: 開発環境に限らず、システムやユーザー設定なども管理できる。

限界

  1. 学習コスト: Nixの独自の概念や仕組みを理解するための学習コストが高い。
  2. エコシステム: パッケージ管理において、Nixのエコシステムが必須であるが規模が小さい。

まとめ

Nixは、DockerやIaCの代わりになるものではなく、役割の異なるツールとして補完関係にあります

  • Docker:
    アプリケーションやその依存関係を分離し、異なる環境で同じ動作を保証する。
    適している場面:

    • 本番環境でサービスをデプロイしたい場合。
    • 開発環境と本番環境を独立させたい場合。
  • IaC:
    インフラストラクチャの構成やリソースの管理をコードで宣言的に行うためのツール。
    適している場面:

    • クラウド上で仮想マシンやネットワークを管理したい場合。
    • インフラストラクチャの構成管理を自動化したい場合。
  • Nix:
    開発環境やソフトウェアの依存関係を再現可能かつ分離された形で管理し、ホストシステムに直接適用します。
    適している場面:

    • チームで統一された開発環境を構築・共有したい場合。
    • 仮想化なしで軽量な環境管理を実施したい場合。
株式会社スタメン

Discussion