iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
Build on Google AI

給藥袋裝一張嘴:30 天用 Android 與 Google VLM 實作高齡語音用藥助手系列 第 21 篇

Day 21|映像檔瘦身 60%!實作 Docker 多階段建構與生產環境極速部署

  • 分享至 

  • xImage
  •  

✏️【本日實作紀錄:Docker 容器多階段建構與輕量化瘦身】

在 Day 20 完成 SQLite 資料庫自動熱備份 與 災難復原工具 後,PrescriptionVLM 系統的核心功能、無障礙 UX、資安防衛與資料備援機制已建置完畢。

隨著專案進入尾聲,我們需要將系統打包為適合生產環境部署的容器映像檔。原本的 Dockerfile 包含了完整的 Python 構建工具與編譯依賴,導致打包出來的映像檔體積高達 1 GB。這會增加伺服器拉取映像檔的頻寬成本,且包含了執行期不需要的開發工具。

今天我們將為 PrescriptionVLM 系統導入 Docker 多階段建構(Multi-Stage Build) 技術。完成項目包含:

  • Builder 與 Final 雙階段隔離 — 將編譯安裝 Python 套件的環境與最終執行環境分離。
  • 以 python:3.11-slim 為基礎映像檔 — 移除不必要的系統編譯器,縮減映像檔體積。
  • 最小權限原則 (Non-Root User) — 建立非 root 權限使用者執行容器,提升安全性。

一、Docker 多階段建構的設計

在生產環境的 Docker 最佳實踐中,多階段建構有以下好處:

  • 映像檔瘦身:將原本 1 GB 的映像檔壓縮至 300 MB 以下,節省 60% 的空間與傳輸時間。
  • 資安防護:正式環境的容器中不包含 gcc、g++ 等編譯工具,降低被利用的風險。
  • 快取優化:將 Python 套件編譯層與應用程式碼層分開,修改 app.py 時能快速重建。

二、改寫輕量化 Dockerfile

請開啟專案根目錄的 Dockerfile,將原本單一階段的內容替換為多階段建構結構:

# ── 階段 1: Builder 構建環境 ──
FROM python:3.11-slim AS builder

WORKDIR /app

# 安裝基礎編譯工具(僅用於安裝/編譯 Python 套件)
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    curl \
    && rm -rf /var/lib/apt/lists/*

# 先複製 requirements.txt 利用 Docker 快取機制
COPY requirements.txt .

# 將套件安裝至指定 Wheels/Site-Packages 目錄
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt


# ── 階段 2: Production 執行環境 ──
FROM python:3.11-slim AS final

WORKDIR /app

# 安裝必要的執行期系統庫(如 ffmpeg 或 curl)
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    && rm -rf /var/lib/apt/lists/*

# 從 Builder 階段複製已安裝好的 Python 套件
COPY --from=builder /install /usr/local

# 建立非 root 專用使用者,提升安全性
RUN useradd -m -u 1000 appuser && \
    mkdir -p /app/backups && \
    chown -R appuser:appuser /app

# 複製應用程式原始碼
COPY --chown=appuser:appuser . .

# 切換為非 root 使用者執行
USER appuser

EXPOSE 5000

CMD ["python", "app.py"]

三、更新 .dockerignore 排除不必要檔案

為了確保 Docker 建構時不會把不必要的快取檔與本地測試資料打入映像檔,請更新專案根目錄的 .dockerignore:

__pycache__/
*.pyc
*.pyo
*.pyd
.git/
.gitignore
.env
venv/
.venv/
backups/
*.db
*.db.enc
*.log

四、更新 docker-compose.yml 服務配置

確認根目錄的 docker-compose.yml 能正常使用優化後的 Dockerfile:

version: '3.8'

services:
  redis:
    image: redis:7.2-alpine
    container_name: prescription_redis
    ports:
      - "6379:6379"
    restart: always

  web:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: prescription_service
    ports:
      - "5000:5000"
    env_file:
      - .env
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    depends_on:
      - redis
    restart: always

五、測試與瘦身成果驗證

1. 執行多階段 Docker 重建

在 Terminal 執行命令啟動編譯:

docker-compose build --no-cache
  • 觀察過程:Terminal 會分成 [stage-0 1/5] (Builder) 與 [stage-1 1/6] (Final) 兩個階段循序構建。

2. 檢查映像檔體積縮減幅度

在 Terminal 查看生成的 Docker 映像檔大小:

docker images | grep prescription
  • 預期成果:原本的映像檔體積約在 850MB~950MB,優化後的 Multi-Stage 映像檔體積約 250MB~320MB,瘦身 60% 以上。

3. 容器運作功能測試

啟動容器並確認 API 服務正常:

docker-compose up -d
curl -i http://127.0.0.1:5000/dashboard
  • 預期成果:回傳 HTTP 200,儀表板與 API 均正常運作。

六、版本控制與提交 GitHub

測試通過後,將 Day 21 的修改提交至 GitHub:

git add Dockerfile .dockerignore docker-compose.yml
git commit -m "保留雙引號 改填寫自己要記錄的標記 ex.鐵人賽第二十一天"
git push

七、本日小結與明日預告

今天我們透過 Docker 多階段建構 與 最小權限使用者設置,將 PrescriptionVLM 系統的映像檔體積縮減 60% 以上,不僅加速了部署與升級流程,也提升了生產環境的安全性。

明天(Day 22),我們將實作 GitHub Actions CI/CD 自動化建構與測試流水線,讓每次 git push 都自動觸發單元測試與 Docker 映像檔打包!


上一篇
Day 20|資料安全不漏接!實作 SQLite 資料庫自動定期備份與災難復原機制
下一篇
Day 22|自動化防線到位!實作 GitHub Actions CI/CD 流水線與自動化測試
系列文
給藥袋裝一張嘴:30 天用 Android 與 Google VLM 實作高齡語音用藥助手 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言