原本想自己刻一套照片語意搜尋,後來想想沒必要重新發明輪子——先去找了找市面上有沒有現成又做得夠好的方案,最後選了開源的 Immich。它不只能辨識照片裡的人臉,還能用「描述畫面內容」的方式直接搜圖,甚至連截圖或文件照片裡的文字都讀得出來、搜得到。更方便的是它支援「原地索引」,舊照片放在哪個資料夾就留在哪,不用搬也不用複製一份。

部署與儲存規劃

Immich 拆成四個容器(主程式、AI 辨識模型、資料庫、快取),都用官方最新版本部署。資料庫放在讀寫快的 SSD——這是每次滑動相簿都要即時反應的部分,不能等;照片本體跟縮圖則丟去 RAID1 硬碟,背景在跑縮圖產生這種不急著看結果的工作,優先給空間而不是速度。有點像出門帶錢包只放常用的現金卡片,其他大宗物資放倉庫,用途不同、擺的地方自然不一樣。

踩坑:容器看不到既有照片資料夾

設定好「原地索引」的資料夾之後,Immich 一直找不到路徑,一開始以為是權限沒開對。查了實際的 Docker Compose 設定檔才發現,問題根本不是權限——是那個資料夾從一開始就沒有被接進容器裡,後台介面設定得再仔細都沒用,因為容器裡根本沒有那扇門通往那個房間。補上正確的掛載設定之後,還特地分四步驗證:主機那邊寫入檔案、容器裡看不看得到、資料庫有沒有真的自動建立索引,一步一步確認,不是看到「畫面上顯示成功」就相信。

踩坑:批量匯入時的兩次誤判

用社群工具一次匯入一大批舊照片時,發現處理速度追不上上傳速度,佇列越堆越多。排查過程中自己也錯怪了兩次:

  1. 一度以為是稍早測試故障時留下的後遺症,後來比對時間點才發現兩件事根本對不上,收回這個猜測
  2. 一度以為進度顯示「上傳完成」就代表照片都處理好了,結果去資料庫查實際筆數才發現,「上傳完成」只代表檔案傳到了,後面的辨識、產生縮圖還在排隊跑

最後真正的原因,是匯入工具本身有個「錯誤累積到一定次數就整批中止」的預設參數,調整這個設定之後,匯入才能一路跑完不會中途斷掉。

驗證

還特地拿其中一個容器做 docker kill 測試,故意驗證一件事:手動被砍掉的容器,不會被 restart: always 這個設定自動救回來——這是 Docker 本來就有的行為限制,故意重現一次,是為了確認另一篇提到的監控告警系統,真的抓得到這種故障,不是紙上談兵、寫了規則卻沒實際測過會不會響。