| # ==================== | |
| # 基礎映像檔設定 | |
| # ==================== | |
| # 使用輕量版 Python(固定具體版本避免意外更新) | |
| FROM python:3.12.7-slim | |
| # 安裝系統相依套件 | |
| RUN apt-get update && apt-get install -y \ | |
| build-essential \ | |
| libglib2.0-0 \ | |
| libgl1-mesa-glx \ | |
| && rm -rf /var/lib/apt/lists/* | |
| # ==================== | |
| # 環境變數設定 | |
| # ==================== | |
| # 設定 Python 環境變數以提升安全性和效能 | |
| ENV PYTHONUNBUFFERED=1 \ | |
| PYTHONDONTWRITEBYTECODE=1 \ | |
| PIP_NO_CACHE_DIR=1 \ | |
| PIP_DISABLE_PIP_VERSION_CHECK=1 | |
| # PYTHONUNBUFFERED=1: 確保 Python 輸出立即顯示 | |
| # PYTHONDONTWRITEBYTECODE=1: 防止生成 .pyc 檔案,減少映像檔大小 | |
| # PIP_NO_CACHE_DIR=1: 禁用 pip 快取,減少映像檔大小 | |
| # PIP_DISABLE_PIP_VERSION_CHECK=1: 禁用 pip 版本檢查,加速安裝 | |
| # ==================== | |
| # 使用者和群組設定 | |
| # ==================== | |
| # 建立專用的應用程式使用者和群組(早期建立以確保安全) | |
| RUN groupadd -r appgroup && \ | |
| useradd -r -g appgroup -u 1001 -d /app -s /sbin/nologin appuser | |
| # -r: 建立系統使用者/群組 | |
| # -u 1001: 指定 UID,避免與 host 使用者衝突 | |
| # -d /app: 設定家目錄 | |
| # -s /sbin/nologin: 禁止 shell 登入,增強安全性 | |
| # ==================== | |
| # 系統套件安裝 | |
| # ==================== | |
| # 安裝必要的系統相依套件並立即清理,減少映像檔大小和攻擊面 | |
| RUN apt-get update && \ | |
| apt-get install -y --no-install-recommends \ | |
| build-essential \ | |
| libglib2.0-0 \ | |
| libgl1-mesa-glx && \ | |
| apt-get clean && \ | |
| rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* | |
| # --no-install-recommends: 只安裝必要套件,不安裝建議套件 | |
| # 立即清理 apt 快取和臨時檔案 | |
| # ==================== | |
| # 工作目錄和權限設定 | |
| # ==================== | |
| # 設定應用程式工作目錄 | |
| WORKDIR /app | |
| # 建立必要目錄並設定適當權限(避免使用危險的 777 權限) | |
| # RUN mkdir -p /app/tmp /app/logs /app/data && \ | |
| # chown -R appuser:appgroup /app && \ | |
| # chmod 777 /app && \ | |
| # chmod 777 /app/tmp /app/logs /app/data | |
| # 755: 擁有者可讀寫執行,群組和其他人可讀執行 | |
| # 750: 擁有者可讀寫執行,群組可讀執行,其他人無權限 | |
| # ==================== | |
| # Python 依賴安裝 | |
| # ==================== | |
| # 先複製 requirements.txt(利用 Docker 層快取優化) | |
| COPY --chown=appuser:appgroup requirements.txt . | |
| # --chown: 複製時直接設定擁有者,避免額外的 chown 指令 | |
| # 升級 pip 並安裝 Python 套件 | |
| RUN pip install --upgrade pip && \ | |
| pip install --no-cache-dir -r requirements.txt | |
| # --no-cache-dir: 不使用快取,減少映像檔大小 | |
| # ==================== | |
| # 應用程式代碼複製 | |
| # ==================== | |
| # 複製應用程式代碼並設定擁有者 | |
| COPY --chown=appuser:appgroup . . | |
| # ==================== | |
| # 清理和優化 | |
| # ==================== | |
| # 移除不必要的 Python 快取檔案,進一步減少映像檔大小 | |
| RUN find /app -name "*.pyc" -delete && \ | |
| find /app -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true | |
| # 刪除所有 .pyc 檔案和 __pycache__ 目錄 | |
| # 2>/dev/null || true: 忽略錯誤訊息 | |
| # ==================== | |
| # 使用者切換 | |
| # ==================== | |
| # 切換到非特權使用者執行應用程式(重要安全措施) | |
| USER appuser | |
| # ==================== | |
| # 網路設定 | |
| # ==================== | |
| # 暴露應用程式端口 | |
| EXPOSE 7860 | |
| # ==================== | |
| # 健康檢查 | |
| # ==================== | |
| # 設定容器健康檢查,確保應用程式正常運作 | |
| HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ | |
| CMD curl -f http://localhost:7860/_stcore/health || exit 1 | |
| # --interval: 檢查間隔 | |
| # --timeout: 檢查超時時間 | |
| # --start-period: 啟動寬限期 | |
| # --retries: 重試次數 | |
| # ==================== | |
| # 應用程式啟動 | |
| # ==================== | |
| # 啟動 Streamlit 應用程式(啟用安全功能) | |
| ENV GRADIO_SERVER_NAME="0.0.0.0" | |
| CMD ["python", "app.py"] | |
| # enableXsrfProtection=true: 啟用 CSRF 保護 | |
| # enableCORS=false: 禁用跨域請求,增強安全性 | |
| # headless=true: 無頭模式,適合容器環境 |