From 8623b71d5694c089387535086f2cf4c695aa590e Mon Sep 17 00:00:00 2001 From: HHY Date: Thu, 24 Sep 2026 20:45:59 -0700 Subject: [PATCH] =?UTF-8?q?chore:=20Docker=20=E9=83=A8=E7=BD=B2=E2=80=94?= =?UTF-8?q?=E2=80=94=E5=A4=9A=E9=98=B6=E6=AE=B5=20Dockerfile=20+=20compose?= =?UTF-8?q?=20+=20=E6=95=B0=E6=8D=AE=E5=8D=B7=E6=8C=81=E4=B9=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 前端 node:22-alpine 构建阶段(npm ci + vite build) - 运行时 python:3.14-slim + uv --frozen 冻结安装(依赖层独立缓存) - entrypoint: 数据卷为空时自动建库并导入 254 套样板 - SQLite 落数据卷 /app/db(HMC_DATABASE_URL 可切 MySQL); healthcheck /api/health - .dockerignore 排除构建无关资产; .gitattributes 强制 sh LF --- .dockerignore | 32 ++++++++++++++++++++++++++++++ .gitattributes | 2 ++ Dockerfile | 46 ++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 25 ++++++++++++++++++++++++ docker/entrypoint.sh | 15 +++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitattributes create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 docker/entrypoint.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a124525 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,32 @@ +# 版本控制 +.git +.gitignore + +# Python 运行产物 +.venv +**/__pycache__ +*.py[oc] +huamenchuang.db + +# 前端构建产物与依赖(Docker 内重建) +frontend/node_modules +frontend/dist +frontend/scripts + +# 本地开发/验证资产(非运行必需) +/doc +/shots +/scripts +.claude +*.log + +# 抓取残留与单文件脚本 +data/dxf-study +data/full-site +data/api-endpoint-inventory.txt +data/fetch-images.py + +# 杂项 +image.png +3D窗型.png +.env diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fddb165 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# shell 脚本强制 LF(容器内 sh 对 CRLF 敏感) +*.sh text eol=lf diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cff567e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ +# syntax=docker/dockerfile:1 +# 华门窗云平台镜像(多阶段:前端构建 → Python 运行时) +# 云端构建: git 仓库直接构建即可; 本地: docker build -t menchuang . + +# ---------- 阶段 1: 前端构建 (Vue3 + Vite → dist) ---------- +FROM node:22-alpine AS web +WORKDIR /web +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci +COPY frontend/ ./ +RUN npm run build + +# ---------- 阶段 2: 后端运行时 (Python 3.14 + uv) ---------- +FROM python:3.14-slim-bookworm + +# uv 包管理器(按 uv.lock 冻结安装) +COPY --from=ghcr.io/astral-sh/uv:0.9 /uv /usr/local/bin/uv +ENV UV_COMPILE_BYTECODE=1 \ + UV_LINK_MODE=copy \ + TZ=Asia/Shanghai + +WORKDIR /app + +# 依赖层(独立缓存: 代码变更不触发依赖重装) +COPY pyproject.toml uv.lock README.md ./ +RUN uv sync --frozen --no-dev --no-install-project + +# 应用代码 + 样板数据资产 + 前端产物 +COPY src/ ./src/ +COPY data/ ./data/ +COPY --from=web /web/dist/ ./frontend/dist/ +RUN uv sync --frozen --no-dev + +# 运行配置: SQLite 落在数据卷 /app/db (compose 挂载持久化) +ENV HMC_DATABASE_URL="sqlite+aiosqlite:////app/db/huamenchuang.db" +VOLUME ["/app/db"] + +COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +EXPOSE 8000 +HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \ + CMD python -c "import urllib.request;urllib.request.urlopen('http://127.0.0.1:8000/api/health',timeout=4)" || exit 1 + +ENTRYPOINT ["entrypoint.sh"] +CMD ["/app/.venv/bin/uvicorn", "huamenchuang.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..11a6bcf --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,25 @@ +services: + web: + build: . + image: menchuang:latest + container_name: menchuang + restart: unless-stopped + ports: + - "8000:8000" + environment: + # SQLite 落在数据卷; 如需 MySQL: mysql+aiomysql://user:pwd@host:3306/hmc + HMC_DATABASE_URL: sqlite+aiosqlite:////app/db/huamenchuang.db + # 生产务必换成随机长密钥(登录态签名) + HMC_JWT_SECRET: ${HMC_JWT_SECRET:-change-me-in-production-please-set-a-long-random-secret-key} + TZ: Asia/Shanghai + volumes: + - db_data:/app/db + healthcheck: + test: ["CMD", "python", "-c", "import urllib.request;urllib.request.urlopen('http://127.0.0.1:8000/api/health',timeout=4)"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 30s + +volumes: + db_data: diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000..f19d354 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# 容器入口: 数据卷为空时自动建库并导入 254 套样板, 之后交给 CMD 启动服务 +set -e + +DB_FILE="/app/db/huamenchuang.db" +export PATH="/app/.venv/bin:$PATH" + +mkdir -p /app/db +if [ ! -f "$DB_FILE" ]; then + echo "[entrypoint] 首次启动: 初始化数据库并导入样板数据..." + python -m huamenchuang.scripts.seed + echo "[entrypoint] 种子完成: 管理员 13800000000/123456" +fi + +exec "$@"