Docker Composeを捨ててNixに移行したら開発環境の悩みが全部消えた

$ |
Docker Composeを捨ててNixに移行したら開発環境の悩みが全部消えた
$

Docker Composeに疲れた

Docker Compose、もう何年使ったか分からない。でもある日気づいた。「開発環境の構築にDockerfile書いて、docker-compose.yml書いて、.envファイル管理して、ボリュームのパーミッション問題に悩んで、M1 Macでamd64イメージが遅くて...」これ、本質的な開発作業じゃなくない?

そう思ってNixに手を出した。結論から言うと、開発環境の悩みが全部消えた

Nixとは何か — 再現性の鬼

Nixはパッケージマネージャー兼ビルドシステム。最大の特徴は「宣言的」かつ「再現可能」なこと。同じflake.nixから同じ環境が100%再現される。

# flake.nix
{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  outputs = { nixpkgs, ... }: {
    devShells.default = nixpkgs.legacyPackages.x86_64-linux.mkShell {
      packages = with nixpkgs.legacyPackages.x86_64-linux; [
        nodejs_20
        postgresql_16
        redis
      ];
    };
  };
}

nix develop一発で、Node.js 20、PostgreSQL 16、Redisが使える環境が立ち上がる。Dockerイメージのビルド不要。

Docker Composeとの決定的な違い

Docker Composeは「コンテナの中に環境を閉じ込める」アプローチ。Nixは「ホストマシンに正確な環境を構築する」アプローチ。この違いがデカい。コンテナのオーバーヘッドがないから速い。ファイルウォッチもネイティブ速度。ホットリロードが一瞬で反映される。

devenvで更に楽になる

Nix単体だと設定がまだ面倒。そこでdevenvを使う。

# devenv.nix
{ pkgs, ... }: {
  languages.typescript.enable = true;
  services.postgres = {
    enable = true;
    initialDatabases = [{ name = "myapp"; }];
  };
  services.redis.enable = true;
  processes.dev.exec = "npm run dev";
}

これでdevenv upするとPostgreSQLとRedisとdevサーバーが全部起動する。Docker Composeと同じ使用感で、コンテナのオーバーヘッドがない。

Nixの弱点と移行判断

学習コストは正直高い。Nix言語は独特で最初は戸惑う。あとLinux以外(特にmacOS)だとNixパッケージのビルドが遅いことがある。チーム全員がNixを受け入れるかという政治問題もある。でも一度セットアップすれば「新メンバーがjoinしてから開発開始まで5分」が実現する。この体験、Docker Composeでは無理だった。