jim800121chen 21f863ae1e fix(worker): real image 加 tensorflow 支援 tflite 輸入格式
staging real worker 轉 tflite 失敗:tflite→onnx 需要 import tensorflow,但
Dockerfile.real 當初為省 image 大小沒裝 TF(只驗過 onnx/bie/nef 輸入)。

改 services/workers/Dockerfile.real:
- 加 tensorflow-cpu==2.13.1(Python 3.9 相容 + numpy<2 相容 + ktc TF compat
  patch 預期範圍的交集;-cpu 省 ~1.5GB CUDA)
- 加 igraph==1.0.0(tree_structure.py 硬 import、pin 對齊本檔版本鎖哲學)
- 補 typing-extensions>=4.8.0(TF 會把它降版打爆 fastapi import)
- numpy<2 精確化為 numpy==1.23.5(落在原 <2 範圍 + TF 接受窗口、語意子集非破鎖)

本機驗證:image 4.36GB→5.71GB;tflite→onnx 通(產 188 節點合法 ONNX);既有
BIE→NEF 回歸產出同一顆真 NEF(621,956 bytes)、prebuild ldd 全 resolved。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 15:31:59 +08:00

137 lines
8.0 KiB
Docker
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Real Worker Dockerfile — 自帶 prebuild toolchain可實際把 BIE→NEF 真實轉檔
#
# 與 Dockerfile.stub 的差異:本 image 內含 ktc/ 真實轉檔素材 + toolchain/prebuild
# 的 x86-64 編譯 binariesbatch_compile / kneron_nef_utils / model_converter
# 並設好 USE_PREBUILD/LD_LIBRARY_PATH/PYTHONPATH讓 import ktc + ktc.compile 走
# repo 自帶 prebuild 路徑(不抓系統 libs/compiler、libs/dynasty
#
# Build從專案根目錄、本機 Docker daemon
# docker build -f services/workers/Dockerfile.real -t kneron-worker-real:verify .
#
# 注意build context 含 toolchain/prebuild (~2GB)。搭配「專案根 .dockerignore」
# docker build 以專案根為 context只讀 context 根目錄的 .dockerignore不存在
# services/workers/.dockerignore排除 libs/dynasty + libs/compiler被 USE_PREBUILD
# 取代,省 ~3.2GB)。
# python:3.9 對齊既有 workerbullseye(Debian 11, glibc 2.31) 對舊 toolchain
# prebuild ELF 最低需求 GNU/Linux 3.2.0)相容性最佳。
FROM python:3.9-slim-bullseye
WORKDIR /app
# --- System libraries ---------------------------------------------------------
# opencv-python runtime: libgl1 / libglib2.0-0
# OpenMP / OpenBLAScompiler binary 會用): libgomp1
# gfortran runtimeprebuild/lib 雖自帶 libgfortran.so.5,仍裝保險): libgfortran5
# 其餘缺的 .so 靠 image 內 `ldd toolchain/prebuild/batch_compile` 的 "not found" 補。
RUN apt-get update && apt-get install -y --no-install-recommends \
libgl1 \
libglib2.0-0 \
libgomp1 \
libgfortran5 \
ca-certificates \
procps \
file \
&& rm -rf /var/lib/apt/lists/*
# --- Python dependencies ------------------------------------------------------
# 1) queue / storageconsumer.py 需要)
# 2) worker 既有 requirementsfastapi/onnx/opencv…
# 3) ktc → sys_flow / sys_flow_v2 + extract_bie_info + kneronnxopt module-load 額外
# 需要(全部由本機實跑 `import ktc` 逐個盤出):
# pandas blinker docopt snoop pyzipper dict_recursive_update beautifulsoup4
# jinja2 matplotlib tabulate commentjson IPython adjustText onnx_tool onnxsim
#
# 特別注意的版本鎖:
# - onnx==1.14.1:與 root requirements 一致ktc/toolchain.py 對 onnx==1.7.0 會
# 關閉 730 支援,必須避開 1.7.0。
# - onnx_tool==0.7.0:未鎖時裝到的新版在 import 期會踩
# "unsupported operand type(s) for |: MessageMeta and type"protobuf 衝突);
# 0.7.0 import 乾淨。
# - onnxsim==0.4.36--only-binarypy3.9/bullseye 上新版 onnxsim 無 wheel、需
# cmake 從源碼編0.4.36 有 prebuilt wheel避免裝 build toolchain。
# 4) tflite 輸入格式轉檔tflite→onnx第一步 ktc.onnx_optimizer.tflite2onnx_flow
# 需要 tensorflow + python-igraphconverter: libs/ONNX_Convertor/tflite-onnx
# - tensorflow-cpu==2.13.1:挑此版的三重理由——
# (a) Python 3.9 相容2.13.x 支援 py3.83.11;再新的 TF2.16+drop py3.9。
# (b) numpy<2 相容最關鍵TF 2.13.1 要求 numpy>=1.22,<=1.24.3(全 1.x
# 與既有 prebuild 鏈的「numpy 1.x」硬需求一致再新的 TF2.16+)會拉
# numpy>=2 → 直接撞爆 prebuild 的 "numpy.core.multiarray failed to import"。
# (c) ktc 需求ktc/onnx_optimizer_1_13.py 的 _get_tensor_details_compat patch
# 是為「較新 TFtf.lite.Interpreter._get_tensor_details 需 subgraph_index
# TF 2.5+ 引入)」寫的 → TF 2.13.1 落在此範圍、patch 正常生效。
# 選 -cpu 版:不需 GPU、省下 CUDA 相關 ~1.5GB。
# - igraph==1.0.0converter 的 tree_structure.py:13 `from igraph import Graph` 硬
# import 需要不裝→tflite→onnx 第一步 ModuleNotFoundError。pin 死是為了
# reproducible build——igraph 是 tflite 鏈的硬依賴、裸裝 latest 未來重 build 可能
# 裝到行為改變的新版1.0.0 是本次 build 實裝並驗證可跑的版本。
# - typing-extensions>=4.8.0TF 2.13.1 會把 typing-extensions 降到 4.5.0
# (其 pin 是 <4.6),導致 fastapi 0.104.1 `import fastapi` 掛
# `cannot import name 'TypeAliasType'`。TF 對 typing-extensions 的上限只是
# *soft warning*(實測升到 4.15 後 tf 2.13.1 + tf.lite.Interpreter 仍正常),
# 故在 TF 之後把 typing-extensions 補回 >=4.8.0,修復 fastapi/pydantic。
# 5) numpy==1.23.5 最後裝並「釘死」prebuild 鏈的 C-extension 以 numpy 1.x 編譯,
# numpy 2.x 會出 "numpy.core.multiarray failed to import"。1.23.5 同時滿足
# TF 2.13.1 的 numpy>=1.22,<=1.24.3 窗口 + 既有 prebuild/onnx 的 1.x 需求。
# 最後安裝確保不被 TF/其他套件連帶升級。
COPY services/workers/nef/requirements.txt /tmp/worker-requirements.txt
RUN pip install --no-cache-dir \
redis>=5.0 boto3>=1.28 \
&& pip install --no-cache-dir -r /tmp/worker-requirements.txt \
&& pip install --no-cache-dir \
"onnx==1.14.1" \
scipy \
pandas blinker docopt snoop \
pyzipper dict_recursive_update beautifulsoup4 jinja2 matplotlib tabulate \
commentjson IPython adjustText "onnx_tool==0.7.0" \
&& pip install --no-cache-dir --only-binary :all: "onnxsim==0.4.36" \
&& pip install --no-cache-dir "tensorflow-cpu==2.13.1" "igraph==1.0.0" \
&& pip install --no-cache-dir "typing-extensions>=4.8.0" \
&& pip install --no-cache-dir "numpy==1.23.5"
# --- Application + toolchain source ------------------------------------------
# 精準 COPY避免把 libs/dynasty(2.0G) + libs/compiler(1.2G) 帶進來。
COPY ktc/ /app/ktc/
COPY vendor/ /app/vendor/
COPY services/ /app/services/
COPY toolchain/prebuild/ /app/toolchain/prebuild/
COPY libs/kneronnxopt/ /app/libs/kneronnxopt/
COPY libs/ONNX_Convertor/ /app/libs/ONNX_Convertor/
COPY libs/fpAnalyser/ /app/libs/fpAnalyser/
COPY E2E_Simulator/python_flow/ /app/E2E_Simulator/python_flow/
# 驗證用 fixtures + conftestproduction 部署可拿掉,這裡為了在 image 內端到端跑)
COPY tests/ /app/tests/
RUN mkdir -p /data/jobs
# --- Toolchain / runtime environment即 tests/conftest.py 的 production 化版本)---
ENV USE_PREBUILD=/app/toolchain/prebuild
ENV LD_LIBRARY_PATH=/app/toolchain/prebuild/lib
ENV PYTHONPATH=/app:/app/vendor:/app/libs:/app/libs/kneronnxopt:/app/E2E_Simulator/python_flow
ENV KTC_DISABLE_MP=1
# --- Worker runtime config ----------------------------------------------------
ENV WORKER_MODE=real
ENV REDIS_URL=redis://redis:6379
ENV JOB_DATA_DIR=/data/jobs
# STORAGE_BACKEND 刻意「不」在此 image 設預設值。
#
# 為什麼consumer.py 第 52 行 `os.environ.get("STORAGE_BACKEND", "local")` 本身
# 已會 fall back 到 local。若這支真實版 image 又寫死 ENV STORAGE_BACKEND=local會給
# 部署者「image 預設就能上雲」的錯覺;一旦 staging compose 漏設 STORAGE_BACKEND=minio
# worker 會 *安靜* 走 local產出寫 container 本機磁碟、不上 MinIO→ 轉檔成功但
# visionA poll 拿不到結果(即 commit b8457dd / cbd1b9d 修過的同類隱患)。
#
# 處理姿態:
# - 本 image 不設預設 → 由 compose / 部署環境「顯式」提供。
# - staging用 MinIO必設 `STORAGE_BACKEND=minio`(見部署 checklist 硬性項)。
# - 本機 / dev 不設時consumer.py 仍 fall back localstub/local 開發流程不受影響。
# - 註:要根除 silent fallback 的最穩做法是在 consumer.py 對 WORKER_MODE=real 做
# fail-fast漏設 minio 即報錯),但那屬 application code、需 backend 處理,
# 不在本 Dockerfile 範圍。
# STAGE: onnx / bie / nef三個 worker 共用此 image差在 entrypoint
ENV STAGE=nef
# 用 shell form 以便 ${STAGE} 變數展開(三個 worker 共用 image、差在此變數
CMD ["sh", "-c", "python -m services.workers.${STAGE}.worker"]