fix: 添加 --break-system-packages 修復 uv pip install
This commit is contained in:
parent
b0d6aea234
commit
d03d084294
2 changed files with 562 additions and 582 deletions
572
Dockerfile
572
Dockerfile
|
|
@ -57,32 +57,32 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
# 配置 APT 重試機制
|
# 配置 APT 重試機制
|
||||||
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \
|
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::http::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::http::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::https::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::https::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::ftp::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::ftp::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'DPkg::Lock::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries
|
&& echo 'DPkg::Lock::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries
|
||||||
|
|
||||||
# 安裝基礎工具
|
# 安裝基礎工具
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
curl \
|
curl \
|
||||||
unzip \
|
unzip \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 安裝 Bun(根據架構選擇版本)
|
# 安裝 Bun(根據架構選擇版本)
|
||||||
RUN ARCH=$(uname -m) && \
|
RUN ARCH=$(uname -m) && \
|
||||||
if [ "$ARCH" = "aarch64" ]; then \
|
if [ "$ARCH" = "aarch64" ]; then \
|
||||||
curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
-o bun-linux-aarch64.zip \
|
-o bun-linux-aarch64.zip \
|
||||||
https://github.com/oven-sh/bun/releases/download/bun-v1.3.6/bun-linux-aarch64.zip; \
|
https://github.com/oven-sh/bun/releases/download/bun-v1.3.6/bun-linux-aarch64.zip; \
|
||||||
else \
|
else \
|
||||||
curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
-o bun-linux-x64-baseline.zip \
|
-o bun-linux-x64-baseline.zip \
|
||||||
https://github.com/oven-sh/bun/releases/download/bun-v1.3.6/bun-linux-x64-baseline.zip; \
|
https://github.com/oven-sh/bun/releases/download/bun-v1.3.6/bun-linux-x64-baseline.zip; \
|
||||||
fi && \
|
fi && \
|
||||||
unzip -j bun-linux-*.zip -d /usr/local/bin && \
|
unzip -j bun-linux-*.zip -d /usr/local/bin && \
|
||||||
rm bun-linux-*.zip && \
|
rm bun-linux-*.zip && \
|
||||||
chmod +x /usr/local/bin/bun
|
chmod +x /usr/local/bin/bun
|
||||||
|
|
||||||
# ===================================
|
# ===================================
|
||||||
# Stage 2: Install - Node Dependencies
|
# Stage 2: Install - Node Dependencies
|
||||||
|
|
@ -115,154 +115,154 @@ FROM base AS system-tools
|
||||||
|
|
||||||
# 配置 APT
|
# 配置 APT
|
||||||
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \
|
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::http::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::http::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::https::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::https::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::ftp::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::ftp::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'APT::Get::Assume-Yes "true";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'APT::Get::Assume-Yes "true";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'DPkg::Lock::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries
|
&& echo 'DPkg::Lock::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries
|
||||||
|
|
||||||
# 階段 4.1:基礎系統工具 + Locale
|
# 階段 4.1:基礎系統工具 + Locale
|
||||||
RUN echo "📦 [Stage 4.1] 安裝基礎系統工具..." && \
|
RUN echo "📦 [Stage 4.1] 安裝基礎系統工具..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
locales \
|
locales \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl \
|
curl \
|
||||||
openssl \
|
openssl \
|
||||||
git \
|
git \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.2:核心轉換工具(輕量)
|
# 階段 4.2:核心轉換工具(輕量)
|
||||||
RUN echo "📦 [Stage 4.2] 安裝核心轉換工具..." && \
|
RUN echo "📦 [Stage 4.2] 安裝核心轉換工具..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
assimp-utils \
|
assimp-utils \
|
||||||
dcraw \
|
dcraw \
|
||||||
dvisvgm \
|
dvisvgm \
|
||||||
ghostscript \
|
ghostscript \
|
||||||
graphicsmagick \
|
graphicsmagick \
|
||||||
mupdf-tools \
|
mupdf-tools \
|
||||||
poppler-utils \
|
poppler-utils \
|
||||||
potrace \
|
potrace \
|
||||||
qpdf \
|
qpdf \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.3:安裝 dasel(從 GitHub 二進位)
|
# 階段 4.3:安裝 dasel(從 GitHub 二進位)
|
||||||
RUN echo "📦 [Stage 4.3] 安裝 dasel..." && \
|
RUN echo "📦 [Stage 4.3] 安裝 dasel..." && \
|
||||||
ARCH=$(uname -m) && \
|
ARCH=$(uname -m) && \
|
||||||
if [ "$ARCH" = "aarch64" ]; then DASEL_ARCH="linux_arm64"; \
|
if [ "$ARCH" = "aarch64" ]; then DASEL_ARCH="linux_arm64"; \
|
||||||
else DASEL_ARCH="linux_amd64"; fi && \
|
else DASEL_ARCH="linux_amd64"; fi && \
|
||||||
curl -sSLf --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -sSLf --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
"https://github.com/TomWright/dasel/releases/download/v2.8.1/dasel_${DASEL_ARCH}" \
|
"https://github.com/TomWright/dasel/releases/download/v2.8.1/dasel_${DASEL_ARCH}" \
|
||||||
-o /usr/local/bin/dasel && \
|
-o /usr/local/bin/dasel && \
|
||||||
chmod +x /usr/local/bin/dasel
|
chmod +x /usr/local/bin/dasel
|
||||||
|
|
||||||
# 階段 4.4:安裝 resvg(僅 x86_64)
|
# 階段 4.4:安裝 resvg(僅 x86_64)
|
||||||
RUN echo "📦 [Stage 4.4] 安裝 resvg..." && \
|
RUN echo "📦 [Stage 4.4] 安裝 resvg..." && \
|
||||||
ARCH=$(uname -m) && \
|
ARCH=$(uname -m) && \
|
||||||
if [ "$ARCH" = "aarch64" ]; then \
|
if [ "$ARCH" = "aarch64" ]; then \
|
||||||
echo "⚠️ resvg 無 ARM64 版本,跳過"; \
|
echo "⚠️ resvg 無 ARM64 版本,跳過"; \
|
||||||
else \
|
else \
|
||||||
curl -sSLf --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -sSLf --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
"https://github.com/linebender/resvg/releases/download/v0.44.0/resvg-linux-x86_64.tar.gz" \
|
"https://github.com/linebender/resvg/releases/download/v0.44.0/resvg-linux-x86_64.tar.gz" \
|
||||||
-o /tmp/resvg.tar.gz && \
|
-o /tmp/resvg.tar.gz && \
|
||||||
tar -xzf /tmp/resvg.tar.gz -C /tmp/ && \
|
tar -xzf /tmp/resvg.tar.gz -C /tmp/ && \
|
||||||
mv /tmp/resvg /usr/local/bin/resvg && \
|
mv /tmp/resvg /usr/local/bin/resvg && \
|
||||||
chmod +x /usr/local/bin/resvg && \
|
chmod +x /usr/local/bin/resvg && \
|
||||||
rm -rf /tmp/resvg.tar.gz; \
|
rm -rf /tmp/resvg.tar.gz; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 階段 4.5:編譯安裝 deark
|
# 階段 4.5:編譯安裝 deark
|
||||||
RUN echo "📦 [Stage 4.5] 編譯 deark..." && \
|
RUN echo "📦 [Stage 4.5] 編譯 deark..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
&& cd /tmp && \
|
&& cd /tmp && \
|
||||||
git clone --depth 1 https://github.com/jsummers/deark.git && \
|
git clone --depth 1 https://github.com/jsummers/deark.git && \
|
||||||
cd deark && make -j$(nproc) && \
|
cd deark && make -j$(nproc) && \
|
||||||
cp deark /usr/local/bin/deark && \
|
cp deark /usr/local/bin/deark && \
|
||||||
chmod +x /usr/local/bin/deark && \
|
chmod +x /usr/local/bin/deark && \
|
||||||
cd / && rm -rf /tmp/deark && \
|
cd / && rm -rf /tmp/deark && \
|
||||||
apt-get remove -y build-essential && \
|
apt-get remove -y build-essential && \
|
||||||
apt-get autoremove -y && \
|
apt-get autoremove -y && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.6:影音處理工具
|
# 階段 4.6:影音處理工具
|
||||||
RUN echo "📦 [Stage 4.6] 安裝 FFmpeg..." && \
|
RUN echo "📦 [Stage 4.6] 安裝 FFmpeg..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
libavcodec-extra \
|
libavcodec-extra \
|
||||||
libva2 \
|
libva2 \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.7:圖像處理工具(含 ImageMagick)
|
# 階段 4.7:圖像處理工具(含 ImageMagick)
|
||||||
# ⚠️ 修復:確保 ImageMagick 已安裝
|
# ⚠️ 修復:確保 ImageMagick 已安裝
|
||||||
RUN echo "📦 [Stage 4.7] 安裝圖像處理工具(含 ImageMagick)..." && \
|
RUN echo "📦 [Stage 4.7] 安裝圖像處理工具(含 ImageMagick)..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
imagemagick \
|
imagemagick \
|
||||||
inkscape \
|
inkscape \
|
||||||
libheif-examples \
|
libheif-examples \
|
||||||
libjxl-tools \
|
libjxl-tools \
|
||||||
libvips-tools \
|
libvips-tools \
|
||||||
xauth \
|
xauth \
|
||||||
xvfb \
|
xvfb \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.8:文件處理工具
|
# 階段 4.8:文件處理工具
|
||||||
RUN echo "📦 [Stage 4.8] 安裝 Calibre + Pandoc..." && \
|
RUN echo "📦 [Stage 4.8] 安裝 Calibre + Pandoc..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
calibre \
|
calibre \
|
||||||
libemail-outlook-message-perl \
|
libemail-outlook-message-perl \
|
||||||
pandoc \
|
pandoc \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.9:LibreOffice
|
# 階段 4.9:LibreOffice
|
||||||
RUN echo "📦 [Stage 4.9] 安裝 LibreOffice(需數分鐘)..." && \
|
RUN echo "📦 [Stage 4.9] 安裝 LibreOffice(需數分鐘)..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
libreoffice \
|
libreoffice \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.10:TexLive 基礎
|
# 階段 4.10:TexLive 基礎
|
||||||
RUN echo "📦 [Stage 4.10] 安裝 TexLive 基礎..." && \
|
RUN echo "📦 [Stage 4.10] 安裝 TexLive 基礎..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
texlive-base \
|
texlive-base \
|
||||||
texlive-latex-base \
|
texlive-latex-base \
|
||||||
texlive-latex-recommended \
|
texlive-latex-recommended \
|
||||||
texlive-fonts-recommended \
|
texlive-fonts-recommended \
|
||||||
texlive-xetex \
|
texlive-xetex \
|
||||||
latexmk \
|
latexmk \
|
||||||
lmodern \
|
lmodern \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.11:TexLive 語言包
|
# 階段 4.11:TexLive 語言包
|
||||||
RUN echo "📦 [Stage 4.11] 安裝 TexLive 語言包..." && \
|
RUN echo "📦 [Stage 4.11] 安裝 TexLive 語言包..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
texlive-lang-cjk \
|
texlive-lang-cjk \
|
||||||
texlive-lang-german \
|
texlive-lang-german \
|
||||||
texlive-lang-french \
|
texlive-lang-french \
|
||||||
texlive-lang-arabic \
|
texlive-lang-arabic \
|
||||||
texlive-lang-other \
|
texlive-lang-other \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.12:OCR 支援
|
# 階段 4.12:OCR 支援
|
||||||
RUN echo "📦 [Stage 4.12] 安裝 Tesseract OCR..." && \
|
RUN echo "📦 [Stage 4.12] 安裝 Tesseract OCR..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
tesseract-ocr \
|
tesseract-ocr \
|
||||||
tesseract-ocr-eng \
|
tesseract-ocr-eng \
|
||||||
tesseract-ocr-chi-tra \
|
tesseract-ocr-chi-tra \
|
||||||
tesseract-ocr-chi-sim \
|
tesseract-ocr-chi-sim \
|
||||||
tesseract-ocr-jpn \
|
tesseract-ocr-jpn \
|
||||||
tesseract-ocr-kor \
|
tesseract-ocr-kor \
|
||||||
tesseract-ocr-deu \
|
tesseract-ocr-deu \
|
||||||
tesseract-ocr-fra \
|
tesseract-ocr-fra \
|
||||||
ocrmypdf \
|
ocrmypdf \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.13:字型
|
# 階段 4.13:字型
|
||||||
RUN echo "📦 [Stage 4.13] 安裝系統字型..." && \
|
RUN echo "📦 [Stage 4.13] 安裝系統字型..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
fonts-noto-cjk \
|
fonts-noto-cjk \
|
||||||
fonts-noto-core \
|
fonts-noto-core \
|
||||||
fonts-noto-color-emoji \
|
fonts-noto-color-emoji \
|
||||||
fonts-liberation \
|
fonts-liberation \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# ===================================
|
# ===================================
|
||||||
# Stage 5: Python Base
|
# Stage 5: Python Base
|
||||||
|
|
@ -271,21 +271,21 @@ FROM system-tools AS python-base
|
||||||
|
|
||||||
# 階段 5.1:Python 基礎 + uv
|
# 階段 5.1:Python 基礎 + uv
|
||||||
RUN echo "📦 [Stage 5.1] 安裝 Python 基礎..." && \
|
RUN echo "📦 [Stage 5.1] 安裝 Python 基礎..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
python3 \
|
python3 \
|
||||||
python3-pip \
|
python3-pip \
|
||||||
python3-venv \
|
python3-venv \
|
||||||
python3-numpy \
|
python3-numpy \
|
||||||
python3-tinycss2 \
|
python3-tinycss2 \
|
||||||
python3-opencv \
|
python3-opencv \
|
||||||
python3-img2pdf \
|
python3-img2pdf \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 5.2:安裝 uv(Python 套件管理器)
|
# 階段 5.2:安裝 uv(Python 套件管理器)
|
||||||
# ⚠️ 重要:使用 uv 作為主要安裝方式,確保一致性
|
# ⚠️ 重要:使用 uv 作為主要安裝方式,確保一致性
|
||||||
RUN echo "📦 [Stage 5.2] 安裝 uv..." && \
|
RUN echo "📦 [Stage 5.2] 安裝 uv..." && \
|
||||||
pip3 install --no-cache-dir --break-system-packages uv && \
|
pip3 install --no-cache-dir --break-system-packages uv && \
|
||||||
uv --version
|
uv --version
|
||||||
|
|
||||||
# 設定 PATH
|
# 設定 PATH
|
||||||
ENV PATH="/root/.local/bin:/usr/local/bin:${PATH}"
|
ENV PATH="/root/.local/bin:/usr/local/bin:${PATH}"
|
||||||
|
|
@ -297,26 +297,16 @@ FROM python-base AS python-tools
|
||||||
|
|
||||||
# 階段 6.1:安裝 huggingface_hub + endesive(PDF 簽章)
|
# 階段 6.1:安裝 huggingface_hub + endesive(PDF 簽章)
|
||||||
RUN echo "📦 [Stage 6.1] 安裝 huggingface_hub + endesive..." && \
|
RUN echo "📦 [Stage 6.1] 安裝 huggingface_hub + endesive..." && \
|
||||||
apt-get update && apt-get install -y --no-install-recommends \
|
apt-get update && apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
swig \
|
swig \
|
||||||
libpcsclite-dev \
|
libpcsclite-dev \
|
||||||
&& uv pip install --system --no-cache huggingface_hub endesive && \
|
&& uv pip install --system --break-system-packages --no-cache huggingface_hub endesive && \
|
||||||
apt-get remove -y build-essential swig && \
|
uv pip install --system --break-system-packages --no-cache "markitdown[all]"
|
||||||
apt-get autoremove -y && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# 階段 6.2:安裝 markitdown
|
|
||||||
RUN echo "📦 [Stage 6.2] 安裝 markitdown..." && \
|
|
||||||
uv pip install --system --no-cache "markitdown[all]"
|
|
||||||
|
|
||||||
# 階段 6.3:安裝 pdf2zh
|
|
||||||
RUN echo "📦 [Stage 6.3] 安裝 pdf2zh..." && \
|
RUN echo "📦 [Stage 6.3] 安裝 pdf2zh..." && \
|
||||||
uv pip install --system --no-cache pdf2zh
|
uv pip install --system --break-system-packages --no-cache pdf2zh
|
||||||
|
|
||||||
# 階段 6.4:安裝 babeldoc
|
|
||||||
RUN echo "📦 [Stage 6.4] 安裝 babeldoc..." && \
|
RUN echo "📦 [Stage 6.4] 安裝 babeldoc..." && \
|
||||||
uv pip install --system --no-cache babeldoc || echo "⚠️ babeldoc 安裝可能有警告"
|
uv pip install --system --break-system-packages --no-cache babeldoc || echo "⚠️ babeldoc 安裝可能有警告"
|
||||||
|
|
||||||
# 階段 6.5:安裝 MinerU(⚠️ 關鍵修復)
|
# 階段 6.5:安裝 MinerU(⚠️ 關鍵修復)
|
||||||
# ⚠️ 只使用 system-level 安裝(uv pip install --system)
|
# ⚠️ 只使用 system-level 安裝(uv pip install --system)
|
||||||
|
|
@ -327,7 +317,7 @@ RUN echo "📦 [Stage 6.5] 安裝 MinerU(system-level only)..." && \
|
||||||
echo "⚠️ ARM64:MinerU 不支援,跳過"; \
|
echo "⚠️ ARM64:MinerU 不支援,跳過"; \
|
||||||
else \
|
else \
|
||||||
echo "🔧 使用 uv pip install --system(官方推薦)..." && \
|
echo "🔧 使用 uv pip install --system(官方推薦)..." && \
|
||||||
uv pip install --system --no-cache -U "mineru[all]" && \
|
uv pip install --system --break-system-packages --no-cache -U "mineru[all]" && \
|
||||||
echo "✅ 驗證 MinerU 安裝..." && \
|
echo "✅ 驗證 MinerU 安裝..." && \
|
||||||
which mineru && \
|
which mineru && \
|
||||||
mineru --version || echo "(版本資訊可能不可用)"; \
|
mineru --version || echo "(版本資訊可能不可用)"; \
|
||||||
|
|
@ -345,10 +335,10 @@ ENV HF_HOME="/tmp/hf_download_cache"
|
||||||
|
|
||||||
# 階段 7.1:創建目錄結構
|
# 階段 7.1:創建目錄結構
|
||||||
RUN mkdir -p "${MINERU_MODELS_DIR}" && \
|
RUN mkdir -p "${MINERU_MODELS_DIR}" && \
|
||||||
mkdir -p "${BABELDOC_CACHE_DIR}/models" && \
|
mkdir -p "${BABELDOC_CACHE_DIR}/models" && \
|
||||||
mkdir -p "${BABELDOC_CACHE_DIR}/fonts" && \
|
mkdir -p "${BABELDOC_CACHE_DIR}/fonts" && \
|
||||||
mkdir -p "${BABELDOC_CACHE_DIR}/cmap" && \
|
mkdir -p "${BABELDOC_CACHE_DIR}/cmap" && \
|
||||||
mkdir -p "${BABELDOC_CACHE_DIR}/tiktoken"
|
mkdir -p "${BABELDOC_CACHE_DIR}/tiktoken"
|
||||||
|
|
||||||
# 階段 7.2:下載 MinerU Pipeline 模型
|
# 階段 7.2:下載 MinerU Pipeline 模型
|
||||||
# ⚠️ 關鍵修復:使用顯式下載,存放到固定目錄
|
# ⚠️ 關鍵修復:使用顯式下載,存放到固定目錄
|
||||||
|
|
@ -416,16 +406,16 @@ EOF
|
||||||
# 階段 7.4:BabelDOC warmup + 資源下載
|
# 階段 7.4:BabelDOC warmup + 資源下載
|
||||||
# ⚠️ 關鍵修復:完整 warmup,確保所有資源已下載
|
# ⚠️ 關鍵修復:完整 warmup,確保所有資源已下載
|
||||||
RUN echo "📥 [Stage 7.4] BabelDOC warmup..." && \
|
RUN echo "📥 [Stage 7.4] BabelDOC warmup..." && \
|
||||||
export BABELDOC_CACHE_PATH="${BABELDOC_CACHE_DIR}" && \
|
export BABELDOC_CACHE_PATH="${BABELDOC_CACHE_DIR}" && \
|
||||||
if command -v babeldoc >/dev/null 2>&1; then \
|
if command -v babeldoc >/dev/null 2>&1; then \
|
||||||
echo "執行 babeldoc --warmup..." && \
|
echo "執行 babeldoc --warmup..." && \
|
||||||
babeldoc --warmup 2>&1 || echo "⚠️ warmup 可能有警告" && \
|
babeldoc --warmup 2>&1 || echo "⚠️ warmup 可能有警告" && \
|
||||||
echo "驗證 BabelDOC 資源..." && \
|
echo "驗證 BabelDOC 資源..." && \
|
||||||
ls -la "${BABELDOC_CACHE_DIR}/" && \
|
ls -la "${BABELDOC_CACHE_DIR}/" && \
|
||||||
du -sh "${BABELDOC_CACHE_DIR}/" || true; \
|
du -sh "${BABELDOC_CACHE_DIR}/" || true; \
|
||||||
else \
|
else \
|
||||||
echo "⚠️ babeldoc 不可用,跳過 warmup"; \
|
echo "⚠️ babeldoc 不可用,跳過 warmup"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 階段 7.5:下載 tiktoken 編碼(BabelDOC 依賴)
|
# 階段 7.5:下載 tiktoken 編碼(BabelDOC 依賴)
|
||||||
RUN <<EOF
|
RUN <<EOF
|
||||||
|
|
@ -446,12 +436,12 @@ EOF
|
||||||
|
|
||||||
# 階段 7.6:清理下載 cache(保留實際模型)
|
# 階段 7.6:清理下載 cache(保留實際模型)
|
||||||
RUN echo "🧹 [Stage 7.6] 清理下載 cache..." && \
|
RUN echo "🧹 [Stage 7.6] 清理下載 cache..." && \
|
||||||
rm -rf /tmp/hf_download_cache && \
|
rm -rf /tmp/hf_download_cache && \
|
||||||
rm -rf /root/.cache/huggingface && \
|
rm -rf /root/.cache/huggingface && \
|
||||||
rm -rf /root/.cache/pip && \
|
rm -rf /root/.cache/pip && \
|
||||||
rm -rf /root/.cache/uv && \
|
rm -rf /root/.cache/uv && \
|
||||||
find /usr -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true && \
|
find /usr -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true && \
|
||||||
echo "✅ Cache 清理完成"
|
echo "✅ Cache 清理完成"
|
||||||
|
|
||||||
# ===================================
|
# ===================================
|
||||||
# Stage 8: Final Image
|
# Stage 8: Final Image
|
||||||
|
|
@ -481,16 +471,16 @@ COPY models/ /root/.cache/babeldoc/models/
|
||||||
|
|
||||||
# 複製字型到 BabelDOC 目錄
|
# 複製字型到 BabelDOC 目錄
|
||||||
RUN mkdir -p /root/.cache/babeldoc/fonts && \
|
RUN mkdir -p /root/.cache/babeldoc/fonts && \
|
||||||
cp /usr/share/fonts/truetype/custom/GoNotoKurrent-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
cp /usr/share/fonts/truetype/custom/GoNotoKurrent-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
||||||
cp /usr/share/fonts/truetype/custom/SourceHanSerifCN-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
cp /usr/share/fonts/truetype/custom/SourceHanSerifCN-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
||||||
cp /usr/share/fonts/truetype/custom/SourceHanSerifTW-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
cp /usr/share/fonts/truetype/custom/SourceHanSerifTW-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
||||||
cp /usr/share/fonts/truetype/custom/SourceHanSerifJP-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
cp /usr/share/fonts/truetype/custom/SourceHanSerifJP-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
||||||
cp /usr/share/fonts/truetype/custom/SourceHanSerifKR-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true
|
cp /usr/share/fonts/truetype/custom/SourceHanSerifKR-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true
|
||||||
|
|
||||||
# 同步 BabelDOC cache 從固定目錄
|
# 同步 BabelDOC cache 從固定目錄
|
||||||
RUN if [ -d /opt/babeldoc/cache ]; then \
|
RUN if [ -d /opt/babeldoc/cache ]; then \
|
||||||
cp -r /opt/babeldoc/cache/* /root/.cache/babeldoc/ 2>/dev/null || true; \
|
cp -r /opt/babeldoc/cache/* /root/.cache/babeldoc/ 2>/dev/null || true; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 更新字型 cache
|
# 更新字型 cache
|
||||||
RUN fc-cache -fv
|
RUN fc-cache -fv
|
||||||
|
|
@ -499,56 +489,56 @@ RUN fc-cache -fv
|
||||||
# PDF 簽章憑證
|
# PDF 簽章憑證
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN mkdir -p /app/certs && \
|
RUN mkdir -p /app/certs && \
|
||||||
openssl req -x509 -newkey rsa:2048 \
|
openssl req -x509 -newkey rsa:2048 \
|
||||||
-keyout /tmp/key.pem -out /tmp/cert.pem \
|
-keyout /tmp/key.pem -out /tmp/cert.pem \
|
||||||
-days 3650 -nodes \
|
-days 3650 -nodes \
|
||||||
-subj "/CN=PDF Packager Default/O=ConvertX-CN/C=TW" && \
|
-subj "/CN=PDF Packager Default/O=ConvertX-CN/C=TW" && \
|
||||||
openssl pkcs12 -export \
|
openssl pkcs12 -export \
|
||||||
-inkey /tmp/key.pem -in /tmp/cert.pem \
|
-inkey /tmp/key.pem -in /tmp/cert.pem \
|
||||||
-out /app/certs/default.p12 \
|
-out /app/certs/default.p12 \
|
||||||
-passout pass: && \
|
-passout pass: && \
|
||||||
rm -f /tmp/key.pem /tmp/cert.pem && \
|
rm -f /tmp/key.pem /tmp/cert.pem && \
|
||||||
chmod 644 /app/certs/default.p12
|
chmod 644 /app/certs/default.p12
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# VTracer
|
# VTracer
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN ARCH=$(uname -m) && \
|
RUN ARCH=$(uname -m) && \
|
||||||
if [ "$ARCH" = "aarch64" ]; then \
|
if [ "$ARCH" = "aarch64" ]; then \
|
||||||
VTRACER_ASSET="vtracer-aarch64-unknown-linux-musl.tar.gz"; \
|
VTRACER_ASSET="vtracer-aarch64-unknown-linux-musl.tar.gz"; \
|
||||||
else \
|
else \
|
||||||
VTRACER_ASSET="vtracer-x86_64-unknown-linux-musl.tar.gz"; \
|
VTRACER_ASSET="vtracer-x86_64-unknown-linux-musl.tar.gz"; \
|
||||||
fi && \
|
fi && \
|
||||||
curl -L --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -L --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
-o /tmp/vtracer.tar.gz \
|
-o /tmp/vtracer.tar.gz \
|
||||||
"https://github.com/visioncortex/vtracer/releases/download/0.6.4/${VTRACER_ASSET}" && \
|
"https://github.com/visioncortex/vtracer/releases/download/0.6.4/${VTRACER_ASSET}" && \
|
||||||
tar -xzf /tmp/vtracer.tar.gz -C /tmp/ && \
|
tar -xzf /tmp/vtracer.tar.gz -C /tmp/ && \
|
||||||
mv /tmp/vtracer /usr/local/bin/vtracer && \
|
mv /tmp/vtracer /usr/local/bin/vtracer && \
|
||||||
chmod +x /usr/local/bin/vtracer && \
|
chmod +x /usr/local/bin/vtracer && \
|
||||||
rm /tmp/vtracer.tar.gz
|
rm /tmp/vtracer.tar.gz
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# Locale 設定
|
# Locale 設定
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
|
RUN sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# zh_TW.UTF-8 UTF-8/zh_TW.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# zh_TW.UTF-8 UTF-8/zh_TW.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
locale-gen
|
locale-gen
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# 最終清理
|
# 最終清理
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN rm -rf /usr/share/doc/texlive* \
|
RUN rm -rf /usr/share/doc/texlive* \
|
||||||
&& rm -rf /usr/share/texlive/texmf-dist/doc \
|
&& rm -rf /usr/share/texlive/texmf-dist/doc \
|
||||||
&& rm -rf /usr/share/doc/* \
|
&& rm -rf /usr/share/doc/* \
|
||||||
&& rm -rf /usr/share/man/* \
|
&& rm -rf /usr/share/man/* \
|
||||||
&& rm -rf /usr/share/info/* \
|
&& rm -rf /usr/share/info/* \
|
||||||
&& rm -rf /tmp/* \
|
&& rm -rf /tmp/* \
|
||||||
&& rm -rf /var/tmp/*
|
&& rm -rf /var/tmp/*
|
||||||
|
|
||||||
# 複製驗證腳本
|
# 複製驗證腳本
|
||||||
COPY scripts/verify-models.sh /app/scripts/verify-models.sh
|
COPY scripts/verify-models.sh /app/scripts/verify-models.sh
|
||||||
|
|
@ -563,77 +553,77 @@ RUN mkdir -p data
|
||||||
# ⚠️ 此步驟模擬斷網環境,驗證所有工具可離線執行
|
# ⚠️ 此步驟模擬斷網環境,驗證所有工具可離線執行
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN echo "======================================" && \
|
RUN echo "======================================" && \
|
||||||
echo "🔒 Runtime 離線驗證" && \
|
echo "🔒 Runtime 離線驗證" && \
|
||||||
echo "======================================" && \
|
echo "======================================" && \
|
||||||
ARCH=$(uname -m) && \
|
ARCH=$(uname -m) && \
|
||||||
VALIDATION_PASSED=true && \
|
VALIDATION_PASSED=true && \
|
||||||
\
|
\
|
||||||
# 驗證 MinerU
|
# 驗證 MinerU
|
||||||
echo "🔍 驗證 MinerU..." && \
|
echo "🔍 驗證 MinerU..." && \
|
||||||
if [ "$ARCH" != "aarch64" ]; then \
|
if [ "$ARCH" != "aarch64" ]; then \
|
||||||
if command -v mineru >/dev/null 2>&1; then \
|
if command -v mineru >/dev/null 2>&1; then \
|
||||||
echo " ✅ mineru 可執行: $(which mineru)"; \
|
echo " ✅ mineru 可執行: $(which mineru)"; \
|
||||||
else \
|
else \
|
||||||
echo " ❌ mineru 不可執行" && VALIDATION_PASSED=false; \
|
echo " ❌ mineru 不可執行" && VALIDATION_PASSED=false; \
|
||||||
fi && \
|
fi && \
|
||||||
if [ -d "/opt/mineru/models/PDF-Extract-Kit-1.0" ]; then \
|
if [ -d "/opt/mineru/models/PDF-Extract-Kit-1.0" ]; then \
|
||||||
echo " ✅ MinerU 模型目錄存在"; \
|
echo " ✅ MinerU 模型目錄存在"; \
|
||||||
else \
|
else \
|
||||||
echo " ❌ MinerU 模型目錄不存在" && VALIDATION_PASSED=false; \
|
echo " ❌ MinerU 模型目錄不存在" && VALIDATION_PASSED=false; \
|
||||||
fi && \
|
fi && \
|
||||||
if [ -f "/root/mineru.json" ]; then \
|
if [ -f "/root/mineru.json" ]; then \
|
||||||
echo " ✅ mineru.json 存在"; \
|
echo " ✅ mineru.json 存在"; \
|
||||||
else \
|
else \
|
||||||
echo " ❌ mineru.json 不存在" && VALIDATION_PASSED=false; \
|
echo " ❌ mineru.json 不存在" && VALIDATION_PASSED=false; \
|
||||||
fi; \
|
fi; \
|
||||||
else \
|
else \
|
||||||
echo " ⚠️ ARM64:跳過 MinerU 驗證"; \
|
echo " ⚠️ ARM64:跳過 MinerU 驗證"; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證 BabelDOC
|
# 驗證 BabelDOC
|
||||||
echo "🔍 驗證 BabelDOC..." && \
|
echo "🔍 驗證 BabelDOC..." && \
|
||||||
if command -v babeldoc >/dev/null 2>&1; then \
|
if command -v babeldoc >/dev/null 2>&1; then \
|
||||||
babeldoc --help >/dev/null 2>&1 && echo " ✅ babeldoc --help 成功" || echo " ⚠️ babeldoc --help 有警告"; \
|
babeldoc --help >/dev/null 2>&1 && echo " ✅ babeldoc --help 成功" || echo " ⚠️ babeldoc --help 有警告"; \
|
||||||
else \
|
else \
|
||||||
echo " ⚠️ babeldoc 不可用"; \
|
echo " ⚠️ babeldoc 不可用"; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證 pdf2zh
|
# 驗證 pdf2zh
|
||||||
echo "🔍 驗證 pdf2zh..." && \
|
echo "🔍 驗證 pdf2zh..." && \
|
||||||
if command -v pdf2zh >/dev/null 2>&1; then \
|
if command -v pdf2zh >/dev/null 2>&1; then \
|
||||||
pdf2zh --help >/dev/null 2>&1 && echo " ✅ pdf2zh --help 成功" || echo " ⚠️ pdf2zh --help 有警告"; \
|
pdf2zh --help >/dev/null 2>&1 && echo " ✅ pdf2zh --help 成功" || echo " ⚠️ pdf2zh --help 有警告"; \
|
||||||
else \
|
else \
|
||||||
echo " ⚠️ pdf2zh 不可用"; \
|
echo " ⚠️ pdf2zh 不可用"; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證 ImageMagick
|
# 驗證 ImageMagick
|
||||||
echo "🔍 驗證 ImageMagick..." && \
|
echo "🔍 驗證 ImageMagick..." && \
|
||||||
if command -v convert >/dev/null 2>&1; then \
|
if command -v convert >/dev/null 2>&1; then \
|
||||||
echo " ✅ ImageMagick 已安裝: $(convert --version | head -1)"; \
|
echo " ✅ ImageMagick 已安裝: $(convert --version | head -1)"; \
|
||||||
else \
|
else \
|
||||||
echo " ❌ ImageMagick 未安裝" && VALIDATION_PASSED=false; \
|
echo " ❌ ImageMagick 未安裝" && VALIDATION_PASSED=false; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證模型檔案
|
# 驗證模型檔案
|
||||||
echo "🔍 驗證 ONNX 模型..." && \
|
echo "🔍 驗證 ONNX 模型..." && \
|
||||||
if [ -f "/root/.cache/babeldoc/models/doclayout_yolo_docstructbench_imgsz1024.onnx" ]; then \
|
if [ -f "/root/.cache/babeldoc/models/doclayout_yolo_docstructbench_imgsz1024.onnx" ]; then \
|
||||||
echo " ✅ DocLayout-YOLO ONNX 存在"; \
|
echo " ✅ DocLayout-YOLO ONNX 存在"; \
|
||||||
else \
|
else \
|
||||||
echo " ⚠️ DocLayout-YOLO ONNX 不存在(將使用 COPY 複製)"; \
|
echo " ⚠️ DocLayout-YOLO ONNX 不存在(將使用 COPY 複製)"; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證字型
|
# 驗證字型
|
||||||
echo "🔍 驗證字型..." && \
|
echo "🔍 驗證字型..." && \
|
||||||
FONTS_COUNT=$(ls /usr/share/fonts/truetype/custom/*.ttf 2>/dev/null | wc -l) && \
|
FONTS_COUNT=$(ls /usr/share/fonts/truetype/custom/*.ttf 2>/dev/null | wc -l) && \
|
||||||
echo " ✅ 自訂字型數量: ${FONTS_COUNT}" && \
|
echo " ✅ 自訂字型數量: ${FONTS_COUNT}" && \
|
||||||
\
|
\
|
||||||
echo "======================================" && \
|
echo "======================================" && \
|
||||||
if [ "$VALIDATION_PASSED" = "true" ]; then \
|
if [ "$VALIDATION_PASSED" = "true" ]; then \
|
||||||
echo "✅ 離線驗證通過!"; \
|
echo "✅ 離線驗證通過!"; \
|
||||||
else \
|
else \
|
||||||
echo "❌ 離線驗證失敗!" && exit 1; \
|
echo "❌ 離線驗證失敗!" && exit 1; \
|
||||||
fi && \
|
fi && \
|
||||||
echo "======================================"
|
echo "======================================"
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# 🔐 Runtime 環境變數(強制離線模式)
|
# 🔐 Runtime 環境變數(強制離線模式)
|
||||||
|
|
|
||||||
|
|
@ -57,32 +57,32 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
# 配置 APT 重試機制
|
# 配置 APT 重試機制
|
||||||
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \
|
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::http::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::http::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::https::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::https::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::ftp::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::ftp::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'DPkg::Lock::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries
|
&& echo 'DPkg::Lock::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries
|
||||||
|
|
||||||
# 安裝基礎工具
|
# 安裝基礎工具
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
curl \
|
curl \
|
||||||
unzip \
|
unzip \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 安裝 Bun(根據架構選擇版本)
|
# 安裝 Bun(根據架構選擇版本)
|
||||||
RUN ARCH=$(uname -m) && \
|
RUN ARCH=$(uname -m) && \
|
||||||
if [ "$ARCH" = "aarch64" ]; then \
|
if [ "$ARCH" = "aarch64" ]; then \
|
||||||
curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
-o bun-linux-aarch64.zip \
|
-o bun-linux-aarch64.zip \
|
||||||
https://github.com/oven-sh/bun/releases/download/bun-v1.3.6/bun-linux-aarch64.zip; \
|
https://github.com/oven-sh/bun/releases/download/bun-v1.3.6/bun-linux-aarch64.zip; \
|
||||||
else \
|
else \
|
||||||
curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -fsSL --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
-o bun-linux-x64-baseline.zip \
|
-o bun-linux-x64-baseline.zip \
|
||||||
https://github.com/oven-sh/bun/releases/download/bun-v1.3.6/bun-linux-x64-baseline.zip; \
|
https://github.com/oven-sh/bun/releases/download/bun-v1.3.6/bun-linux-x64-baseline.zip; \
|
||||||
fi && \
|
fi && \
|
||||||
unzip -j bun-linux-*.zip -d /usr/local/bin && \
|
unzip -j bun-linux-*.zip -d /usr/local/bin && \
|
||||||
rm bun-linux-*.zip && \
|
rm bun-linux-*.zip && \
|
||||||
chmod +x /usr/local/bin/bun
|
chmod +x /usr/local/bin/bun
|
||||||
|
|
||||||
# ===================================
|
# ===================================
|
||||||
# Stage 2: Install - Node Dependencies
|
# Stage 2: Install - Node Dependencies
|
||||||
|
|
@ -115,154 +115,154 @@ FROM base AS system-tools
|
||||||
|
|
||||||
# 配置 APT
|
# 配置 APT
|
||||||
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \
|
RUN echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::http::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::http::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::https::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::https::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'Acquire::ftp::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'Acquire::ftp::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'APT::Get::Assume-Yes "true";' >> /etc/apt/apt.conf.d/80-retries \
|
&& echo 'APT::Get::Assume-Yes "true";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
&& echo 'DPkg::Lock::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries
|
&& echo 'DPkg::Lock::Timeout "120";' >> /etc/apt/apt.conf.d/80-retries
|
||||||
|
|
||||||
# 階段 4.1:基礎系統工具 + Locale
|
# 階段 4.1:基礎系統工具 + Locale
|
||||||
RUN echo "📦 [Stage 4.1] 安裝基礎系統工具..." && \
|
RUN echo "📦 [Stage 4.1] 安裝基礎系統工具..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
locales \
|
locales \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl \
|
curl \
|
||||||
openssl \
|
openssl \
|
||||||
git \
|
git \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.2:核心轉換工具(輕量)
|
# 階段 4.2:核心轉換工具(輕量)
|
||||||
RUN echo "📦 [Stage 4.2] 安裝核心轉換工具..." && \
|
RUN echo "📦 [Stage 4.2] 安裝核心轉換工具..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
assimp-utils \
|
assimp-utils \
|
||||||
dcraw \
|
dcraw \
|
||||||
dvisvgm \
|
dvisvgm \
|
||||||
ghostscript \
|
ghostscript \
|
||||||
graphicsmagick \
|
graphicsmagick \
|
||||||
mupdf-tools \
|
mupdf-tools \
|
||||||
poppler-utils \
|
poppler-utils \
|
||||||
potrace \
|
potrace \
|
||||||
qpdf \
|
qpdf \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.3:安裝 dasel(從 GitHub 二進位)
|
# 階段 4.3:安裝 dasel(從 GitHub 二進位)
|
||||||
RUN echo "📦 [Stage 4.3] 安裝 dasel..." && \
|
RUN echo "📦 [Stage 4.3] 安裝 dasel..." && \
|
||||||
ARCH=$(uname -m) && \
|
ARCH=$(uname -m) && \
|
||||||
if [ "$ARCH" = "aarch64" ]; then DASEL_ARCH="linux_arm64"; \
|
if [ "$ARCH" = "aarch64" ]; then DASEL_ARCH="linux_arm64"; \
|
||||||
else DASEL_ARCH="linux_amd64"; fi && \
|
else DASEL_ARCH="linux_amd64"; fi && \
|
||||||
curl -sSLf --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -sSLf --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
"https://github.com/TomWright/dasel/releases/download/v2.8.1/dasel_${DASEL_ARCH}" \
|
"https://github.com/TomWright/dasel/releases/download/v2.8.1/dasel_${DASEL_ARCH}" \
|
||||||
-o /usr/local/bin/dasel && \
|
-o /usr/local/bin/dasel && \
|
||||||
chmod +x /usr/local/bin/dasel
|
chmod +x /usr/local/bin/dasel
|
||||||
|
|
||||||
# 階段 4.4:安裝 resvg(僅 x86_64)
|
# 階段 4.4:安裝 resvg(僅 x86_64)
|
||||||
RUN echo "📦 [Stage 4.4] 安裝 resvg..." && \
|
RUN echo "📦 [Stage 4.4] 安裝 resvg..." && \
|
||||||
ARCH=$(uname -m) && \
|
ARCH=$(uname -m) && \
|
||||||
if [ "$ARCH" = "aarch64" ]; then \
|
if [ "$ARCH" = "aarch64" ]; then \
|
||||||
echo "⚠️ resvg 無 ARM64 版本,跳過"; \
|
echo "⚠️ resvg 無 ARM64 版本,跳過"; \
|
||||||
else \
|
else \
|
||||||
curl -sSLf --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -sSLf --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
"https://github.com/linebender/resvg/releases/download/v0.44.0/resvg-linux-x86_64.tar.gz" \
|
"https://github.com/linebender/resvg/releases/download/v0.44.0/resvg-linux-x86_64.tar.gz" \
|
||||||
-o /tmp/resvg.tar.gz && \
|
-o /tmp/resvg.tar.gz && \
|
||||||
tar -xzf /tmp/resvg.tar.gz -C /tmp/ && \
|
tar -xzf /tmp/resvg.tar.gz -C /tmp/ && \
|
||||||
mv /tmp/resvg /usr/local/bin/resvg && \
|
mv /tmp/resvg /usr/local/bin/resvg && \
|
||||||
chmod +x /usr/local/bin/resvg && \
|
chmod +x /usr/local/bin/resvg && \
|
||||||
rm -rf /tmp/resvg.tar.gz; \
|
rm -rf /tmp/resvg.tar.gz; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 階段 4.5:編譯安裝 deark
|
# 階段 4.5:編譯安裝 deark
|
||||||
RUN echo "📦 [Stage 4.5] 編譯 deark..." && \
|
RUN echo "📦 [Stage 4.5] 編譯 deark..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
&& cd /tmp && \
|
&& cd /tmp && \
|
||||||
git clone --depth 1 https://github.com/jsummers/deark.git && \
|
git clone --depth 1 https://github.com/jsummers/deark.git && \
|
||||||
cd deark && make -j$(nproc) && \
|
cd deark && make -j$(nproc) && \
|
||||||
cp deark /usr/local/bin/deark && \
|
cp deark /usr/local/bin/deark && \
|
||||||
chmod +x /usr/local/bin/deark && \
|
chmod +x /usr/local/bin/deark && \
|
||||||
cd / && rm -rf /tmp/deark && \
|
cd / && rm -rf /tmp/deark && \
|
||||||
apt-get remove -y build-essential && \
|
apt-get remove -y build-essential && \
|
||||||
apt-get autoremove -y && \
|
apt-get autoremove -y && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.6:影音處理工具
|
# 階段 4.6:影音處理工具
|
||||||
RUN echo "📦 [Stage 4.6] 安裝 FFmpeg..." && \
|
RUN echo "📦 [Stage 4.6] 安裝 FFmpeg..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
libavcodec-extra \
|
libavcodec-extra \
|
||||||
libva2 \
|
libva2 \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.7:圖像處理工具(含 ImageMagick)
|
# 階段 4.7:圖像處理工具(含 ImageMagick)
|
||||||
# ⚠️ 修復:確保 ImageMagick 已安裝
|
# ⚠️ 修復:確保 ImageMagick 已安裝
|
||||||
RUN echo "📦 [Stage 4.7] 安裝圖像處理工具(含 ImageMagick)..." && \
|
RUN echo "📦 [Stage 4.7] 安裝圖像處理工具(含 ImageMagick)..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
imagemagick \
|
imagemagick \
|
||||||
inkscape \
|
inkscape \
|
||||||
libheif-examples \
|
libheif-examples \
|
||||||
libjxl-tools \
|
libjxl-tools \
|
||||||
libvips-tools \
|
libvips-tools \
|
||||||
xauth \
|
xauth \
|
||||||
xvfb \
|
xvfb \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.8:文件處理工具
|
# 階段 4.8:文件處理工具
|
||||||
RUN echo "📦 [Stage 4.8] 安裝 Calibre + Pandoc..." && \
|
RUN echo "📦 [Stage 4.8] 安裝 Calibre + Pandoc..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
calibre \
|
calibre \
|
||||||
libemail-outlook-message-perl \
|
libemail-outlook-message-perl \
|
||||||
pandoc \
|
pandoc \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.9:LibreOffice
|
# 階段 4.9:LibreOffice
|
||||||
RUN echo "📦 [Stage 4.9] 安裝 LibreOffice(需數分鐘)..." && \
|
RUN echo "📦 [Stage 4.9] 安裝 LibreOffice(需數分鐘)..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
libreoffice \
|
libreoffice \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.10:TexLive 基礎
|
# 階段 4.10:TexLive 基礎
|
||||||
RUN echo "📦 [Stage 4.10] 安裝 TexLive 基礎..." && \
|
RUN echo "📦 [Stage 4.10] 安裝 TexLive 基礎..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
texlive-base \
|
texlive-base \
|
||||||
texlive-latex-base \
|
texlive-latex-base \
|
||||||
texlive-latex-recommended \
|
texlive-latex-recommended \
|
||||||
texlive-fonts-recommended \
|
texlive-fonts-recommended \
|
||||||
texlive-xetex \
|
texlive-xetex \
|
||||||
latexmk \
|
latexmk \
|
||||||
lmodern \
|
lmodern \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.11:TexLive 語言包
|
# 階段 4.11:TexLive 語言包
|
||||||
RUN echo "📦 [Stage 4.11] 安裝 TexLive 語言包..." && \
|
RUN echo "📦 [Stage 4.11] 安裝 TexLive 語言包..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
texlive-lang-cjk \
|
texlive-lang-cjk \
|
||||||
texlive-lang-german \
|
texlive-lang-german \
|
||||||
texlive-lang-french \
|
texlive-lang-french \
|
||||||
texlive-lang-arabic \
|
texlive-lang-arabic \
|
||||||
texlive-lang-other \
|
texlive-lang-other \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.12:OCR 支援
|
# 階段 4.12:OCR 支援
|
||||||
RUN echo "📦 [Stage 4.12] 安裝 Tesseract OCR..." && \
|
RUN echo "📦 [Stage 4.12] 安裝 Tesseract OCR..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
tesseract-ocr \
|
tesseract-ocr \
|
||||||
tesseract-ocr-eng \
|
tesseract-ocr-eng \
|
||||||
tesseract-ocr-chi-tra \
|
tesseract-ocr-chi-tra \
|
||||||
tesseract-ocr-chi-sim \
|
tesseract-ocr-chi-sim \
|
||||||
tesseract-ocr-jpn \
|
tesseract-ocr-jpn \
|
||||||
tesseract-ocr-kor \
|
tesseract-ocr-kor \
|
||||||
tesseract-ocr-deu \
|
tesseract-ocr-deu \
|
||||||
tesseract-ocr-fra \
|
tesseract-ocr-fra \
|
||||||
ocrmypdf \
|
ocrmypdf \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 4.13:字型
|
# 階段 4.13:字型
|
||||||
RUN echo "📦 [Stage 4.13] 安裝系統字型..." && \
|
RUN echo "📦 [Stage 4.13] 安裝系統字型..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
fonts-noto-cjk \
|
fonts-noto-cjk \
|
||||||
fonts-noto-core \
|
fonts-noto-core \
|
||||||
fonts-noto-color-emoji \
|
fonts-noto-color-emoji \
|
||||||
fonts-liberation \
|
fonts-liberation \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# ===================================
|
# ===================================
|
||||||
# Stage 5: Python Base
|
# Stage 5: Python Base
|
||||||
|
|
@ -271,21 +271,21 @@ FROM system-tools AS python-base
|
||||||
|
|
||||||
# 階段 5.1:Python 基礎 + uv
|
# 階段 5.1:Python 基礎 + uv
|
||||||
RUN echo "📦 [Stage 5.1] 安裝 Python 基礎..." && \
|
RUN echo "📦 [Stage 5.1] 安裝 Python 基礎..." && \
|
||||||
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
apt-get update --fix-missing && apt-get install -y --no-install-recommends \
|
||||||
python3 \
|
python3 \
|
||||||
python3-pip \
|
python3-pip \
|
||||||
python3-venv \
|
python3-venv \
|
||||||
python3-numpy \
|
python3-numpy \
|
||||||
python3-tinycss2 \
|
python3-tinycss2 \
|
||||||
python3-opencv \
|
python3-opencv \
|
||||||
python3-img2pdf \
|
python3-img2pdf \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 階段 5.2:安裝 uv(Python 套件管理器)
|
# 階段 5.2:安裝 uv(Python 套件管理器)
|
||||||
# ⚠️ 重要:使用 uv 作為主要安裝方式,確保一致性
|
# ⚠️ 重要:使用 uv 作為主要安裝方式,確保一致性
|
||||||
RUN echo "📦 [Stage 5.2] 安裝 uv..." && \
|
RUN echo "📦 [Stage 5.2] 安裝 uv..." && \
|
||||||
pip3 install --no-cache-dir --break-system-packages uv && \
|
pip3 install --no-cache-dir --break-system-packages uv && \
|
||||||
uv --version
|
uv --version
|
||||||
|
|
||||||
# 設定 PATH
|
# 設定 PATH
|
||||||
ENV PATH="/root/.local/bin:/usr/local/bin:${PATH}"
|
ENV PATH="/root/.local/bin:/usr/local/bin:${PATH}"
|
||||||
|
|
@ -297,26 +297,16 @@ FROM python-base AS python-tools
|
||||||
|
|
||||||
# 階段 6.1:安裝 huggingface_hub + endesive(PDF 簽章)
|
# 階段 6.1:安裝 huggingface_hub + endesive(PDF 簽章)
|
||||||
RUN echo "📦 [Stage 6.1] 安裝 huggingface_hub + endesive..." && \
|
RUN echo "📦 [Stage 6.1] 安裝 huggingface_hub + endesive..." && \
|
||||||
apt-get update && apt-get install -y --no-install-recommends \
|
apt-get update && apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
swig \
|
swig \
|
||||||
libpcsclite-dev \
|
libpcsclite-dev \
|
||||||
&& uv pip install --system --no-cache huggingface_hub endesive && \
|
&& uv pip install --system --break-system-packages --no-cache huggingface_hub endesive && \
|
||||||
apt-get remove -y build-essential swig && \
|
uv pip install --system --break-system-packages --no-cache "markitdown[all]"
|
||||||
apt-get autoremove -y && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# 階段 6.2:安裝 markitdown
|
|
||||||
RUN echo "📦 [Stage 6.2] 安裝 markitdown..." && \
|
|
||||||
uv pip install --system --no-cache "markitdown[all]"
|
|
||||||
|
|
||||||
# 階段 6.3:安裝 pdf2zh
|
|
||||||
RUN echo "📦 [Stage 6.3] 安裝 pdf2zh..." && \
|
RUN echo "📦 [Stage 6.3] 安裝 pdf2zh..." && \
|
||||||
uv pip install --system --no-cache pdf2zh
|
uv pip install --system --break-system-packages --no-cache pdf2zh
|
||||||
|
|
||||||
# 階段 6.4:安裝 babeldoc
|
|
||||||
RUN echo "📦 [Stage 6.4] 安裝 babeldoc..." && \
|
RUN echo "📦 [Stage 6.4] 安裝 babeldoc..." && \
|
||||||
uv pip install --system --no-cache babeldoc || echo "⚠️ babeldoc 安裝可能有警告"
|
uv pip install --system --break-system-packages --no-cache babeldoc || echo "⚠️ babeldoc 安裝可能有警告"
|
||||||
|
|
||||||
# 階段 6.5:安裝 MinerU(⚠️ 關鍵修復)
|
# 階段 6.5:安裝 MinerU(⚠️ 關鍵修復)
|
||||||
# ⚠️ 只使用 system-level 安裝(uv pip install --system)
|
# ⚠️ 只使用 system-level 安裝(uv pip install --system)
|
||||||
|
|
@ -327,7 +317,7 @@ RUN echo "📦 [Stage 6.5] 安裝 MinerU(system-level only)..." && \
|
||||||
echo "⚠️ ARM64:MinerU 不支援,跳過"; \
|
echo "⚠️ ARM64:MinerU 不支援,跳過"; \
|
||||||
else \
|
else \
|
||||||
echo "🔧 使用 uv pip install --system(官方推薦)..." && \
|
echo "🔧 使用 uv pip install --system(官方推薦)..." && \
|
||||||
uv pip install --system --no-cache -U "mineru[all]" && \
|
uv pip install --system --break-system-packages --no-cache -U "mineru[all]" && \
|
||||||
echo "✅ 驗證 MinerU 安裝..." && \
|
echo "✅ 驗證 MinerU 安裝..." && \
|
||||||
which mineru && \
|
which mineru && \
|
||||||
mineru --version || echo "(版本資訊可能不可用)"; \
|
mineru --version || echo "(版本資訊可能不可用)"; \
|
||||||
|
|
@ -345,10 +335,10 @@ ENV HF_HOME="/tmp/hf_download_cache"
|
||||||
|
|
||||||
# 階段 7.1:創建目錄結構
|
# 階段 7.1:創建目錄結構
|
||||||
RUN mkdir -p "${MINERU_MODELS_DIR}" && \
|
RUN mkdir -p "${MINERU_MODELS_DIR}" && \
|
||||||
mkdir -p "${BABELDOC_CACHE_DIR}/models" && \
|
mkdir -p "${BABELDOC_CACHE_DIR}/models" && \
|
||||||
mkdir -p "${BABELDOC_CACHE_DIR}/fonts" && \
|
mkdir -p "${BABELDOC_CACHE_DIR}/fonts" && \
|
||||||
mkdir -p "${BABELDOC_CACHE_DIR}/cmap" && \
|
mkdir -p "${BABELDOC_CACHE_DIR}/cmap" && \
|
||||||
mkdir -p "${BABELDOC_CACHE_DIR}/tiktoken"
|
mkdir -p "${BABELDOC_CACHE_DIR}/tiktoken"
|
||||||
|
|
||||||
# 階段 7.2:下載 MinerU Pipeline 模型
|
# 階段 7.2:下載 MinerU Pipeline 模型
|
||||||
# ⚠️ 關鍵修復:使用顯式下載,存放到固定目錄
|
# ⚠️ 關鍵修復:使用顯式下載,存放到固定目錄
|
||||||
|
|
@ -416,16 +406,16 @@ EOF
|
||||||
# 階段 7.4:BabelDOC warmup + 資源下載
|
# 階段 7.4:BabelDOC warmup + 資源下載
|
||||||
# ⚠️ 關鍵修復:完整 warmup,確保所有資源已下載
|
# ⚠️ 關鍵修復:完整 warmup,確保所有資源已下載
|
||||||
RUN echo "📥 [Stage 7.4] BabelDOC warmup..." && \
|
RUN echo "📥 [Stage 7.4] BabelDOC warmup..." && \
|
||||||
export BABELDOC_CACHE_PATH="${BABELDOC_CACHE_DIR}" && \
|
export BABELDOC_CACHE_PATH="${BABELDOC_CACHE_DIR}" && \
|
||||||
if command -v babeldoc >/dev/null 2>&1; then \
|
if command -v babeldoc >/dev/null 2>&1; then \
|
||||||
echo "執行 babeldoc --warmup..." && \
|
echo "執行 babeldoc --warmup..." && \
|
||||||
babeldoc --warmup 2>&1 || echo "⚠️ warmup 可能有警告" && \
|
babeldoc --warmup 2>&1 || echo "⚠️ warmup 可能有警告" && \
|
||||||
echo "驗證 BabelDOC 資源..." && \
|
echo "驗證 BabelDOC 資源..." && \
|
||||||
ls -la "${BABELDOC_CACHE_DIR}/" && \
|
ls -la "${BABELDOC_CACHE_DIR}/" && \
|
||||||
du -sh "${BABELDOC_CACHE_DIR}/" || true; \
|
du -sh "${BABELDOC_CACHE_DIR}/" || true; \
|
||||||
else \
|
else \
|
||||||
echo "⚠️ babeldoc 不可用,跳過 warmup"; \
|
echo "⚠️ babeldoc 不可用,跳過 warmup"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 階段 7.5:下載 tiktoken 編碼(BabelDOC 依賴)
|
# 階段 7.5:下載 tiktoken 編碼(BabelDOC 依賴)
|
||||||
RUN <<EOF
|
RUN <<EOF
|
||||||
|
|
@ -446,12 +436,12 @@ EOF
|
||||||
|
|
||||||
# 階段 7.6:清理下載 cache(保留實際模型)
|
# 階段 7.6:清理下載 cache(保留實際模型)
|
||||||
RUN echo "🧹 [Stage 7.6] 清理下載 cache..." && \
|
RUN echo "🧹 [Stage 7.6] 清理下載 cache..." && \
|
||||||
rm -rf /tmp/hf_download_cache && \
|
rm -rf /tmp/hf_download_cache && \
|
||||||
rm -rf /root/.cache/huggingface && \
|
rm -rf /root/.cache/huggingface && \
|
||||||
rm -rf /root/.cache/pip && \
|
rm -rf /root/.cache/pip && \
|
||||||
rm -rf /root/.cache/uv && \
|
rm -rf /root/.cache/uv && \
|
||||||
find /usr -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true && \
|
find /usr -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true && \
|
||||||
echo "✅ Cache 清理完成"
|
echo "✅ Cache 清理完成"
|
||||||
|
|
||||||
# ===================================
|
# ===================================
|
||||||
# Stage 8: Final Image
|
# Stage 8: Final Image
|
||||||
|
|
@ -481,16 +471,16 @@ COPY models/ /root/.cache/babeldoc/models/
|
||||||
|
|
||||||
# 複製字型到 BabelDOC 目錄
|
# 複製字型到 BabelDOC 目錄
|
||||||
RUN mkdir -p /root/.cache/babeldoc/fonts && \
|
RUN mkdir -p /root/.cache/babeldoc/fonts && \
|
||||||
cp /usr/share/fonts/truetype/custom/GoNotoKurrent-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
cp /usr/share/fonts/truetype/custom/GoNotoKurrent-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
||||||
cp /usr/share/fonts/truetype/custom/SourceHanSerifCN-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
cp /usr/share/fonts/truetype/custom/SourceHanSerifCN-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
||||||
cp /usr/share/fonts/truetype/custom/SourceHanSerifTW-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
cp /usr/share/fonts/truetype/custom/SourceHanSerifTW-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
||||||
cp /usr/share/fonts/truetype/custom/SourceHanSerifJP-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
cp /usr/share/fonts/truetype/custom/SourceHanSerifJP-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true && \
|
||||||
cp /usr/share/fonts/truetype/custom/SourceHanSerifKR-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true
|
cp /usr/share/fonts/truetype/custom/SourceHanSerifKR-Regular.ttf /root/.cache/babeldoc/fonts/ 2>/dev/null || true
|
||||||
|
|
||||||
# 同步 BabelDOC cache 從固定目錄
|
# 同步 BabelDOC cache 從固定目錄
|
||||||
RUN if [ -d /opt/babeldoc/cache ]; then \
|
RUN if [ -d /opt/babeldoc/cache ]; then \
|
||||||
cp -r /opt/babeldoc/cache/* /root/.cache/babeldoc/ 2>/dev/null || true; \
|
cp -r /opt/babeldoc/cache/* /root/.cache/babeldoc/ 2>/dev/null || true; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 更新字型 cache
|
# 更新字型 cache
|
||||||
RUN fc-cache -fv
|
RUN fc-cache -fv
|
||||||
|
|
@ -499,56 +489,56 @@ RUN fc-cache -fv
|
||||||
# PDF 簽章憑證
|
# PDF 簽章憑證
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN mkdir -p /app/certs && \
|
RUN mkdir -p /app/certs && \
|
||||||
openssl req -x509 -newkey rsa:2048 \
|
openssl req -x509 -newkey rsa:2048 \
|
||||||
-keyout /tmp/key.pem -out /tmp/cert.pem \
|
-keyout /tmp/key.pem -out /tmp/cert.pem \
|
||||||
-days 3650 -nodes \
|
-days 3650 -nodes \
|
||||||
-subj "/CN=PDF Packager Default/O=ConvertX-CN/C=TW" && \
|
-subj "/CN=PDF Packager Default/O=ConvertX-CN/C=TW" && \
|
||||||
openssl pkcs12 -export \
|
openssl pkcs12 -export \
|
||||||
-inkey /tmp/key.pem -in /tmp/cert.pem \
|
-inkey /tmp/key.pem -in /tmp/cert.pem \
|
||||||
-out /app/certs/default.p12 \
|
-out /app/certs/default.p12 \
|
||||||
-passout pass: && \
|
-passout pass: && \
|
||||||
rm -f /tmp/key.pem /tmp/cert.pem && \
|
rm -f /tmp/key.pem /tmp/cert.pem && \
|
||||||
chmod 644 /app/certs/default.p12
|
chmod 644 /app/certs/default.p12
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# VTracer
|
# VTracer
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN ARCH=$(uname -m) && \
|
RUN ARCH=$(uname -m) && \
|
||||||
if [ "$ARCH" = "aarch64" ]; then \
|
if [ "$ARCH" = "aarch64" ]; then \
|
||||||
VTRACER_ASSET="vtracer-aarch64-unknown-linux-musl.tar.gz"; \
|
VTRACER_ASSET="vtracer-aarch64-unknown-linux-musl.tar.gz"; \
|
||||||
else \
|
else \
|
||||||
VTRACER_ASSET="vtracer-x86_64-unknown-linux-musl.tar.gz"; \
|
VTRACER_ASSET="vtracer-x86_64-unknown-linux-musl.tar.gz"; \
|
||||||
fi && \
|
fi && \
|
||||||
curl -L --retry 3 --retry-delay 5 --retry-all-errors \
|
curl -L --retry 3 --retry-delay 5 --retry-all-errors \
|
||||||
-o /tmp/vtracer.tar.gz \
|
-o /tmp/vtracer.tar.gz \
|
||||||
"https://github.com/visioncortex/vtracer/releases/download/0.6.4/${VTRACER_ASSET}" && \
|
"https://github.com/visioncortex/vtracer/releases/download/0.6.4/${VTRACER_ASSET}" && \
|
||||||
tar -xzf /tmp/vtracer.tar.gz -C /tmp/ && \
|
tar -xzf /tmp/vtracer.tar.gz -C /tmp/ && \
|
||||||
mv /tmp/vtracer /usr/local/bin/vtracer && \
|
mv /tmp/vtracer /usr/local/bin/vtracer && \
|
||||||
chmod +x /usr/local/bin/vtracer && \
|
chmod +x /usr/local/bin/vtracer && \
|
||||||
rm /tmp/vtracer.tar.gz
|
rm /tmp/vtracer.tar.gz
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# Locale 設定
|
# Locale 設定
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
|
RUN sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# zh_TW.UTF-8 UTF-8/zh_TW.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# zh_TW.UTF-8 UTF-8/zh_TW.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen && \
|
sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen && \
|
||||||
locale-gen
|
locale-gen
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# 最終清理
|
# 最終清理
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN rm -rf /usr/share/doc/texlive* \
|
RUN rm -rf /usr/share/doc/texlive* \
|
||||||
&& rm -rf /usr/share/texlive/texmf-dist/doc \
|
&& rm -rf /usr/share/texlive/texmf-dist/doc \
|
||||||
&& rm -rf /usr/share/doc/* \
|
&& rm -rf /usr/share/doc/* \
|
||||||
&& rm -rf /usr/share/man/* \
|
&& rm -rf /usr/share/man/* \
|
||||||
&& rm -rf /usr/share/info/* \
|
&& rm -rf /usr/share/info/* \
|
||||||
&& rm -rf /tmp/* \
|
&& rm -rf /tmp/* \
|
||||||
&& rm -rf /var/tmp/*
|
&& rm -rf /var/tmp/*
|
||||||
|
|
||||||
# 複製驗證腳本
|
# 複製驗證腳本
|
||||||
COPY scripts/verify-models.sh /app/scripts/verify-models.sh
|
COPY scripts/verify-models.sh /app/scripts/verify-models.sh
|
||||||
|
|
@ -563,77 +553,77 @@ RUN mkdir -p data
|
||||||
# ⚠️ 此步驟模擬斷網環境,驗證所有工具可離線執行
|
# ⚠️ 此步驟模擬斷網環境,驗證所有工具可離線執行
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
RUN echo "======================================" && \
|
RUN echo "======================================" && \
|
||||||
echo "🔒 Runtime 離線驗證" && \
|
echo "🔒 Runtime 離線驗證" && \
|
||||||
echo "======================================" && \
|
echo "======================================" && \
|
||||||
ARCH=$(uname -m) && \
|
ARCH=$(uname -m) && \
|
||||||
VALIDATION_PASSED=true && \
|
VALIDATION_PASSED=true && \
|
||||||
\
|
\
|
||||||
# 驗證 MinerU
|
# 驗證 MinerU
|
||||||
echo "🔍 驗證 MinerU..." && \
|
echo "🔍 驗證 MinerU..." && \
|
||||||
if [ "$ARCH" != "aarch64" ]; then \
|
if [ "$ARCH" != "aarch64" ]; then \
|
||||||
if command -v mineru >/dev/null 2>&1; then \
|
if command -v mineru >/dev/null 2>&1; then \
|
||||||
echo " ✅ mineru 可執行: $(which mineru)"; \
|
echo " ✅ mineru 可執行: $(which mineru)"; \
|
||||||
else \
|
else \
|
||||||
echo " ❌ mineru 不可執行" && VALIDATION_PASSED=false; \
|
echo " ❌ mineru 不可執行" && VALIDATION_PASSED=false; \
|
||||||
fi && \
|
fi && \
|
||||||
if [ -d "/opt/mineru/models/PDF-Extract-Kit-1.0" ]; then \
|
if [ -d "/opt/mineru/models/PDF-Extract-Kit-1.0" ]; then \
|
||||||
echo " ✅ MinerU 模型目錄存在"; \
|
echo " ✅ MinerU 模型目錄存在"; \
|
||||||
else \
|
else \
|
||||||
echo " ❌ MinerU 模型目錄不存在" && VALIDATION_PASSED=false; \
|
echo " ❌ MinerU 模型目錄不存在" && VALIDATION_PASSED=false; \
|
||||||
fi && \
|
fi && \
|
||||||
if [ -f "/root/mineru.json" ]; then \
|
if [ -f "/root/mineru.json" ]; then \
|
||||||
echo " ✅ mineru.json 存在"; \
|
echo " ✅ mineru.json 存在"; \
|
||||||
else \
|
else \
|
||||||
echo " ❌ mineru.json 不存在" && VALIDATION_PASSED=false; \
|
echo " ❌ mineru.json 不存在" && VALIDATION_PASSED=false; \
|
||||||
fi; \
|
fi; \
|
||||||
else \
|
else \
|
||||||
echo " ⚠️ ARM64:跳過 MinerU 驗證"; \
|
echo " ⚠️ ARM64:跳過 MinerU 驗證"; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證 BabelDOC
|
# 驗證 BabelDOC
|
||||||
echo "🔍 驗證 BabelDOC..." && \
|
echo "🔍 驗證 BabelDOC..." && \
|
||||||
if command -v babeldoc >/dev/null 2>&1; then \
|
if command -v babeldoc >/dev/null 2>&1; then \
|
||||||
babeldoc --help >/dev/null 2>&1 && echo " ✅ babeldoc --help 成功" || echo " ⚠️ babeldoc --help 有警告"; \
|
babeldoc --help >/dev/null 2>&1 && echo " ✅ babeldoc --help 成功" || echo " ⚠️ babeldoc --help 有警告"; \
|
||||||
else \
|
else \
|
||||||
echo " ⚠️ babeldoc 不可用"; \
|
echo " ⚠️ babeldoc 不可用"; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證 pdf2zh
|
# 驗證 pdf2zh
|
||||||
echo "🔍 驗證 pdf2zh..." && \
|
echo "🔍 驗證 pdf2zh..." && \
|
||||||
if command -v pdf2zh >/dev/null 2>&1; then \
|
if command -v pdf2zh >/dev/null 2>&1; then \
|
||||||
pdf2zh --help >/dev/null 2>&1 && echo " ✅ pdf2zh --help 成功" || echo " ⚠️ pdf2zh --help 有警告"; \
|
pdf2zh --help >/dev/null 2>&1 && echo " ✅ pdf2zh --help 成功" || echo " ⚠️ pdf2zh --help 有警告"; \
|
||||||
else \
|
else \
|
||||||
echo " ⚠️ pdf2zh 不可用"; \
|
echo " ⚠️ pdf2zh 不可用"; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證 ImageMagick
|
# 驗證 ImageMagick
|
||||||
echo "🔍 驗證 ImageMagick..." && \
|
echo "🔍 驗證 ImageMagick..." && \
|
||||||
if command -v convert >/dev/null 2>&1; then \
|
if command -v convert >/dev/null 2>&1; then \
|
||||||
echo " ✅ ImageMagick 已安裝: $(convert --version | head -1)"; \
|
echo " ✅ ImageMagick 已安裝: $(convert --version | head -1)"; \
|
||||||
else \
|
else \
|
||||||
echo " ❌ ImageMagick 未安裝" && VALIDATION_PASSED=false; \
|
echo " ❌ ImageMagick 未安裝" && VALIDATION_PASSED=false; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證模型檔案
|
# 驗證模型檔案
|
||||||
echo "🔍 驗證 ONNX 模型..." && \
|
echo "🔍 驗證 ONNX 模型..." && \
|
||||||
if [ -f "/root/.cache/babeldoc/models/doclayout_yolo_docstructbench_imgsz1024.onnx" ]; then \
|
if [ -f "/root/.cache/babeldoc/models/doclayout_yolo_docstructbench_imgsz1024.onnx" ]; then \
|
||||||
echo " ✅ DocLayout-YOLO ONNX 存在"; \
|
echo " ✅ DocLayout-YOLO ONNX 存在"; \
|
||||||
else \
|
else \
|
||||||
echo " ⚠️ DocLayout-YOLO ONNX 不存在(將使用 COPY 複製)"; \
|
echo " ⚠️ DocLayout-YOLO ONNX 不存在(將使用 COPY 複製)"; \
|
||||||
fi && \
|
fi && \
|
||||||
\
|
\
|
||||||
# 驗證字型
|
# 驗證字型
|
||||||
echo "🔍 驗證字型..." && \
|
echo "🔍 驗證字型..." && \
|
||||||
FONTS_COUNT=$(ls /usr/share/fonts/truetype/custom/*.ttf 2>/dev/null | wc -l) && \
|
FONTS_COUNT=$(ls /usr/share/fonts/truetype/custom/*.ttf 2>/dev/null | wc -l) && \
|
||||||
echo " ✅ 自訂字型數量: ${FONTS_COUNT}" && \
|
echo " ✅ 自訂字型數量: ${FONTS_COUNT}" && \
|
||||||
\
|
\
|
||||||
echo "======================================" && \
|
echo "======================================" && \
|
||||||
if [ "$VALIDATION_PASSED" = "true" ]; then \
|
if [ "$VALIDATION_PASSED" = "true" ]; then \
|
||||||
echo "✅ 離線驗證通過!"; \
|
echo "✅ 離線驗證通過!"; \
|
||||||
else \
|
else \
|
||||||
echo "❌ 離線驗證失敗!" && exit 1; \
|
echo "❌ 離線驗證失敗!" && exit 1; \
|
||||||
fi && \
|
fi && \
|
||||||
echo "======================================"
|
echo "======================================"
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# 🔐 Runtime 環境變數(強制離線模式)
|
# 🔐 Runtime 環境變數(強制離線模式)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue