一般社団法人 全国個人事業主支援協会

COLUMN コラム

  • Nixによる再現可能な開発環境構築:Docker代替としての可能性

「自分のマシンでは動くのに」問題を根本解決する

開発チームが大きくなるにつれ、開発環境の差異に起因するトラブルは増加の一途をたどります。「自分のマシンでは動くのに」という言葉を聞いたことがないエンジニアはいないでしょう。Dockerはこの問題を大きく改善しましたが、Dockerfileのメンテナンスやビルド時間の長さに悩むチームも少なくありません。

そこで注目されているのがNixです。Nixは純粋関数型のパッケージマネージャでして、再現可能なビルドと開発環境構築を実現します。本記事では、Nixの基本概念からDocker代替としての実用性まで、実務経験を踏まえて解説します。

Nixの基本概念を理解する

Nixの根幹にあるのは「純粋性」と「再現性」です。すべてのパッケージはハッシュで管理され、同じ入力からは必ず同じ出力が得られます。従来のパッケージマネージャのようにグローバルな状態を変更することはありません。

Nix言語の基礎

Nixは独自の関数型言語(Nix Expression Language)を使ってパッケージや環境を定義します。

# 基本的なNix式の例
let
pkgs = import <nixpkgs> {};
in
pkgs.mkShell {
buildInputs = [
pkgs.nodejs_20
pkgs.python311
pkgs.postgresql_15
];

shellHook = ''
echo "開発環境が準備されました"
export DATABASE_URL="postgresql://localhost/myapp_dev"
'';
}

この設定をshell.nixとして保存し、nix-shellコマンドを実行するだけで、Node.js 20、Python 3.11、PostgreSQL 15が揃った環境が立ち上がります。チーム全員が完全に同一のバージョンを使うことが保証されます。

Flakesで再現性をさらに強化する

Nix Flakesは、Nixの再現性をさらに向上させる実験的機能です。ロックファイルにより依存関係のバージョンを完全に固定できます。

# flake.nix
{
description = "My project development environment";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
flake-utils.url = "github:numtide/flake-utils";
};

outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.default = pkgs.mkShell {
packages = [
pkgs.go_1_22
pkgs.gopls
pkgs.golangci-lint
pkgs.docker-compose
];
};
}
);
}

nix developコマンドを実行すると、flake.lockに記録されたリビジョンのパッケージが使われます。半年後に新しいメンバーが参加しても、全く同じ環境を再現できるのは大きなメリットです。

direnvとの組み合わせで自動化する

実際の開発ではnix-direnvとの連携が非常に便利です。プロジェクトディレクトリに入ると自動的にNix環境が有効化されます。

# .envrc
use flake

たったこの一行を.envrcに書くだけです。cdでプロジェクトに移動すると自動的に環境が切り替わり、離れると元に戻ります。複数プロジェクトを掛け持ちするエンジニアにとって、これは非常に快適な体験です。

Docker代替としての現実的な評価

NixはDockerの完全な代替になるかというと、正直なところケースバイケースです。開発環境の構築に関しては、Nixの方が優れている場面が多いと感じます。

Nixが優れている点

  • 起動速度:コンテナのオーバーヘッドがなく、ネイティブ速度で開発ツールが動作する
  • キャッシュ効率:パッケージ単位でキャッシュされるため、1つの変更で全体の再ビルドが不要
  • ホストOSとの親和性:ファイルシステムの共有問題(Dockerのvolume性能問題)がない
  • 依存関係の透明性:何がインストールされているかが宣言的に明確

Dockerが依然として有利な点

  • 本番環境との一致:本番でコンテナを使うなら、開発もコンテナの方が一貫性がある
  • チームへの浸透度:Dockerの方が圧倒的に知名度が高く、学習コストが低い
  • Linux以外の対応:macOSでのNixはやや不安定な部分が残る

実務での導入アドバイス

筆者のチームではDockerとNixを併用しています。データベースやメッセージキューなどのミドルウェアはDocker Composeで管理し、開発ツール(言語ランタイム、リンター、フォーマッタなど)はNixで管理するハイブリッド構成です。

Nixの最大の障壁は学習曲線の急さです。Nix言語の独特な構文やエラーメッセージの分かりにくさは、導入初期に多くのチームが苦戦するポイントです。まずはシンプルなshell.nixから始め、チームが慣れてきたらFlakesに移行するステップを踏むことをおすすめします。

再現可能な開発環境は、長期的なプロジェクトの生産性を確実に向上させます。NixはDockerを置き換えるものではなく、補完するツールとして活用するのが現時点での最善策でしょう。

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア