Docker 開發

本指南涵蓋 PETsARD 開發者的 Docker 開發設定、測試和部署。

開發環境設定

先決條件

  • 已安裝並運行 Docker Desktop
  • 已在本地複製 Git 儲存庫
  • 對 Docker 概念有基本了解

快速環境檢查

使用基本指令驗證您的 Docker 設定:

# 檢查 Docker 安裝和版本
docker --version

# 檢查 Docker daemon 狀態
docker info

# 測試基本 Docker 功能
docker run --rm hello-world

這將:

  • 驗證 Docker 版本
  • 檢查 Docker daemon 狀態
  • 測試基本 Docker 功能

使用 Docker 進行本地開發

建置本地映像檔

# 建置標準版本(預設 - 不含 Jupyter)
docker build -t petsard:latest .

# 建置包含 Jupyter Lab 的 Jupyter 版本
docker build --build-arg INCLUDE_JUPYTER=true -t petsard:jupyter .

# 針對 ARM64 平台(Apple Silicon)
docker buildx build --platform linux/arm64 --load --build-arg INCLUDE_JUPYTER=true -t petsard:jupyter --no-cache .

運行容器

標準容器

# 運行標準容器(不含 Jupyter)- Python REPL
docker run -it --entrypoint /opt/venv/bin/python3 petsard:latest

# 使用資料卷掛載運行
docker run -it -v $(pwd):/app/data --entrypoint /opt/venv/bin/python3 petsard:latest

Jupyter Lab 容器

# 運行包含 Jupyter Lab 的容器(預設行為)
docker run -it -p 8888:8888 \
  -v $(pwd)/data:/app/data \
  -v $(pwd)/notebooks:/app/notebooks \
  petsard:jupyter

# 在 Jupyter 容器中運行 Python REPL
docker run -it --entrypoint /opt/venv/bin/python3 petsard:jupyter

# 在 http://localhost:8888 存取 Jupyter Lab

特點:

  • Jupyter Lab 介面用於互動式開發
  • 開放 8888 端口供瀏覽器存取
  • 卷掛載以保持資料和 notebook 持久化
  • ARM64 優化,適用於 Apple Silicon

開發環境管理

Docker 建置變體

PETsARD 提供靈活的 Docker 建置,可選擇性包含 Jupyter Lab 支援:

# 建置 Jupyter 版本(包含 Jupyter Lab)
docker build --build-arg INCLUDE_JUPYTER=true -t petsard:jupyter .

# 建置標準版本(不含 Jupyter)
docker build --build-arg INCLUDE_JUPYTER=false -t petsard:standard .

# 預設建置(包含 Jupyter)
docker build -t petsard:latest .

Jupyter 版 vs 標準版環境

Jupyter 環境特點

  • Jupyter Lab 整合 - 完整的 Jupyter 環境,可在 http://localhost:8888 存取
  • 互動式開發 - 卷掛載以進行即時開發
  • 完整開發堆疊 - 來自 pyproject.toml [docker] 群組的所有依賴
  • 較大映像檔大小 - 包含 Jupyter Lab 和開發工具
# 運行包含 Jupyter Lab 的 Jupyter 容器
docker run -it --rm \
  -p 8888:8888 \
  -v $(pwd):/workspace \
  petsard:jupyter
# 在 http://localhost:8888 存取 Jupyter Lab

標準環境特點

  • 核心運行時 - 僅包含 PETsARD 核心功能的必要依賴
  • 較小映像檔大小 - 針對部署優化,不含 Jupyter
  • 安全優化 - 非 root 使用者執行(UID 1000)
  • Distroless 基礎 - 使用 gcr.io/distroless/python3 的最小攻擊面
# 運行標準容器
docker run -it --rm \
  -v $(pwd)/data:/app/data \
  petsard:standard

配置檔案

Docker 環境使用這些關鍵檔案:

  • Dockerfile - 多階段生產優化映像檔,可選擇性支援 Jupyter
  • pyproject.toml - 專案配置與依賴群組
  • .github/workflows/docker-publish.yml - 自動建置的 CI/CD 流水線

環境變數

容器會自動配置:

# Python 優化
PYTHONPATH=/app
PYTHONUNBUFFERED=1
PYTHONDONTWRITEBYTECODE=1

# Jupyter 專用(當 INCLUDE_JUPYTER=true 時)
JUPYTER_ENABLE_LAB=yes
JUPYTER_ALLOW_ROOT=1

# 建置變體指示器
INCLUDE_JUPYTER=true/false

開發工作流程

功能開發

  1. 設定開發環境

    # 建置包含 Jupyter Lab 的 Jupyter 映像檔(ARM64 優化)
    docker buildx build --platform linux/arm64 --load --build-arg INCLUDE_JUPYTER=true -t petsard:jupyter --no-cache .
    
    # 啟動包含 Jupyter Lab 的容器
    docker run -it -p 8888:8888 \
      -v $(pwd)/data:/app/data \
      -v $(pwd)/notebooks:/app/notebooks \
      petsard:jupyter
    
    # 在 http://localhost:8888 存取 Jupyter Lab
  2. 編碼和測試

    # 運行 Python REPL 進行測試
    docker run -it --entrypoint /opt/venv/bin/python3 petsard:jupyter
    
    # 使用資料卷運行測試
    docker run -it -v $(pwd):/app/data --entrypoint /opt/venv/bin/python3 petsard:jupyter
    
    # 在容器內測試 PETsARD 功能
    # python -m petsard.executor demo/tutorial/use-cases/data-constraining.yaml
  3. 測試兩種建置變體

    # 測試 Jupyter 建置(包含 Jupyter Lab)
    docker build --build-arg INCLUDE_JUPYTER=true -t petsard:jupyter .
    
    # 測試標準建置(預設,不含 Jupyter)
    docker build -t petsard:latest .
    
    # 針對 ARM64 平台
    docker buildx build --platform linux/arm64 --load --build-arg INCLUDE_JUPYTER=true -t petsard:jupyter --no-cache .

研究和實驗工作流程

  1. 啟動 Jupyter 環境

    # 運行包含 Jupyter Lab 的容器
    docker run -it --rm \
      -p 8888:8888 \
      -v $(pwd):/workspace \
      petsard:jupyter
    # 導航至 http://localhost:8888
  2. 建立和運行 Notebook

    • 使用 /workspace 目錄存放持久化 notebook
    • 直接存取 PETsARD 模組:import petsard
    • 實驗不同的配置
  3. 匯出結果

    # 存取容器 shell 進行檔案操作
    docker run -it --rm \
      -v $(pwd):/workspace \
      petsard:jupyter \
      bash
    # 您的 notebook 和資料會持久保存在掛載的卷中

測試和驗證

手動測試指令

# 測試基本功能(預設包含 Jupyter)
docker run --rm petsard:latest python -c "
import petsard
import importlib.metadata
print(f'✅ PETsARD v{importlib.metadata.version(\"petsard\")} 已載入')
from petsard.executor import Executor
print('✅ 所有模組匯入成功')
"

# 使用範例配置測試
docker run --rm \
  -v $(pwd):/workspace \
  -w /workspace \
  petsard:latest \
  python -m petsard.executor demo/tutorial/use-cases/data-constraining.yaml

# 測試 Jupyter 變體
docker run --rm \
  -p 8888:8888 \
  -v $(pwd):/workspace \
  petsard:jupyter \
  python -c "import jupyterlab; print('✅ Jupyter Lab 可用')"

# 測試標準變體
docker run --rm \
  petsard:standard \
  python -c "import petsard; print('✅ 標準建置正常')"

建置測試

# 測試標準建置(不含 Jupyter)
docker build --build-arg INCLUDE_JUPYTER=false -t petsard:test-standard .
docker run --rm petsard:test-standard python -c "import petsard; print('✅ 標準建置正常')"

# 測試 Jupyter 建置(包含 Jupyter Lab)
docker build --build-arg INCLUDE_JUPYTER=true -t petsard:test-jupyter .
docker run --rm petsard:test-jupyter python -c "import jupyterlab; print('✅ Jupyter 建置正常')"

# 清理測試映像檔
docker rmi petsard:test-standard petsard:test-jupyter

多階段 Dockerfile 架構

Dockerfile 使用多階段建置進行優化:

建置階段

  • 基於 python:3.11-slim
  • 安裝建置依賴和編譯工具
  • /opt/venv 建置虛擬環境
  • ARM64 優化 - 針對 Apple Silicon 特別處理 CPU 版本的 PyTorch
  • 根據 INCLUDE_JUPYTER 建置參數安裝 PETsARD 與依賴
  • 使用 --dependency-groups=docker 安裝 Jupyter Lab

