在Nix模块中构建Docker镜像Derivation时出现src缺失报错
问题分析与解决:Nix构建Docker镜像模块写法错误
问题场景
你尝试将Docker镜像构建逻辑拆分为模块文件,但执行nix-build时出现错误,而将逻辑放在单个文件中却能正常工作。以下是相关代码与错误信息:
拆分模块的代码
services/invidious.nix
{ pkgs, stdenv, ... }: stdenv.mkDerivation { name = "invidious"; container = pkgs.dockerTools.buildLayeredImage { name = "invidious"; contents = [ pkgs.busybox pkgs.bash pkgs.invidious ]; config = { Cmd = [ "/bin/bash" ]; Env = []; Volumes = {}; }; }; }
services.nix
let config = import ./config.nix; pkgs = config.pkgs; invidious = import ./services/invidious.nix; in rec { serviceimages = pkgs.writeText "images.txt" '' ${invidious(pkgs)} ''; }
config.nix
{ # nixos-22.05 / https://status.nixos.org/ pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/d86a4619b7e80bddb6c01bc01a954f368c56d1df.tar.gz") {}; }
执行错误信息
nix-build services.nix -A serviceimages these 2 derivations will be built: /nix/store/dbl3bzc05pssq3q9g8wd2i92xpmwf5bb-invidious.drv /nix/store/4x31hx9nxcbbksi2hsim08djrsj4h1zh-images.txt.drv building '/nix/store/dbl3bzc05pssq3q9g8wd2i92xpmwf5bb-invidious.drv'... unpacking sources variable $src or $srcs should point to the source error: builder for '/nix/store/dbl3bzc05pssq3q9g8wd2i92xpmwf5bb-invidious.drv' failed with exit code 1; last 2 log lines: > unpacking sources > variable $src or $srcs should point to the source For full logs, run 'nix log /nix/store/dbl3bzc05pssq3q9g8wd2i92xpmwf5bb-invidious.drv'.
正常工作的单文件代码
let # nixos-22.05 / https://status.nixos.org/ pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/d86a4619b7e80bddb6c01bc01a954f368c56d1df.tar.gz") {}; in rec { docker = pkgs.dockerTools.buildLayeredImage { name = "invidious"; contents = [ pkgs.busybox pkgs.bash pkgs.invidious ]; config = { Cmd = [ "/bin/sh" ]; Env = []; Volumes = {}; }; }; results = pkgs.writeText "images.txt" '' ${docker} ''; }
问题根源
- 错误使用
stdenv.mkDerivation:services/invidious.nix里用stdenv.mkDerivation包裹了dockerTools.buildLayeredImage。stdenv.mkDerivation是用于构建需要编译/处理源码的包,它默认会执行解压源码的步骤,因此必须指定src或srcs参数。但你这里只是生成Docker镜像,根本不需要处理源码,完全没必要用stdenv.mkDerivation包装。 - 参数传递错误:
invidious函数接收的是一个属性集({ pkgs, ... }),但services.nix里直接传递了pkgs值,而非包含pkgs的属性集。
解决方案
1. 修改services/invidious.nix
去掉多余的stdenv.mkDerivation,直接返回dockerTools.buildLayeredImage的结果:
{ pkgs, ... }: pkgs.dockerTools.buildLayeredImage { name = "invidious"; contents = [ pkgs.busybox pkgs.bash pkgs.invidious ]; config = { Cmd = [ "/bin/bash" ]; Env = []; Volumes = {}; }; }
2. 修改services.nix的参数传递
将invidious(pkgs)改为传递属性集:
let config = import ./config.nix; pkgs = config.pkgs; invidious = import ./services/invidious.nix; in rec { serviceimages = pkgs.writeText "images.txt" '' ${invidious { inherit pkgs; }} ''; }
修改后重新执行nix-build services.nix -A serviceimages即可正常构建,生成的镜像路径会写入images.txt文件。
内容的提问来源于stack exchange,提问作者djsumdog
相关产品推荐
相关产品推荐

