Dockhand¶
概述¶
Dockhand 係 fnsys/dockhand 嘅容器編排同 GitOps 中樞,負責管理 oracle-arm-stacks 倉庫入面嘅 56+ 個 Docker Compose stacks。Dockhand 透過掛載 Docker socket 同 Docker daemon 直接互動,可以偵測 compose 檔案變更、同步環境變數,以及執行 stack 嘅部署/更新/移除。所有 secret 唔會直接 hardcode 喺 compose 檔案,而係經由外部 secret provider Infisical 注入,確保敏感資料淨係喺執行時間先出現。
Dockhand 喺設計上維持「零 Port 暴露」:Host 上完全冇 publish 任何容器 port,對外路由一律交由 cf_network 入面嘅 cloudflared 處理,避免管理介面目視於公網,減少攻擊面。
架構¶
Dockhand 部署喺 Oracle Cloud ARM 主機,使用外部 Docker network cf_network,並固定 IPv4 172.21.0.15。由於 cf_network 已經存在,compose 檔案用 external: true 宣告,Dockhand 直接加入現有主網絡;同一網絡內嘅 cloudflared 可以用 http://dockhand:8080 或者 http://172.21.0.15:8080 作為 upstream。
Dockhand 依賴以下元件:
- PostgreSQL:以
pg-main容器提供資料庫服務,Dockhand 使用dockhand資料庫,用戶同樣係dockhand,密碼由${DOCKHAND_DB_PASSWORD}提供。 - Docker socket:
/var/run/docker.sock俾 Dockhand 管理 host 上其他 containers。 - Infisical:負責存放同加解密環境變數同 secrets;Dockhand 部署時會向 Infisical 攞最新 secret 再寫入執行環境。
- Cloudflare Tunnel:作為唯一對外入口,令管理員可以經內部域名存取 Dockhand,但唔需要開任何 Host port。
- oracle-arm-stacks 倉庫:裝載所有 stacks 嘅 compose 同
.env範本,Dockhand 以 GitOps 方式同步,當 repo 有更新時會觸發重新部署。
部署(Docker Compose 片段)¶
以下係精簡版 docker-compose.yml,已移除敏感值,直接可用於 oracle-arm-stacks 入面嘅 Dockhand stack:
services:
dockhand:
image: fnsys/dockhand:latest
container_name: dockhand
restart: unless-stopped
# 刻意唔寫 ports:,維持零 Port 暴露
environment:
- TZ=Asia/Hong_Kong
- DATABASE_URL=postgres://dockhand:${DOCKHAND_DB_PASSWORD}@pg-main:5432/dockhand
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- dockhand_data:/app/data
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
networks:
cf_network:
ipv4_address: 172.21.0.15
volumes:
dockhand_data:
name: dockhand_data_vol
networks:
cf_network:
external: true
部署前請確保 cf_network 已經存在;如果未建立,需要先執行:
docker network create --subnet 172.21.0.0/16 cf_network
之後用 docker compose up -d dockhand 啟動服務。
配置與環境變數¶
Dockhand 嘅主要環境變數包括:
TZ=Asia/Hong_Kong:設定容器時區為香港時間,並同步/etc/localtime同/etc/timezone。DATABASE_URL:PostgreSQL 連線字串,格式為postgres://dockhand:${DOCKHAND_DB_PASSWORD}@pg-main:5432/dockhand。${DOCKHAND_DB_PASSWORD}:必須由 Infisical 注入,唔好寫入 repo。INFISICAL_URL同INFISICAL_TOKEN:如果 Dockhand 原生整合 Infisical,需要喺部署環境注入,等佢可以喺執行時間抓取 secrets。
所有敏感變數建議由 Infisical 管理,並喺 CI/CD 或 host 上嘅 deploy script 度解析成環境變數,避免 .env 入面出現明文密碼。Dockhand 每次收到 Git push 或 repo 更新後,會以最新 secrets 重新建立相關 containers。
維運與監控¶
日常維運可以透過以下指令檢查 Dockhand 狀態:
# 睇 Dockhand 即時 log
docker logs -f dockhand
# 確認容器已加入 cf_network 及 static IP
docker inspect dockhand --format '{{.NetworkSettings.Networks.cf_network.IPAddress}}'
# 測試同 PostgreSQL 嘅連線
docker exec dockhand psql "$DATABASE_URL" -c 'SELECT 1;'
# 檢查容器內部管理服務
docker exec dockhand curl -s http://localhost:8080/healthz
# 強制重新建立 Dockhand 容器
docker compose up -d --force-recreate dockhand
監控重點:
- 確保
cf_network冇異動,避免 IP 衝突;尤其當其他 containers 都用固定 IP 時,要檢查172.21.0.15冇畀人佔用。 - 留意 Docker socket 權限,如果 Dockhand 冇辦法讀取 containers,會出現 permission denied;需要確認容器內 process 有足夠權限。
- 定期檢查
dockhand_data_vol容量,避免/app/data寫滿。 - Cloudflare Tunnel 如果斷線,Dockhand 仍然喺
cf_network入面運作,但管理介面會暫時無法存取;可以檢查cloudflared嘅 log 同 tunnel credentials。
常見問題¶
1. 點解 Dockhand 有 static IP 但外面訪問唔到?
因為 Dockhand 冇 publish 任何 Host port,對外必須經 cf_network 入面嘅 cloudflared。請確認 cloudflared 同 Dockhand 喺同一個 network,而且 tunnel config 入面 upstream 係 http://dockhand:8080 或者 http://172.21.0.15:8080。
2. Dockhand 連唔到 PostgreSQL?
先檢查 pg-main 容器係咪正常:docker ps | grep pg-main。然後確認 DATABASE_URL 入面嘅 username、password 同 database 名正確。最常見問題係 ${DOCKHAND_DB_PASSWORD} 未有由 Infisical 注入,導致字串入面有空白或者變數名。
3. Docker socket permission denied?
確認執行 Dockhand image 嘅用戶有權限訪問 /var/run/docker.sock。如果 host 上 Docker group 嘅 GID 同 container 入面唔一致,可能要重建 image 或者用 group_add 指定 GID。
4. GitOps sync 冇觸發部署?
Check Dockhand 有冇正確 read-only mount oracle-arm-stacks 或者有冇 webhook 連到 GitHub。如果係用 polling 模式,確認 /app/data 入面嘅 cache 冇損壞,必要時 restart Dockhand。
相關鏈接¶
- docker
- docker-compose
- cloudflare-tunnel
- infisical
- postgres
- oracle-arm-stacks
- qdrant
- litellm