生產階段

  • 基於 python:3.11-slim(非 distroless,以提供更好的相容性)
  • 建立專用的 petsard 使用者以提高安全性
  • 從建置階段複製虛擬環境和應用程式檔案
  • 適應性入口腳本,處理 Jupyter 和 Python REPL 模式
  • ARM64 效能調校 - 針對 Apple Silicon 優化的環境變數

主要特點

  • Python 3.11 - 穩定的 Python 版本,與 anonymeter 相容
  • 虛擬環境隔離 - 依賴隔離在 /opt/venv
  • ARM64 優化 - 針對 Apple Silicon 特別安裝 CPU 版本的 PyTorch
  • 條件性 Jupyter - 基於建置參數的可選 Jupyter Lab
  • 非 root 執行 - 以專用的 petsard 使用者運行以提高安全性
  • 跨平台支援 - 針對 x86_64 和 ARM64 架構優化

CI/CD 整合

自動建置

專案使用 GitHub Actions 進行自動 Docker 建置:

# 由 semantic release 完成觸發
workflow_run:
  workflows: ["Semantic Release"]
  types: [completed]
  branches: [main, dev]

版本管理

  • Semantic Release 整合 - 版本號自動管理
  • 動態標籤 - 每次發布創建多個標籤:
    • latest(main 分支)
    • v1.4.0(特定版本)
    • 1.4(主要.次要版本)
    • 1(主要版本)

註冊表發布

映像檔發布到 GitHub Container Registry:

  • ghcr.io/nics-tw/petsard:latest
  • ghcr.io/nics-tw/petsard:v1.4.0

除錯問題

檢查容器日誌

# 檢查運行中容器的日誌
docker logs <container_id>

# 即時追蹤日誌
docker logs -f <container_id>

互動式除錯

# 啟動具有除錯存取權限的容器
docker run -it --rm \
  -v $(pwd):/workspace \
  petsard:jupyter \
  bash

# 除錯標準版本
docker run -it --rm \
  -v $(pwd):/workspace \
  petsard:standard \
  python

健康檢查除錯

# 手動健康檢查
docker run --rm petsard:latest python -c "
import importlib.metadata
try:
    version = importlib.metadata.version('petsard')
    print(f'✅ 健康檢查通過 - PETsARD v{version}')
except Exception as e:
    print(f'❌ 健康檢查失敗: {e}')
"

效能優化

建置優化

  • 層快取 - Dockerfile 針對 Docker 層快取優化
  • 多階段建置 - 更小的最終映像檔
  • 依賴快取 - 在程式碼複製前安裝需求

運行時優化

  • 虛擬環境 - 隔離的 Python 環境
  • 最小基礎映像檔 - python:3.11-slim 以減少佔用空間
  • 非 root 執行 - 安全性和權限優化

疑難排解

常見問題

  1. 建置失敗

    # 無快取的乾淨建置
    docker build --no-cache -t petsard:debug .
  2. 權限問題

    # 修正檔案權限
    docker run --rm -v $(pwd):/workspace \
      --user $(id -u):$(id -g) \
      petsard:dev chown -R $(id -u):$(id -g) /workspace
  3. 記憶體問題

    # 增加 Docker 記憶體限制
    docker run --memory=4g petsard:dev

環境變數

容器中使用的關鍵環境變數:

# Python 優化
PYTHONPATH=/app
PYTHONUNBUFFERED=1
PYTHONDONTWRITEBYTECODE=1

# Jupyter 專用(當 INCLUDE_JUPYTER=true 時)
JUPYTER_ENABLE_LAB=yes
JUPYTER_ALLOW_ROOT=1

# 建置變體指示器
INCLUDE_JUPYTER=true/false

最佳實踐

  1. 使用 Docker Compose 進行開發工作流程
  2. 本地測試 後再推送變更
  3. 監控映像檔大小 保持最小化
  4. 使用健康檢查 進行生產部署
  5. 遵循語義版本控制 進行映像檔標籤
  6. 記錄環境變數 和配置選項

安全考量

  • 非 root 使用者 在生產環境執行
  • 最小攻擊面 使用精簡基礎映像檔
  • 無硬編碼機密 在 Dockerfile 中
  • 定期基礎映像檔更新 以獲得安全修補程式