fix: Docker deployment optimization
- Replace postgres:15-alpine with pgvector/pgvector:pg15 (built-in vector extension) - Remove init-db.sh (pgvector image includes extension, SQL init script instead) - Add multi-stage Dockerfile for backend (development/runtime targets) - Add development stage to frontend Dockerfile - Update .env.example with correct passwords and Docker-internal URLs - Add POSTGRES_PASSWORD/REDIS_PASSWORD to .env for Docker Compose - Use named volume for frontend node_modules - Add backend healthcheck to docker-compose.yml
This commit is contained in:
parent
33aecc0cb1
commit
218ece564d
21
.env.example
21
.env.example
|
|
@ -4,14 +4,26 @@
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# 数据库(PostgreSQL)
|
# 数据库密码(Docker Compose 引用此变量)
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
DATABASE_URL=postgresql+asyncpg://postgres:postgres123@db:5432/geo_platform
|
POSTGRES_PASSWORD=geo_pg_dev_2026
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Redis 密码(Docker Compose 引用此变量)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
REDIS_PASSWORD=geo_redis_dev_2026
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# 数据库(PostgreSQL + pgvector)
|
||||||
|
# Docker 内部使用 db:5432,本地直连使用 localhost:5433
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
DATABASE_URL=postgresql+asyncpg://postgres:geo_pg_dev_2026@db:5432/geo_platform
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Redis(缓存 / 任务队列)
|
# Redis(缓存 / 任务队列)
|
||||||
|
# Docker 内部使用 redis:6379,本地直连使用 localhost:6380
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
REDIS_URL=redis://redis:6379/0
|
REDIS_URL=redis://:geo_redis_dev_2026@redis:6379/0
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# JWT 认证密钥
|
# JWT 认证密钥
|
||||||
|
|
@ -80,11 +92,10 @@ BAIDU_QIANFAN_API_KEY=your-baidu-qianfan-api-key-here
|
||||||
BAIDU_QIANFAN_SECRET_KEY=your-baidu-qianfan-secret-key-here
|
BAIDU_QIANFAN_SECRET_KEY=your-baidu-qianfan-secret-key-here
|
||||||
|
|
||||||
# 豆包(字节跳动)
|
# 豆包(字节跳动)
|
||||||
DOUBAO_API_KEY=your-doubao-api-key-here
|
DOUBAO_API_KEY=your-doubbo-api-key-here
|
||||||
DOUBAO_ENDPOINT_ID=your-doubao-endpoint-id-here
|
DOUBAO_ENDPOINT_ID=your-doubao-endpoint-id-here
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# API 调用频率限制
|
# API 调用频率限制
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# 每分钟最大请求数(防止触发平台限速)
|
|
||||||
API_RATE_LIMIT_RPM=10
|
API_RATE_LIMIT_RPM=10
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,26 @@
|
||||||
FROM python:3.11-slim
|
FROM python:3.11-slim AS base
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# 安装系统依赖(Playwright需要)
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
curl \
|
curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
FROM base AS development
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
||||||
|
|
||||||
|
FROM base AS runtime
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
wget \
|
wget \
|
||||||
gnupg \
|
gnupg \
|
||||||
libglib2.0-0 \
|
libglib2.0-0 \
|
||||||
|
|
@ -24,20 +40,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
libasound2 \
|
libasound2 \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 复制并安装Python依赖
|
|
||||||
COPY requirements.txt .
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# 安装Playwright浏览器
|
|
||||||
RUN playwright install chromium
|
RUN playwright install chromium
|
||||||
RUN playwright install-deps chromium
|
RUN playwright install-deps chromium
|
||||||
|
|
||||||
# 复制应用代码
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
# 健康检查
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
|
||||||
CMD curl -f http://localhost:8000/health || exit 1
|
CMD curl -f http://localhost:8000/health || exit 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Installing pgvector extension for PostgreSQL ==="
|
|
||||||
|
|
||||||
echo "[1/5] Installing build dependencies..."
|
|
||||||
apk add --no-cache build-base git clang llvm-dev postgresql-dev
|
|
||||||
|
|
||||||
echo "[2/5] Cloning pgvector v0.5.1..."
|
|
||||||
cd /tmp
|
|
||||||
rm -rf pgvector
|
|
||||||
git clone --branch v0.5.1 --depth 1 https://github.com/pgvector/pgvector.git
|
|
||||||
|
|
||||||
echo "[3/5] Compiling and installing pgvector..."
|
|
||||||
cd /tmp/pgvector
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
|
|
||||||
echo "[4/5] Cleaning up build dependencies..."
|
|
||||||
cd /
|
|
||||||
rm -rf /tmp/pgvector
|
|
||||||
apk del build-base git clang llvm-dev postgresql-dev
|
|
||||||
|
|
||||||
echo "[5/5] Creating vector extension in database..."
|
|
||||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
|
||||||
CREATE EXTENSION IF NOT EXISTS vector;
|
|
||||||
EOSQL
|
|
||||||
|
|
||||||
echo "=== pgvector installation complete ==="
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: postgres:15-alpine
|
image: pgvector/pgvector:pg15
|
||||||
container_name: geo_db
|
container_name: geo_db
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -11,7 +11,7 @@ services:
|
||||||
- "5433:5432"
|
- "5433:5432"
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
- ./backend/init-db.sh:/docker-entrypoint-initdb.d/01-install-pgvector.sh
|
- ./docker/init-db:/docker-entrypoint-initdb.d
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U postgres -d geo_platform"]
|
test: ["CMD-SHELL", "pg_isready -U postgres -d geo_platform"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
|
|
@ -48,7 +48,10 @@ services:
|
||||||
memory: 64m
|
memory: 64m
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
build: ./backend
|
build:
|
||||||
|
context: ./backend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
target: ${BACKEND_TARGET:-runtime}
|
||||||
container_name: geo_backend
|
container_name: geo_backend
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
|
|
@ -66,6 +69,12 @@ services:
|
||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
start_period: 30s
|
||||||
|
retries: 3
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
|
|
@ -75,16 +84,21 @@ services:
|
||||||
memory: 256m
|
memory: 256m
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build: ./frontend
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
target: ${FRONTEND_TARGET:-development}
|
||||||
container_name: geo_frontend
|
container_name: geo_frontend
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
environment:
|
||||||
|
NEXT_PUBLIC_API_URL: http://localhost:8000
|
||||||
volumes:
|
volumes:
|
||||||
- ./frontend:/app
|
- ./frontend:/app
|
||||||
- /app/node_modules
|
- frontend_node_modules:/app/node_modules
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
command: npm run dev
|
command: npm run dev
|
||||||
|
|
@ -99,3 +113,4 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
redis_data:
|
redis_data:
|
||||||
|
frontend_node_modules:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
CREATE EXTENSION IF NOT EXISTS vector;
|
||||||
|
|
@ -1,32 +1,35 @@
|
||||||
# ============================================================
|
FROM node:20-alpine AS development
|
||||||
# Stage 1: Builder — 构建 Next.js 生产产物
|
|
||||||
# ============================================================
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["npm", "run", "dev"]
|
||||||
|
|
||||||
FROM node:20-alpine AS builder
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# 安装依赖(利用缓存层)
|
|
||||||
COPY package.json package-lock.json ./
|
COPY package.json package-lock.json ./
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
|
|
||||||
# 复制源码并构建
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# Stage 2: Runner — 只保留运行时必要文件
|
|
||||||
# ============================================================
|
|
||||||
FROM node:20-alpine AS runner
|
FROM node:20-alpine AS runner
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
# 创建非 root 用户运行应用
|
|
||||||
RUN addgroup --system --gid 1001 nodejs \
|
RUN addgroup --system --gid 1001 nodejs \
|
||||||
&& adduser --system --uid 1001 nextjs
|
&& adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
# 复制 standalone 构建产物
|
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||||||
|
|
@ -38,7 +41,6 @@ EXPOSE 3000
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
ENV HOSTNAME="0.0.0.0"
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
# 健康检查
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \
|
||||||
CMD wget -qO- http://localhost:3000/ || exit 1
|
CMD wget -qO- http://localhost:3000/ || exit 1
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue