- 按設定檔和角色組織 Docker Compose 可以簡化擁有數十個服務的家庭實驗室的管理。
- 將配置集中在 .env 檔案中,使用覆蓋規則,並在 Git 中進行版本控制,使得環境具有可移植性,易於遷移。
- 專用網路、Traefik 和健康檢查提高了服務的安全性、隔離性和韌性。
- 監控、受控日誌和自動備份使家庭實驗室成為一個長期穩定的平台。
用貨櫃搭建現代化的家庭實驗室已經成為許多技術人員最喜歡的嗜好。 Docker Compose幾乎總是這種部署的核心。使用 YAML 定義您的服務,使用 Git 進行版本控制,然後您可以使用指令啟動整個環境。
現在,當你開始發展壯大時,事情就會改變:你會從只有兩三個容器增加到 數十個服務、內部網路、反向代理、資料庫和 CI 運行器這時就出現了一個關鍵問題:是用一個巨大的 Docker Compose 文件,還是用許多小文件?我該如何組織設定檔、網路、備份、安全設置,並且還要使其易於遷移?
在家庭實驗室中實際部署 Docker Compose 的方法
實際上,使用 Homelabs 一段時間的人通常會採用三種 Compose 組織模型,每種模型都有其自身的優點和缺點。 在擴展或遷移機器時,選擇正確的方法可以避免很多麻煩。.
一邊是那個從…開始的人 Docker Run 最初是自由運行的,然後遷移到 Portainer,最後升級到 Docker Compose。很典型的例子:Portainer 提供了良好的視覺性、使用者友善的介面、範本等等,但最終,如果沒有文件,編輯複雜的參數或遷移配置就會變得很麻煩。
與此相反的極端是那些 已將所有內容整合到一個「超級」docker-compose.yml檔案中 能夠運行所有家庭實驗室服務:反向代理、媒體、實用程式、監控、LLM、資料庫…所有這些都整合在一個堆疊中。
介於兩者之間的是,許多用戶選擇混合方法: 幾個按上下文分組的小型 docker-compose.yml 文件 (例如,媒體、基礎設施、生產力、監控),所有這些都在同一個儲存庫中,並且通常共用全域環境變數。
一個相當巧妙的解決方案融合了這兩個面向: 包含其他文件的根 docker-compose 文件 (每個應用程式或服務都位於一個子資料夾中)。這樣,您就可以維護家庭實驗室的全局視圖,而無需忍受難以閱讀的上千行 YAML 檔案。
使用者畫像、按功能分組以及大型家庭實驗室
當你的家庭實驗室開始接近… 30、40 或 50 項服務 (包括資料庫、快取或索引器等備份服務)因此,對其進行規格至關重要。這正是兩者發揮作用的地方: 按功能分組 喜歡使用 Docker Compose 設定文件.
一個非常常見的做法是將所有內容歸入一個 Compose「專案」中,但按設定檔進行邏輯劃分。例如:
- 核心概況:家庭實驗室核心,使用 Traefik 作為反向代理,並使用身分識別提供者(例如 OAuth 或 Authentik)對同一網域下的所有應用程式進行 HTTPS 驗證。
- 媒體簡介Plex、Sonarr、Radarr、Ombi、SABnzbd 或 qBittorrent 等服務負責整理、下載和提供多媒體內容。
- 實用工具簡介使用 Portainer、Watchtower(如果使用)、Diun、dockcheck 或類似工具來管理和監控容器和更新。
- 基礎設施/監控概況Traefik、cAdvisor、Prometheus、Grafana、Uptime Kuma、Dozzle 以及所有與監控和日誌記錄相關的工具。
- 實驗概況或LLM:LLM 或特殊應用程式(ChatGPT Next Web local、LibreOffice Online 等)的特定堆疊,通常預設是禁用的。
個人資料的妙處在於… 您可以只啟動部分基礎架構。 這取決於您的需求。例如,您可以在低功耗迷你電腦上只運行核心+基礎架構配置,而在配備更多硬碟和GPU的大型伺服器上只運行媒體配置。
在設計良好的儲存庫中,通常會有一個 docker-compose.yml “master” 會將包含的內容拉取到 apps/ 或 services/ 資料夾中的各個檔案。此外,幾乎所有服務都是透過單一檔案進行設定的。 .env 全域環境變數和 secrets/ 目錄中的一些金鑰這大大簡化了初始設定。
依照這個模式,家庭實驗室管理基本上可以簡化為 編輯 .env 檔案和金鑰,啟用或停用設定文件,並決定在每個主機上啟動哪些服務。如果您要在多台電腦上部署同一組應用程序,這將是理想之選。
一個巨大的 docker-compose 檔案 vs. 多個小文件
這是一個永恆的爭論: 一個包含所有內容的 docker-compose.yml 文件,還是每個服務/堆疊多個文件? 真正的答案通常是「這取決於你想優先考慮什麼:遷移的簡易性還是每個服務的清晰度」。
誰來捍衛 單一主文件 它通常會突出以下幾個優點:
- 遷移主機非常簡單你只需克隆倉庫,複製 .env 檔案和密鑰,掛載卷,然後運行 `docker compose up -d` 即可。無需逐個目錄操作。
- 基礎設施即真理準則家庭實驗室的整個拓樸結構(服務、網路、磁碟區、依賴關係)都在一個地方。
- 集中更新如果您更改了映像版本、重新啟動策略或某些日誌記錄,您就知道要在哪裡進行修改。
但它也有明顯的缺點:龐大的 YAML 檔案更難維護。 合併衝突增加 當需要調試某個具體問題時,你會發現自己要處理數百行程式碼組成的龐大程式碼庫。當程式碼量變得過於龐大時,感到些許懊惱也是人之常情。
另一種方法是… 每個應用程式或每個邏輯堆疊對應一個 docker-compose.yml 檔案。在類似這樣的結構中:
docker/
├── bookstack/
│ └── docker-compose.yml
├── dashy/
│ └── docker-compose.yml
└── traefik/
└── docker-compose.yml
這樣,每個容器都有一個類似這樣的名稱。 bookstack-app-1 o traefik-reverse-proxy-1這有助於您快速定位問題:如果 bookstack-app-1 容器崩潰,您就知道要查看哪個資料夾了。
視覺上更乾淨整潔, 它允許您獨立管理每項服務。 (啟動、停止或更新某個進程而不會影響其他進程)。此外,還有像 Dozzle 這樣的應用程序,它們利用獨立的堆疊來更好地組織日誌。
權衡是 如果將所有東西分開得太遠,那麼公共服務(例如 Traefik 或共享網路)之間的協調就需要更加謹慎。必須聲明外部網絡,必須使用特定的 Traefik 標籤,並且必須記住其他 docker-compose 創建的網路的命名規則。
關於 .env、覆蓋和版本控制的最佳實踐
最被低估的技巧之一是 將配置集中在 .env 檔案中與其在 docker-compose.yml 檔案中堆砌環境變量,不如這樣定義:
DB_USERNAME=myuser DB_PASSWORD=secretpassword
然後在 YAML 檔案中,它們被引用為: ${DB_USERNAME} o ${DB_PASSWORD}這樣一來,文章內容一目了然,方便您一目了然地閱讀。 跨多個服務共享變數 最重要的是,將密碼儲存在單獨的檔案中(您可以將其從 Git 中排除)。
它對不同的環境(生產、測試、開發)都非常有用。 利用 docker-compose.override.yml其想法是創建一個基礎的 docker-compose.yml 文件,然後在覆蓋配置中只覆蓋那些會發生變化的部分:端口、路徑、調試標誌…
例如,在開發過程中,您可以載入一個覆蓋文件,其中 你暴露一個不同的端口,啟用 DEBUG 模式,並掛載本地原始碼。你不需要修改主 YAML 文件,但需要根據啟動環境調整堆疊。
顯然, 如果你想讓你的家庭實驗室達到哪怕稍微可靠一點的程度,使用 Git 對所有內容進行版本控制是必不可少的。通常情況下,你會看到類似這樣的內容:
homelab-docker/ ├── docker-compose.yml ├── .env.example ├── services/ │ ├── media/ │ ├── infra/ │ └── ... └── scripts/
接下來,你需要初始化程式碼庫,提交基礎架構變更,如果有問題, 您可以快速還原到 Compose 的先前版本。對於稍微有點雄心壯志的家庭實驗室來說,這不僅是一種選擇,而且是避免崩潰的唯一方法。
網路、Traefik 和安全服務暴露
幾乎所有中等程度的家庭實驗室都採用了相同的組合: Traefik 可用作反向代理和集中式身分提供者(Auth 或 Authentik)。這樣,您就可以在子網域下透過 HTTPS 和 SSO 公開多個應用程式。
一種經典模式是建立一個專用的 Docker 網絡,例如 反向代理 或類似的方案,其中 Traefik 和所有要對外提供的 Web 服務都連接在一起。其餘容器(資料庫、快取等)則保留在隔離的內部網路中。
如果您使用 Traefik 並將服務分離到不同的 docker-compose 檔案中,則需要 定義一個共享的外部網絡大概就是這樣:
services:
bookstack:
image: lscr.io/linuxserver/bookstack
networks:
- traefik-net
labels:
- "traefik.docker.network=traefik_default"
networks:
traefik-net:
name: traefik_default
external: true
這裡,traefik_default 網路由 Traefik 協定堆疊創建,其他服務則透過名為 traefik-net 的外部網路新增至該網路。標籤告訴 Traefik… 應該使用哪個網路來路由流量.
當單一技術堆疊包含後端服務(例如,Web 容器及其資料庫)時,您可以 將它們連接到共享的預設網絡,並且只允許 Web 容器存取 Traefik 網路。資料庫中將新增標籤 traefik.enable=false,以便 Traefik 忽略它。
這種設定方式能為您帶來兩大主要好處: 服務之間的隔離和受控暴露只有以 Traefik 標籤標記且位於代理網路上的容器才能從外部存取。
資料持久性、磁碟區和磁碟結構
沒有持久化資料的家庭實驗室沒什麼用:資料庫、配置、媒體、文件…所有東西都必須在 docker compose down 指令執行後仍然存在。 捲冊和裝訂架就是你的生命保險.
許多人使用類似這樣的結構來整理儲物空間:
/mnt/storage/
├── downloads/
│ ├── movies/
│ └── tv/
├── media/
│ ├── movies/
│ ├── tv/
│ └── music/
└── srv/
└──
這個想法是 下載器(例如 qBittorrent、SABnzbd 等)只能看到下載資料夾。像 Radarr/Sonarr 這樣的管理器可以存取下載內容和媒體檔案(用於移動/建立硬連結),而像 Plex 或 Jellyfin 這樣的伺服器只能看到媒體資料夾。
這樣你就運用了以下原則: 最低特權每個容器僅存取其實際需要的內容。這種清晰的分離也有助於決定將哪些磁碟區或路徑備份到雲端或外部磁碟機。
srv 目錄通常用於儲存應用程式配置(例如,/srv/jellyfin/config、/srv/traefik、/srv/paperless 等)。目錄通常只包含部分版本控制的內容(模板、Caddyfile 等),而不會包含任何關鍵或資源密集的內容。
在某些情況下,使用 硬連結 在下載鏈中:像 Radarr 或 Sonarr 這樣的服務可以將下載的檔案連結起來,從而在不佔用重複磁碟空間的情況下保持種子下載。 TRaSHGuides 等指南中提出的目錄設計正是基於此。
使用 GitHub Actions 和本地運行器實現自動化部署
如果你想更進一步,你可以再進一步… 使用 CI/CD 實現家庭實驗室更新自動化一些用戶已經用 GitHub Actions 和自架運行器在自己的家庭實驗室中搭建的工作流程取代了 Jenkins 和類似工具。
機制很簡單:每次你向 Homelab 程式碼庫的主分支推送程式碼時, 啟動 GitHub Actions 工作流程,執行測試、程式碼檢查,如果一切順利,則將變更部署到伺服器。.
典型的工作流程包括以下步驟:
- Gitleaks 型秘密掃描器:萬一您不小心將密碼或令牌上傳到了程式碼庫。
- 林亭 為了保持 YAML 或基礎設施程式碼的可讀性和一致性,需要進行修改。
- 在家庭實驗室內部更新儲存庫在目標伺服器上執行 git pull 指令。
- 受控的容器再造停止舊進程,啟動新進程並檢查狀態。
優勢:更高的安全性(您可以控制秘密洩漏),更好的程式碼品質和 只需一次推送即可重複部署由於您使用的是本機運行器,因此映像和磁碟區不會離開您的網路;您只是使用 GitHub 介面來視覺化管道。
為什麼 Docker Compose 能讓家庭實驗室的搭建變得如此輕鬆?
許多人多年來一直依賴 Docker Run 和 Portainer 直到發生事故或遷移,迫使其重新評估其方法。例如,當主機遺失或必須將服務遷移到另一台機器時, 在 Portainer 中僅依賴孤立的命令或配置是一個陷阱。.
切換到 Compose 模式後最大的差異在於: 整個服務定義將轉換為文字。磁碟區、連接埠、網路、標籤、變數…所有內容都包含在一個 YAML 檔案中,您可以複製、共用、版本控制和重複使用。
編輯服務不再是“手動重建容器”,而是變成了 修改檔案中的一行,儲存並執行 docker compose up -d您無需記住原始指令,也無需點擊瀏覽多個 Portainer 畫面。
此外,如果您使用多台伺服器(迷你電腦、NAS、桌上型電腦),能夠…將非常方便。 將同一個 compose 檔案複製到另一台機器上,調整四個路徑,並使用不同的硬體啟動同一個堆疊。事實上,許多人承認,在經歷了資料遺失或混亂遷移等驚險事件後,Compose 在後續事件中為他們節省了大量時間。
此外,從舊服務建立新服務也變得輕而易舉:例如, 克隆 Plex 配置以掛載 Jellyfin 如果透過複製 YAML 區塊來重複使用相同的媒體路徑和轉碼設備,只需幾分鐘。
最佳化:建構上下文、多階段建置和資源
雖然許多家庭實驗室容器都來自公共鏡像,但在某些情況下,您需要自行編譯鏡像。在這種情況下,務必謹慎。 建構上下文不要傳送整個儲存庫,而應限制在專案資料夾內(並編寫一個好的 .dockerignore 檔案),以便建置快速且輕量級。
另一個非常有用的技巧是訴諸於… 多階段構建 在你的 Dockerfile 中:第一階段安裝依賴項並編譯,第二階段僅將必要的構件複製到一個小型基礎映像中。結果:最終鏡像 更小巧、更安全因為它們不繼承工具鏈或額外的函式庫。
在「撰寫」側,您可以選擇定義 CPU 和 RAM 限制 (尤其是在 Swarm 環境或 Docker 支援這些參數的情況下)可以防止資源密集型應用獨佔資源。在家庭實驗室中,這有助於防止配置錯誤的服務導致系統其他部分癱瘓。
不要忘了 重啟策略 (重新啟動:始終、除非停止、故障時):透過這些設置,您可以確保關鍵服務(反向代理、VPN、金鑰資料庫)在重新啟動或一次性故障後自動重新啟動。
最後,最好使用類似這樣的命令來安排定期清潔任務。 Docker 映像修剪、Docker 容器修剪和 Docker 磁碟區修剪 清除舊版、已停止的容器或孤立磁碟區的殘留文件,從而回收磁碟空間。
健康服務、記錄和監測
為了確保你的家庭實驗室不是一個黑盒子,需要專注於以下三個方面: 健康檢查、受控日誌記錄和監控Docker Compose 可讓您為每個服務聲明健康檢查(使用類似 curl -f http://localhost 的命令或特定腳本),以確定容器是否被認為是健康的。
這樣你就可以做到… 只有「健康」的容器才能接收流量。 (例如,透過 Traefik),並且,如果它們停止回應,則會根據配置的策略重新啟動。這只需極少的投入即可顯著提高系統的彈性。
關於日誌,請調整驅動程式 json 檔案的限制。 最大大小和最大文件 它可以防止磁碟被大量遺忘的日誌檔案佔滿。像 Dozzle 這樣的 Web 工具可以幫助你透過瀏覽器瀏覽所有容器的日誌,這對於偵錯特定服務非常方便。
關於指標和持續監控,經典的組合是 cAdvisor + Prometheus + GrafanacAdvisor 會公開每個容器的 CPU、內存、磁碟和網絡使用情況統計信息;Prometheus 會定期收集這些信息,Grafana 會將它們顯示在美觀的儀表板中,並在出現峰值時發出警報。
一個配置完善的家庭實驗室通常還包括 Kuma 可用性檢查的正常運作時間 (HTTP、ICMP、TCP 等)以及像 Duplicati 這樣的自動備份系統,可以將關鍵資料複製到其他磁碟或雲端。這樣,您就能隨時了解資料狀態,萬一出現問題,也不會遺失重要資料。
家庭實驗室的安全性和遠端訪問
無論裝置多麼簡陋,安全都不可或缺。許多人選擇 不要將您的 NAS 或其服務直接暴露給外部世界。透過 VPN 限制遠端存取(WireGuard 因其效能和簡易性而成為非常受歡迎的選擇)。
在這種模式下,路由器充當網關:僅對 VPN 伺服器開放一個隨機端口,連接成功後, 所有對內部服務的請求都透過加密隧道傳輸。Traefik 和這些應用程式在沒有預先過濾的情況下不會暴露在網路上。
那些不想自己管理 VPN 的人有時會求助於… Cloudflare Tunnel 或 Tailscale 無需開放連接埠即可存取家庭實驗室。這些都是便利的替代方案,但如果您最重視隱私,則需要考慮這些第三方可能會收集哪些元資料。
另一個好的做法是 對伺服器和NAS磁碟進行加密定期安裝修補程式並限制自動更新(許多人避免使用 Watchtower,而選擇手動控制更新)。與其因為一次未檢查的更新而導致 Homelab 系統崩潰,不如稍微落後一些,但要有控制權。
如您所見,您無需達到“企業級”水平,但是 是的,制定最低安全和紀律標準是明智之舉。 這樣你的家庭實驗室就不會變成篩子,也不會成為不斷帶來恐懼的來源。
最終,使用 Docker Compose 建立一個像樣的家庭實驗室需要組織性、常識和勇於嘗試的精神:如果你將服務分組、正確定義網絡、在 Git 中記錄並進行一些自動化,最終你會得到一個可以用單個命令啟動、輕鬆遷移到另一台機器、並逐步擴展而不會變成難以控制的混亂環境。



