個人 dotfile 管理解決的是「一個人的環境可重現性」。當同樣的需求擴展到團隊——新人 onboarding 要多久能開始寫 code、團隊成員的開發環境差異造成「在我電腦上能跑」的問題、CI 環境跟本機環境不一致——就進入了「團隊開發環境標準化」的範疇。

個人 Dotfile 跟團隊環境的邊界

維度個人 Dotfile團隊環境標準化
管理對象個人偏好(alias、keybind、配色)專案依賴(runtime 版本、系統套件、服務容器)
目標個人效率和舒適度環境一致性和 onboarding 速度
儲存位置個人 dotfile repo專案 repo 內(.devcontainer/、flake.nix)
強制程度完全個人自由團隊約定或強制
變動頻率高(個人隨時調整)低(跟專案版本走)

兩者共用同一個核心思想(環境 as code、版控、可重現),但管理的對象和約定的範圍不同。個人 dotfile 是「我喜歡怎麼工作」,團隊環境是「這個專案需要什麼才能跑」。

Devcontainer:容器化的開發環境

Devcontainer 是微軟提出的開放規格(devcontainers.org),定義了怎麼用 Docker 容器作為開發環境。VS Code、GitHub Codespaces、JetBrains 都支援。

核心概念

專案 repo 裡放一個 .devcontainer/devcontainer.json,描述這個專案的開發環境需要什麼:

 1{
 2    "name": "My Project",
 3    "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
 4    "features": {
 5        "ghcr.io/devcontainers/features/go:1": {
 6            "version": "1.22"
 7        },
 8        "ghcr.io/devcontainers/features/node:1": {
 9            "version": "20"
10        }
11    },
12    "postCreateCommand": "go mod download && npm install",
13    "customizations": {
14        "vscode": {
15            "extensions": [
16                "golang.go",
17                "esbenp.prettier-vscode"
18            ]
19        }
20    },
21    "forwardPorts": [8080, 3000]
22}

打開專案時,IDE 自動啟動這個容器、在裡面安裝指定版本的 Go 和 Node、跑 dependency install、裝 VS Code extension。新人 clone repo → 打開 → 等容器建好 → 直接開始寫 code。

跟個人 Dotfile 的互動

Devcontainer 管的是「專案需要什麼」,但你在容器裡工作時還是會想要自己的 shell alias、Git 設定、editor keybind。兩者的整合方式:

  • dotfiles repo 自動部署:devcontainer.json 支援 "dotfiles.repository" 欄位,容器啟動時自動 clone 你的 dotfile repo 並執行 install script
  • 個人 vs 團隊設定分離.devcontainer/ 裡放團隊共用的環境定義,個人偏好透過 dotfiles 機制注入,不互相干擾
1{
2    "dotfiles.repository": "https://github.com/you/dotfiles",
3    "dotfiles.installCommand": "scripts/install.sh",
4    "dotfiles.targetPath": "~/dotfiles"
5}

這是個人 dotfile 和團隊環境標準化最乾淨的接合點——團隊定義「環境長什麼樣」,個人 dotfile 定義「在這個環境裡我怎麼操作」。

Devcontainer 的限制

  • Docker 是前提:團隊每個人的機器都要裝 Docker,macOS 上要跑 Docker Desktop 或 OrbStack
  • GUI 應用不適合:devcontainer 定位是 headless 開發環境,不處理圖形桌面
  • 效能折扣:檔案系統操作在 macOS 上的 Docker volume 有效能折扣(Linux 上幾乎沒差)
  • 離線環境:建容器需要拉 image 和 feature,斷網環境要另外處理(見 Infra 斷網模組

Nix:宣告式的環境管理

Nix 是另一條技術路線,用宣告式的方式描述整個開發環境,不依賴 Docker。

核心概念

Nix 的 flake.nix(或 shell.nix)宣告了開發環境需要哪些套件,nix develop 進入這個環境:

 1# flake.nix
 2{
 3  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
 4
 5  outputs = { nixpkgs, ... }:
 6    let
 7      pkgs = nixpkgs.legacyPackages.x86_64-linux;
 8    in {
 9      devShells.default = pkgs.mkShell {
10        packages = with pkgs; [
11          go_1_22
12          nodejs_20
13          postgresql_16
14          redis
15        ];
16        shellHook = ''
17          echo "Dev environment ready"
18        '';
19      };
20    };
21}

跟 Devcontainer 的差異:Nix 不用容器,直接在宿主機上建立隔離的環境(透過 Nix store 的路徑隔離)。優點是沒有 Docker 的效能折扣和額外層級;缺點是 Nix 的學習曲線陡峭、語法不直覺。

Home Manager:Nix 管理 Dotfile

Nix 生態裡的 Home Manager 可以用 Nix 語言宣告式地管理整個家目錄的配置——等於用 Nix 取代 stow/chezmoi 做 dotfile 管理:

 1# home.nix
 2{ config, pkgs, ... }:
 3{
 4  programs.git = {
 5    enable = true;
 6    userName = "Your Name";
 7    userEmail = "you@example.com";
 8    extraConfig = {
 9      init.defaultBranch = "main";
10      pull.rebase = true;
11    };
12  };
13
14  programs.zsh = {
15    enable = true;
16    shellAliases = {
17      ll = "ls -alF";
18      gs = "git status";
19    };
20  };
21
22  programs.neovim = {
23    enable = true;
24    defaultEditor = true;
25  };
26}

Home Manager 把「安裝軟體」和「寫配置」統一成一份宣告——改完 home-manager switch 就同時更新套件和配置。這是 dotfile 管理的極致形式,但代價是整個技術棧鎖定在 Nix 生態裡。