Dockerize

This commit is contained in:
RYDE-WORK 2026-01-26 11:08:57 +08:00
parent 68119df128
commit 3cce4c9373
6 changed files with 266 additions and 1 deletions

75
.dockerignore Normal file
View File

@ -0,0 +1,75 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
*.egg-info/
.eggs/
dist/
build/
*.egg
# Virtual environments
.venv/
venv/
ENV/
env/
.pixi/
# IDE
.idea/
.vscode/
*.swp
*.swo
.cursor/
# Git
.git/
.gitignore
# Data (不需要打包到镜像)
data/
!data/.gitkeep
# Notebooks
notebooks/
*.ipynb
# Documentation
docs/
# Reports
reports/
# References
references/
# Scripts (训练脚本不需要)
scripts/
# Lock files
pixi.lock
# Tests
tests/
.pytest_cache/
# Logs
*.log
logs/
# Temporary files
*.tmp
*.temp
.DS_Store
# Models (will be mounted as volume or copied explicitly)
# Note: models/final/ is copied in Dockerfile
models/finetune_cv/
models/pretrain_cv/
models/mpnn/
models/*.pt
models/*.json
!models/final/

63
Dockerfile Normal file
View File

@ -0,0 +1,63 @@
# LNP-ML Docker Image
# 多阶段构建,支持 API 和 Streamlit 两种服务
FROM python:3.8-slim AS base
# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libxrender1 \
libxext6 \
curl \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖文件
COPY requirements.txt .
# 安装 Python 依赖
RUN pip install --upgrade pip && \
pip install -r requirements.txt
# 复制项目代码
COPY pyproject.toml .
COPY README.md .
COPY LICENSE .
COPY lnp_ml/ ./lnp_ml/
COPY app/ ./app/
# 安装项目包
RUN pip install -e .
# 复制模型文件
COPY models/final/ ./models/final/
# ============ API 服务 ============
FROM base AS api
EXPOSE 8000
ENV MODEL_PATH=/app/models/final/model.pt
CMD ["uvicorn", "app.api:app", "--host", "0.0.0.0", "--port", "8000"]
# ============ Streamlit 服务 ============
FROM base AS streamlit
EXPOSE 8501
# Streamlit 配置
ENV STREAMLIT_SERVER_PORT=8501 \
STREAMLIT_SERVER_ADDRESS=0.0.0.0 \
STREAMLIT_SERVER_HEADLESS=true \
STREAMLIT_BROWSER_GATHER_USAGE_STATS=false
CMD ["streamlit", "run", "app/app.py"]

View File

@ -200,6 +200,48 @@ serve:
@echo "然后访问: http://localhost:8501"
#################################################################################
# DOCKER COMMANDS #
#################################################################################
## Build Docker images
.PHONY: docker-build
docker-build:
docker compose build
## Start all services with Docker Compose
.PHONY: docker-up
docker-up:
docker compose up -d
## Stop all Docker services
.PHONY: docker-down
docker-down:
docker compose down
## View Docker logs
.PHONY: docker-logs
docker-logs:
docker compose logs -f
## Build and start all services
.PHONY: docker-serve
docker-serve: docker-build docker-up
@echo ""
@echo "🚀 服务已启动!"
@echo " - API: http://localhost:8000"
@echo " - Web 应用: http://localhost:8501"
@echo ""
@echo "查看日志: make docker-logs"
@echo "停止服务: make docker-down"
## Clean Docker resources (images, volumes, etc.)
.PHONY: docker-clean
docker-clean:
docker compose down -v --rmi local
docker system prune -f
#################################################################################
# Self Documenting Commands #
#################################################################################

View File

@ -3,9 +3,13 @@ Streamlit 配方优化交互界面
启动应用:
streamlit run app/app.py
Docker 环境变量:
API_URL: API 服务地址 (默认: http://localhost:8000)
"""
import io
import os
from datetime import datetime
import httpx
@ -14,7 +18,8 @@ import streamlit as st
# ============ 配置 ============
API_URL = "http://localhost:8000"
# 从环境变量读取 API 地址,支持 Docker 环境
API_URL = os.environ.get("API_URL", "http://localhost:8000")
AVAILABLE_ORGANS = [
"liver",

60
docker-compose.yml Normal file
View File

@ -0,0 +1,60 @@
services:
# FastAPI 后端服务
api:
build:
context: .
dockerfile: Dockerfile
target: api
container_name: lnp-api
# ports:
# - "8000:8000"
environment:
- MODEL_PATH=/app/models/final/model.pt
- DEVICE=cpu
volumes:
# 挂载模型目录以便更新模型
- ./models/final:/app/models/final:ro
- ./models/mpnn:/app/models/mpnn:ro
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# 如果有 NVIDIA GPU取消下面的注释
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: 1
# capabilities: [gpu]
# Streamlit 前端服务
streamlit:
build:
context: .
dockerfile: Dockerfile
target: streamlit
container_name: lnp-streamlit
ports:
- "8501:8501"
environment:
# 连接到 API 服务(使用 Docker 内部网络)
- API_URL=http://api:8000
depends_on:
api:
condition: service_started
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8501/_stcore/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
networks:
default:
name: lnp-network

20
requirements.txt Normal file
View File

@ -0,0 +1,20 @@
# 严格遵循 pixi.toml 的依赖版本
# 注意: lnp_ml 本地包在 Dockerfile 中单独安装
# conda dependencies (in pixi.toml [dependencies])
loguru
tqdm
typer
# pypi dependencies (in pixi.toml [pypi-dependencies])
chemprop==1.7.0
setuptools
pandas>=2.0.3,<3
openpyxl>=3.1.5,<4
python-dotenv>=1.0.1,<2
pyarrow>=17.0.0,<18
fastparquet>=2024.2.0,<2025
fastapi>=0.124.4,<0.125
streamlit>=1.40.1,<2
httpx>=0.28.1,<0.29
uvicorn>=0.33.0,<0.34