NixOS 上 Docker 的声明式配置。和 Podman 的路径不同,两者有不同 NixOS 配置接口,需按版本核对。
基础配置#
最小启用
# configuration.nix
{
virtualisation.docker.enable = true;
# 将自己的用户加入 docker 组
users.users.alice = {
extraGroups = [ "docker" ];
};
}sudo nixos-rebuild switch
# 重新登录后生效
docker run hello-world完整配置
{
virtualisation.docker = {
enable = true;
# 自动清理旧镜像(每天一次)
autoPrune = {
enable = true;
dates = "03:00"; # 每天凌晨 3 点
flags = [ "--all" "--filter" "until=168h" ]; # 按创建时间过滤的示例,非最后使用时间;先确定回滚策略
};
# 存储驱动
# storageDriver = "overlay2"; # 经典引擎示例,先确认当前后端,切换会使旧产物不可见
# daemon JSON 配置(mirror 不等于自动可信)
daemon.settings = {
# 镜像加速地址(根据需要替换)
registry-mirrors = [ "https://mirror.gcr.io" ];
# 日志大小限制
log-driver = "json-file";
log-opts = {
max-size = "10m";
max-file = "3";
};
};
};
}声明式容器:oci-containers 模块#
NixOS 有一个内置模块可以直接声明容器(类似简化版 Compose):
{
virtualisation.oci-containers = {
backend = "docker"; # 或 "podman"
containers = {
nginx = {
image = "nginx:alpine";
autoStart = true;
ports = [ "127.0.0.1:8080:80" ];
volumes = [
"nginx_data:/usr/share/nginx/html"
];
};
postgres = {
image = "postgres:16-alpine";
autoStart = true;
ports = [ "127.0.0.1:5432:5432" ];
volumes = [
"pgdata:/var/lib/postgresql/data"
];
# 文件由外部凭据流程提供;不把秘密内容放入 Nix store
environmentFiles = [ "/run/secrets/postgres.env" ];
environment = {
POSTGRES_DB = "myapp";
};
};
};
};
}局限:该模块不是 Compose 的完整模型;支持自己的 dependsOn 生成 systemd After/Requires,健康/运行参数可通过相应接口或 extraOptions 定义,但不自动拥有 Compose 的 profiles 和 service_healthy 依赖语义。复杂应用建议仍用 docker compose + 把 compose 文件纳入 Git 管理。
Home Manager#
# home.nix
{
# 不需要额外配置 Docker,系统级 virtualisation.docker 已足够
# 如果需要在用户级管理 Docker,用:
# home.file.".docker/config.json" = { ... };
}Docker 主要通过系统级配置管理。凭据配置不能简单把含 auth/token 的 config.json 作为公开 home.file 文本写入 store;用户级 rootless daemon、socket 与 context 应另行确认对应系统或用户模块支持。
NixOS 上 Docker vs Podman 选择#
引擎可以共存,但 CLI 与 socket 兼容选项可能冲突;同时启用真正 Docker 时不要再让 Podman 接管 docker 命令:
{
# 同时启用
virtualisation.docker.enable = true;
virtualisation.podman.enable = true;
virtualisation.podman.dockerCompat = false; # 保留真实 docker 命令
virtualisation.podman.dockerSocket.enable = false; # 不接管 Docker socket
}| 使用场景 | 推荐 |
|---|---|
跑他人的 docker-compose.yml |
Docker(原生 Compose v2) |
| 自己写新服务 | Podman + Quadlet(声明式 + systemd) |
| 学习容器 | Podman(免 root、免后台进程) |
| 公司项目 | Docker(团队标准) |
构建、激活与运行验证#
nixos-rebuild build 只验证构建产物;示例 switch 会激活系统并可能重启服务,需要按部署流程执行。加入 docker 组后重新登录仅改变权限生效时机,不降低组的安全风险。受控的 /run/secrets/postgres.env 必须存在并限制读取权限,文件应包含所需数据库凭据;它不会由此配置自动生成。rootless 模式是另一个 daemon/socket,不能把普通用户运行 CLI 自动称为 rootless。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。