website_content / Dockerfile
Administrator
Claude Opus 5
fix(infra): chặn 502 từ gốc — uvicorn đóng kết nối rảnh quá sớm
a04fadb
Raw History Blame Contribute Delete
4.91 kB
FROM node:20-bookworm AS frontend
WORKDIR /frontend
COPY ./frontend/package*.json ./
RUN npm ci
COPY ./frontend/index.html ./frontend/vite.config.js ./
COPY ./frontend/public ./public
COPY ./frontend/src ./src
RUN npm run build
# ── PO Token provider (bgutil) ──────────────────────────────────────────────
# YouTube chặn IP máy chủ ("bot check"). Provider này sinh Proof-of-Origin Token
# để yt-dlp qua được — TỰ ĐỘNG, không cần cookies/tài khoản. Build sẵn ở đây.
FROM node:20-bookworm AS potprovider
WORKDIR /pot
RUN git clone --depth 1 --single-branch --branch 1.3.1 \
https://github.com/Brainicism/bgutil-ytdlp-pot-provider.git . \
&& cd server && npm ci && npx tsc
FROM python:3.11-slim
# libstdc++6: cần để chạy binary node copy từ tầng trên.
# fontconfig: libass cần để nạp font ổn định (hết lỗi "Cannot load default config
# file"); font phụ đề nhúng kèm ở backend/app/assets/fonts (nạp qua fontsdir).
RUN apt-get update && apt-get install -y ffmpeg libstdc++6 fontconfig && rm -rf /var/lib/apt/lists/*
# Node runtime + server provider (chạy nền cùng uvicorn, xem CMD)
COPY --from=potprovider /usr/local/bin/node /usr/local/bin/node
COPY --from=potprovider /pot/server /opt/bgutil/server
ENV NUMBA_CACHE_DIR=/tmp/numba_cache
ENV XDG_CACHE_HOME=/tmp/hf_cache
ENV HF_HOME=/tmp/hf_cache
WORKDIR /app
# Cài torch/torchaudio bản CPU-ONLY (~200MB) TRƯỚC — mặc định `pip install torch`
# (do demucs kéo vào) tải bản CUDA ~2.5GB vô dụng trên CPU Space, làm build cực chậm.
# Cài CPU trước -> demucs thấy torch đã có, không tải bản CUDA nữa.
RUN pip install --no-cache-dir torch torchaudio --index-url https://download.pytorch.org/whl/cpu
COPY backend/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# ── OmniVoice (TTS clone giọng cho en/fil) ─────────────────────────────────
# Cài TÁCH RIÊNG và --no-deps: metadata của `omnivoice` khai cả `gradio`,
# `webdataset`, `tensorboardx` — chỉ dùng cho demo UI + huấn luyện, đường suy
# luận KHÔNG import tới. Cài trọn bộ thì gradio kéo theo fastapi/starlette/
# uvicorn/pydantic bản khác ĐÈ LÊN web stack đang chạy (đã thử dựng cây phụ
# thuộc: gradio 6 kéo starlette 1.x, fastapi 0.141 — nhảy cả major).
# Các gói dưới đây là đúng những thứ omnivoice import lúc suy luận.
RUN pip install --no-cache-dir "transformers>=5.3" accelerate soundfile pydub librosa && pip install --no-cache-dir --no-deps omnivoice
# CHỐT AN TOÀN: gãy web stack thì HỎNG BUILD ở đây, đừng để chết lúc chạy.
RUN python -c "import fastapi, pydantic, cv2, numpy, gradio_client, transformers, omnivoice; print('deps ok:', fastapi.__version__, pydantic.VERSION, numpy.__version__, transformers.__version__)"
# Trọng số (~3.3GB) KHÔNG nhúng vào ảnh — tải lúc khởi động, chạy nền trong
# warm_voice_previews (mạng nội bộ HF rất nhanh), nên job đầu tiên khỏi phải chờ.
COPY ./backend ./backend
# Cài font phụ đề nhúng vào hệ thống + cập nhật cache fontconfig -> libass tìm
# được theo family name ("Be Vietnam Pro"...) trên server Linux (không có font
# Microsoft). Đây là bộ font mà trình duyệt cũng nạp qua /fonts -> render KHỚP
# xem trước. (burn() còn dùng thêm fontsdir cho môi trường dev.)
RUN mkdir -p /usr/share/fonts/truetype/tnt \
&& cp ./backend/app/assets/fonts/*.ttf /usr/share/fonts/truetype/tnt/ \
&& fc-cache -f /usr/share/fonts/truetype/tnt
COPY --from=frontend /frontend/dist ./frontend/dist
ENV PORT=7860
EXPOSE 7860
# Chạy PO Token provider ở NỀN (cổng mặc định 4416) rồi mới chạy web.
# Provider lỗi/không chạy -> uvicorn vẫn lên bình thường (chỉ mất PO Token).
#
# --timeout-keep-alive 120: KHÔNG phải tinh chỉnh vặt. Router của HF giữ sẵn một
# nắm kết nối tới app rồi dùng lại. Mặc định uvicorn đóng kết nối rảnh sau 5
# GIÂY, nên router thường xuyên gửi request vào một kết nối vừa bị đóng -> nó
# trả 502 kèm trang HTML của huggingface.co, request chưa hề tới app. Đo thực tế
# trên Space: 5/20 lời gọi API dính 502 kiểu này, và chính nó đẻ ra lỗi
# "Unexpected token '<'" mà người dùng gặp. Để ngưỡng cao hơn hẳn thời gian rảnh
# của router thì bên đóng kết nối là router, đóng đàng hoàng từ phía nó.
CMD ["sh", "-c", "node /opt/bgutil/server/build/main.js --port 4416 >/tmp/potprovider.log 2>&1 & exec uvicorn backend.app.main:app --host 0.0.0.0 --port 7860 --timeout-keep-alive 120"]