nix-buildでコンテナイメージを作る際の諸注意
雑多にメモ
このテンプレートを元にしたコンテナ定義は次のようにすると docker へ読み込める
$ nix-build image.nix -o image.tar.gz
$ docker load < image.tar.gz
code:image.nix
{
pkgs ? import <nixpkgs> {},
}:
with pkgs;
dockerTools.buildImage rec {
# ここは docker registry へ登録するフォーマットで記述する
name = "example.tld/name/container";
# これは docker container のタグと等価
tag = "v1";
# buildEnv で rootfs を作る
copyToRoot = buildEnv {
# まぁ名前は適当に
inherit name;
# 【重要ポイント】
# busybox はコンテナをデバッグする時に便利(だが実際にはオプション)
# **cacert は TLS 通信をする場合には必須・これが入ってないと Certificates の検証に失敗する**
paths = [
busybox
cacert
];
# 【重要ポイント】
# これは /nix/store 以下の $out/bin や $out/share を rootfs に集約する設定
# /bin は実行ファイルのパスをまとめる際に使う
# **/etc は cacert を必要する場合に必須・これも無いと Certificates の検証に失敗する**
pathsToLink = [
"/bin"
"/etc"
];
# postBuild でコンテナイメージの最終調整をする
postBuild = let
# 【重要ポイント】
# /etc/passwd と /etc/group はコンテナイメージに含まれないので適当に作る
# fly.io の場合、これらのファイルが無いと kernel panic するので必須
passwd = writeText "passwd" ''
root:x:0:0:root:/root:/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/sbin/nologin
'';
group = writeText "group" ''
root:x:0:
nobody:x:65534:
tty:x:5:
'';
in ''
# 【重要ポイント】
# fly.io では WorkDir が存在しないと、常に No such file or directory というエラーを吐く
mkdir -p $out/var/lib/workdir
# /etc は /etc/passwd と /etc/group をコピーするために作る
mkdir -p $out/etc
cp ${passwd} $out/etc/passwd
cp ${group} $out/etc/group
# 【重要ポイント】
# ファイルを読み書きする際、/tmp が無いと I/O error を吐いて動かないソフトウェアなどがある
# 例えば GoToSocial では SQLite3 を DB として使っている場合にこの問題が起きる
mkdir -p $out/tmp
'';
};
config = {
# 環境変数の設定
Env = [
# とりあえず PATH は通しましょう
"PATH=/bin"
];
# 【重要ポイント】
# WorkDir には **実在する** コンテナ内ディレクトリを指定すること
# fly.io の場合、これに反すると実行時において常に No such file or directory エラーが出る
WorkDir = "/var/lib/workdir";
# EntryPoint の設定。これは Docker contianer などと同じ
};
};