Open9

Nix入門

takeashiptakeaship

おうちk8sサーバーをmini PC上にNixで構築したいという動機で、Nixに入門することに。
WSLの開発環境もNixで構築し、PC変更時の可搬性を高めたい。

takeashiptakeaship

Nixの特長

Reproducible

Nixのパッケージは暗黙的な依存関係を持たないことが保証されている。
Prerequisitesに従いパッケージインストール前に手動であれこれ入れる必要がない。
あるマシンで動作するパッケージは、別のマシンでも一発で動作する。

Declarative

Nix言語で定義を記述すれば、その通りに環境構築してくれる。
Dockerfileのようにビルド手順を順に記述する必要がない。

Reliable

パッケージをアップグレードしても環境が壊れないことが保証されている。
Immutableなパッケージ、パッケージ構成を持つことで、アップグレードに伴う依存関係問題の発生を避けている。

takeashiptakeaship

Nixpkgsについて

  • 公式ストアで、OSSのパッケージリポジトリで最もパッケージ数が多い
  • 唯一のストアという位置づけではなく、Nixpkgsを介さずともパッケージを自由に公開・利用できる
takeashiptakeaship

純粋関数型

入力に対し常に出力が一意に定まり、副作用がなく、入力以外の外部要素に影響を受けない。
Nixはサンドボックス環境を利用することで、純粋関数型のビルドを実現している。

サンドボックス環境にはls等の基本的なコマンドすら存在せず、明示的な指定が必要。
インターネットアクセスも原則禁止。
Fetcherで、ダウンロードするリソースのハッシュを事前に指定しておき、異なる場合は即座に失敗させるようになっている。

takeashiptakeaship

Nixストア

Nixによるビルド生成物を格納するパスにビルド入力のハッシュ値を含めることで(ストアパス)、同じパッケージでもバージョンやビルドごとにディレクトリが分かれ、上書きが発生しない。これによりimmutableを保つ。

ビルドの入力は全てストアパスで指定することで完全な依存関係ツリーを構築する。

ガベージコレクション

ストアパスによりストレージの肥大を防止する仕組み。
どのProfileからも参照されていないパッケージは自動で削除される。
完全な依存関係ツリーが把握されているからこそ可能な仕組み。
手動でのアンインストールは不要になるため、存在しない。

決定的ビルド

純関数型であることで、同じビルド入力に対し同じビルド成果物が出力されることが保証されている。
このため、同じストアパスが生成される場合はビルドをスキップするキャッシュが可能になる。

takeashiptakeaship

バイナリキャッシュ

ローカルストアに加えてSubstituterと呼ばれるストアを使える。
Subsutituterにもいくつか種類があるが、ネットワーク越しにビルド成果物をfetchできるHTTPやS3ストアを使うと本領発揮する。
決定的ビルドのため、ビルド入力が同じならば、手元でビルドしても他のPCでビルドしたものをfetchしても同じ結果が得られるためである。
予め他のPCでビルドしたものをネットワーク越しに利用することができる。

リモートビルド

どのPCでビルドしても結果が同じであることを利用し、
よりスペックの高いマシンにビルドを委譲することでビルド時間を短縮できる仕組み。

takeashiptakeaship

Nixpkgs

Nixpkgsそのものが一つのNix式になっている
パッケージのビルド用関数を収録したNix言語のライブラリとでも言うべきもの

ビルドヘルパー

  • イメージ
    dockerTools.buildImage関数を使って、dockerfileの記述なしにDockerイメージをビルドできる
    Nixで環境構築すると、docker用にあれこれ整えなくてもそのままdockerイメージにできるということ

  • 言語の個別対応
    様々な言語やフレームワークのパッケージをNixpkgとしてビルドするビルド用ユーティリティ関数がある
    poetry2nixなど

takeashiptakeaship

Flakes

Nixpkgs自体がNixのライブラリ
FlakesはNixの高レベル表現世界における依存関係管理
最初にNix式の評価でFlakesがNix言語の依存関係を解決
そうして生成されたderivationの依存関係をNixストアが解決

inputs

flakeのURL、ファイルパスなどを指定する
FlakeHubというFlakeのアーカイブ共有プラットフォームがある

Outputs

outputsに指定した関数がそれをinputsに指定したflakeの引数に渡される