Как записать воспроизводимый профиль в nix (особенно из nix-env)?
Итак, наконец-то я начал получать стабильную среду nix, в которой я могу заниматься практически всеми своими разработками. Ура!
Теперь я хочу сделать его воспроизводимым, как в yarn.lock (для тех, кто знаком с npm / yarn в javascript land) или Pipfile.lock (очень похоже на Python).
По сути, идея заключается в том, чтобы у меня был способ генерировать аналогичный файл блокировки всякий раз, когда я запускаю nix-env -if my-env.nix
или после выполнения этой команды, если это так. Из этого файла блокировки я мог затем точно восстановить свой профиль nix, вплоть до точных версий зависимостей и суб-зависимостей установленного профиля. Это может быть проверено в git или в любом другом месте после тестирования новых улучшений, и поэтому будет поддерживаться запись среды.
Мне кажется, что это будет один из наиболее очевидных вариантов использования Nix и одно из основных преимуществ по сравнению с простым использованием Docker (хотя оба они не являются взаимоисключающими), поэтому я прошу прощения, если пропустил какую-то соответствующую документацию.
2 ответа
То, что вы, вероятно, ищете shell.nix
файл как это:
let
pkgs = import (fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/696c6bed4e8e2d9fd9b956dea7e5d49531e9d13f.tar.gz";
sha256 = "1v3yrpj542niyxp0h3kffsdjwlrkvj0mg4ljb85d142gyn3sdzd4";
}) {};
in pkgs.mkShell {
buildInputs = with pkgs; [
git
hello
];
}
По вызову nix-shell
(который по умолчанию использует shell.nix
файл в текущем каталоге), вы будете в среде с git
а также hello
из конкретной данной ревизии nixpkgs. Это может быть воспроизведено среди всех пользователей nix (хорошо, почти *). Я действительно могу рекомендовать использовать shell.nix
файлы для всей разработки.
Кроме того, есть и менее известные -r
флаг для nix-env
, в котором говорится, что
--remove-all, -r
Сначала удалите все ранее установленные пакеты. Это эквивалентно запуску nix-env -e '.*' В первую очередь, за исключением того, что все происходит в одной транзакции.
Вы можете эффективно использовать его для замены состояний ~/.nix-profile/manifest.nix
, Создать файл env.nix
содержащий:
let
pkgs = import <nixpkgs> {};
in {
inherit (pkgs) git hello;
}
Сейчас работает nix-env -ir env.nix
установит точно git
а также hello
и удалите все остальное, чтобы вы могли воспроизвести ваши установки nix-env с этим единственным файлом. Чтобы установить дополнительные вещи: добавьте его в файл и снова введите команду. Вы также можете прикрепить nixpkgs к определенной версии, как в приведенном выше файле, чтобы не заботиться о вашей nix-channel
установка (которая также с состоянием).
Изменить: Также возможно получить некоторые пакеты из вашего канала и некоторые из конкретных ревизий nixpkgs:
let
pkgs = import <nixpkgs> {};
fixed = import (fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/696c6bed4e8e2d9fd9b956dea7e5d49531e9d13f.tar.gz";
sha256 = "1v3yrpj542niyxp0h3kffsdjwlrkvj0mg4ljb85d142gyn3sdzd4";
}) {};
in {
inherit (pkgs) git;
inherit (fixed) hello;
}
*: Конфигурация nix, оверлеи и ваша система (Linux/Mac) могут по-прежнему влиять на это. Это хорошая идея для использования import <nixpkgs> { config = {}; overlays = []; }
для развития, чтобы избежать этого.
После множества предложений от пользователей IRC я смог собрать следующий скрипт, который принимает выражение nix в качестве единственного аргумента, копирует файл деривации и записывает версии nixpkgs локально при установке указанной среды:
#!/bin/bash
if [ -z "$1" ] || [ "${1: -4}" != ".nix" ] || [ ! -f "$1" ]
then
echo "No .nix file supplied"
exit -1
fi
ENV_DRV=$(nix-instantiate "$1")
cp "$ENV_DRV" ./env_backup.drv
chmod u+rw ./env_backup.drv
nix-env --set "$ENV_DRV"
NIXPKGS_VERSION=$(nix-instantiate --eval '<nixpkgs/lib>' -A version)
NIXOS_VERSION=$(nix-instantiate --eval '<nixos/lib>' -A version)
printf "nixpkgs: %s\\nnixos: %s" "$NIXPKGS_VERSION" "${NIXOS_VERSION}" > .nix_versions
Предостережение: ваше выражение nix должно иметь nix
пакет в нем, так как мы используем nix-env --set
,
Я еще не пробовал использовать скопированный файл.drv, но его нужно каким-то образом восстановить в хранилище nix; Я в основном включил это в качестве крайней меры и для отладки. Выход в .nix_versions
должно быть более полезным, так как они содержат хиты git commit (после последнего "."), которые могут использоваться для использования правильной ревизии nixpkgs (благодаря infinisil на IRC):
pkgs = import "${(import <nixpkgs> {}).fetchFromGitHub { owner = "NixOS"; repo = "nixpkgs"; rev = "<your revision hash>"; sha256 = "<the hash of the output>"; }}" {}
Чтобы заполнить хеш, либо предоставьте неверный хеш, чтобы получить правильный хеш, либо просто используйте следующее: nix-prefetch-url --unpack github.com/nixos/nixpkgs/archive/<revision>.tar.gz
,
Или, если вы вручную проверяете nixpkgs, вы можете просто сделать, например:
with import ((builtins.getEnv "HOME") + "/workspace/nixpkgs") { }; # or:
with import "../nixpkgs" { }; # or similar
Я не проверял такого рода вещи с nix-shell
пока, но надеюсь сделать это в ближайшее время.