chore: Docker生产部署配置 + 部署脚本
This commit is contained in:
78
deploy.sh
Normal file
78
deploy.sh
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ============================================================
|
||||||
|
# Track 生产流转系统 — 增量部署脚本
|
||||||
|
# 服务器: 172.16.0.198
|
||||||
|
# 路径: /opt/Track
|
||||||
|
# 仅更新代码,不覆盖数据库
|
||||||
|
# ============================================================
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SERVER="dxc@172.16.0.198"
|
||||||
|
REMOTE_DIR="/opt/Track"
|
||||||
|
TIMESTAMP=$(date +%Y%m%d_%H%M)
|
||||||
|
REMOTE_BACKUP_DIR="$REMOTE_DIR/backups/$TIMESTAMP"
|
||||||
|
|
||||||
|
echo "==================================================="
|
||||||
|
echo "🚀 Track 增量部署 — 仅更新代码"
|
||||||
|
echo "==================================================="
|
||||||
|
|
||||||
|
# 1. 远端备份
|
||||||
|
echo "[1/4] 服务器备份旧代码..."
|
||||||
|
ssh -t $SERVER "sudo mkdir -p $REMOTE_BACKUP_DIR && \
|
||||||
|
cd $REMOTE_DIR && \
|
||||||
|
echo '>> 备份当前代码...' && \
|
||||||
|
sudo tar -czf $REMOTE_BACKUP_DIR/code_backup.tar.gz \
|
||||||
|
backend frontend docker-compose.prod.yml 2>/dev/null || true && \
|
||||||
|
echo '>> 保留最近 3 个备份...' && \
|
||||||
|
cd $REMOTE_DIR/backups && \
|
||||||
|
sudo sh -c 'ls -dt */ 2>/dev/null | tail -n +4 | xargs -I {} rm -rf {} || true'"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then echo "❌ 备份失败,终止!"; exit 1; fi
|
||||||
|
|
||||||
|
# 2. 本地打包
|
||||||
|
echo "[2/4] 本地打包代码..."
|
||||||
|
tar -czf deploy.tar.gz \
|
||||||
|
--exclude="backend/venv" \
|
||||||
|
--exclude="backend/.venv" \
|
||||||
|
--exclude="backend/__pycache__" \
|
||||||
|
--exclude="backend/*.pyc" \
|
||||||
|
--exclude="backend/.env" \
|
||||||
|
--exclude="backend/uploads" \
|
||||||
|
--exclude="frontend/node_modules" \
|
||||||
|
--exclude="frontend/dist" \
|
||||||
|
--exclude=".git" \
|
||||||
|
--exclude=".idea" \
|
||||||
|
--exclude=".vscode" \
|
||||||
|
--exclude="track-uniapp/node_modules" \
|
||||||
|
--exclude="track-uniapp/dist" \
|
||||||
|
--exclude="track-uniapp/unpackage" \
|
||||||
|
backend frontend docker-compose.prod.yml
|
||||||
|
|
||||||
|
FILESIZE=$(stat -c%s "deploy.tar.gz" 2>/dev/null || stat -f%z "deploy.tar.gz")
|
||||||
|
echo ">> 打包完成: $((FILESIZE / 1024 / 1024)) MB"
|
||||||
|
|
||||||
|
# 3. 上传
|
||||||
|
echo "[3/4] 上传到服务器..."
|
||||||
|
scp deploy.tar.gz $SERVER:/tmp/deploy.tar.gz
|
||||||
|
if [ $? -ne 0 ]; then echo "❌ 上传失败!"; rm -f deploy.tar.gz; exit 1; fi
|
||||||
|
|
||||||
|
# 4. 替换重启
|
||||||
|
echo "[4/4] 服务器替换并重启..."
|
||||||
|
ssh -t $SERVER "cd $REMOTE_DIR && \
|
||||||
|
echo '>> 移除旧备份...' && \
|
||||||
|
sudo rm -rf backend_old frontend_old && \
|
||||||
|
echo '>> 保留当前为 old...' && \
|
||||||
|
(sudo mv backend backend_old 2>/dev/null || true) && \
|
||||||
|
(sudo mv frontend frontend_old 2>/dev/null || true) && \
|
||||||
|
echo '>> 解压新代码...' && \
|
||||||
|
sudo mv /tmp/deploy.tar.gz . && \
|
||||||
|
sudo tar -xzf deploy.tar.gz && \
|
||||||
|
echo '>> 重启 Docker...' && \
|
||||||
|
sudo docker compose -f docker-compose.prod.yml up -d --build && \
|
||||||
|
sudo rm deploy.tar.gz && \
|
||||||
|
echo '>> ✅ 部署完成!'"
|
||||||
|
|
||||||
|
rm -f deploy.tar.gz
|
||||||
|
echo "==================================================="
|
||||||
|
echo "✅ 增量部署完成!访问 http://172.16.0.198:8010"
|
||||||
|
echo "==================================================="
|
||||||
91
deploy_full.sh
Normal file
91
deploy_full.sh
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ============================================================
|
||||||
|
# Track 生产流转系统 — 全量部署脚本(含数据库同步)
|
||||||
|
# 服务器: 172.16.0.198
|
||||||
|
# 路径: /opt/Track
|
||||||
|
# ⚠️ 会覆盖生产数据库!请确认后再执行!
|
||||||
|
# ============================================================
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SERVER="dxc@172.16.0.198"
|
||||||
|
REMOTE_DIR="/opt/Track"
|
||||||
|
TIMESTAMP=$(date +%Y%m%d_%H%M)
|
||||||
|
REMOTE_BACKUP_DIR="$REMOTE_DIR/backups/$TIMESTAMP"
|
||||||
|
|
||||||
|
echo "⚠️⚠️⚠️ 警告:此操作将覆盖生产数据库!⚠️⚠️⚠️"
|
||||||
|
read -p "确认继续?(y/n) " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1. 远端全量备份
|
||||||
|
echo "[1/5] 服务器全量备份..."
|
||||||
|
ssh -t $SERVER "sudo mkdir -p $REMOTE_BACKUP_DIR && \
|
||||||
|
cd $REMOTE_DIR && \
|
||||||
|
echo '>> 导出线上数据库...' && \
|
||||||
|
sudo sh -c 'docker exec track_db_prod pg_dumpall -c -U track | gzip > $REMOTE_BACKUP_DIR/db_backup.sql.gz' && \
|
||||||
|
echo '>> 备份代码...' && \
|
||||||
|
sudo tar -czf $REMOTE_BACKUP_DIR/code_backup.tar.gz \
|
||||||
|
backend frontend docker-compose.prod.yml 2>/dev/null || true && \
|
||||||
|
echo '>> 保留最近 3 个备份...' && \
|
||||||
|
cd $REMOTE_DIR/backups && \
|
||||||
|
sudo sh -c 'ls -dt */ 2>/dev/null | tail -n +4 | xargs -I {} rm -rf {} || true'"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then echo "❌ 备份失败,终止!"; exit 1; fi
|
||||||
|
|
||||||
|
# 2. 导出本地数据库
|
||||||
|
echo "[2/5] 导出本地数据库..."
|
||||||
|
docker exec track_db pg_dumpall -c -U track | gzip > db_sync.sql.gz
|
||||||
|
echo ">> 数据库导出完成"
|
||||||
|
|
||||||
|
# 3. 本地打包
|
||||||
|
echo "[3/5] 本地打包代码+数据库..."
|
||||||
|
tar -czf deploy_full.tar.gz \
|
||||||
|
--exclude="backend/venv" \
|
||||||
|
--exclude="backend/.venv" \
|
||||||
|
--exclude="backend/__pycache__" \
|
||||||
|
--exclude="backend/*.pyc" \
|
||||||
|
--exclude="backend/.env" \
|
||||||
|
--exclude="backend/uploads" \
|
||||||
|
--exclude="frontend/node_modules" \
|
||||||
|
--exclude="frontend/dist" \
|
||||||
|
--exclude=".git" \
|
||||||
|
--exclude=".idea" \
|
||||||
|
--exclude=".vscode" \
|
||||||
|
--exclude="track-uniapp/node_modules" \
|
||||||
|
--exclude="track-uniapp/dist" \
|
||||||
|
--exclude="track-uniapp/unpackage" \
|
||||||
|
--exclude="backups" \
|
||||||
|
backend frontend docker-compose.prod.yml db_sync.sql.gz
|
||||||
|
|
||||||
|
FILESIZE=$(stat -c%s "deploy_full.tar.gz" 2>/dev/null || stat -f%z "deploy_full.tar.gz")
|
||||||
|
echo ">> 打包完成: $((FILESIZE / 1024 / 1024)) MB"
|
||||||
|
|
||||||
|
# 4. 上传
|
||||||
|
echo "[4/5] 上传到服务器..."
|
||||||
|
scp deploy_full.tar.gz $SERVER:/tmp/deploy_full.tar.gz
|
||||||
|
if [ $? -ne 0 ]; then echo "❌ 上传失败!"; rm -f deploy_full.tar.gz db_sync.sql.gz; exit 1; fi
|
||||||
|
|
||||||
|
# 5. 替换+导入+重启
|
||||||
|
echo "[5/5] 服务器部署..."
|
||||||
|
ssh -t $SERVER "cd $REMOTE_DIR && \
|
||||||
|
echo '>> 移除旧备份...' && \
|
||||||
|
sudo rm -rf backend_old frontend_old && \
|
||||||
|
echo '>> 保留当前为 old...' && \
|
||||||
|
(sudo mv backend backend_old 2>/dev/null || true) && \
|
||||||
|
(sudo mv frontend frontend_old 2>/dev/null || true) && \
|
||||||
|
echo '>> 解压新代码...' && \
|
||||||
|
sudo mv /tmp/deploy_full.tar.gz . && \
|
||||||
|
sudo tar -xzf deploy_full.tar.gz && \
|
||||||
|
echo '>> 重启 Docker...' && \
|
||||||
|
sudo docker compose -f docker-compose.prod.yml up -d --build && \
|
||||||
|
echo '>> 导入数据库...' && \
|
||||||
|
sudo sh -c 'gunzip -c db_sync.sql.gz | docker exec -i track_db_prod psql -U track -d track_production' && \
|
||||||
|
sudo rm deploy_full.tar.gz db_sync.sql.gz && \
|
||||||
|
echo '>> ✅ 全量部署完成!'"
|
||||||
|
|
||||||
|
rm -f deploy_full.tar.gz db_sync.sql.gz
|
||||||
|
echo "==================================================="
|
||||||
|
echo "✅ 全量部署完成!访问 http://172.16.0.198:8010"
|
||||||
|
echo "==================================================="
|
||||||
81
docker-compose.prod.yml
Normal file
81
docker-compose.prod.yml
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# ============================================================
|
||||||
|
# 生产流转管理系统 — 生产环境 Docker Compose
|
||||||
|
# 服务器: 172.16.0.198
|
||||||
|
# 部署路径: /opt/Track
|
||||||
|
# 启动: docker compose -f docker-compose.prod.yml up -d --build
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
services:
|
||||||
|
# ============================================================
|
||||||
|
# PostgreSQL 15 + pgvector
|
||||||
|
# ============================================================
|
||||||
|
db:
|
||||||
|
image: pgvector/pgvector:pg15
|
||||||
|
container_name: track_db_prod
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: track
|
||||||
|
POSTGRES_PASSWORD: track_prod_2026
|
||||||
|
POSTGRES_DB: track_production
|
||||||
|
ports:
|
||||||
|
- "8012:5432"
|
||||||
|
volumes:
|
||||||
|
- track_pgdata_prod:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U track -d track_production"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# FastAPI 后端 — gunicorn + uvicorn (生产模式,无热更新)
|
||||||
|
# ============================================================
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ./backend
|
||||||
|
dockerfile: Dockerfile.dev
|
||||||
|
container_name: track_backend_prod
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
DATABASE_URL: postgresql+asyncpg://track:track_prod_2026@track_db_prod:5432/track_production
|
||||||
|
SECRET_KEY: change-me-in-production-please
|
||||||
|
DEBUG: "false"
|
||||||
|
CORS_ORIGINS: '["http://172.16.0.198:8010","https://172.16.0.198:8010","http://172.16.0.198","tauri://localhost"]'
|
||||||
|
# 🚀 MOM 老系统数据库 — 用户登录验证 + 用户名单来源
|
||||||
|
MOM_DB_HOST: inventory_db_prod
|
||||||
|
MOM_DB_PORT: "5432"
|
||||||
|
ports:
|
||||||
|
- "8011:8000"
|
||||||
|
volumes:
|
||||||
|
- ./backend:/app
|
||||||
|
command: >
|
||||||
|
sh -c "uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4 --log-level info"
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
- mom_net
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# React 前端 — Nginx 静态文件服务 (生产模式)
|
||||||
|
# ============================================================
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile.prod
|
||||||
|
container_name: track_frontend_prod
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "8010:80"
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
networks:
|
||||||
|
mom_net:
|
||||||
|
external: true
|
||||||
|
name: inventory-app_default
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
track_pgdata_prod:
|
||||||
|
name: track_pgdata_prod
|
||||||
18
frontend/Dockerfile.prod
Normal file
18
frontend/Dockerfile.prod
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# ============================================================
|
||||||
|
# 前端生产 Dockerfile — 多阶段构建:Vite 打包 → Nginx 托管
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# --- 阶段 1:编译 React ---
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm ci --production=false
|
||||||
|
COPY . .
|
||||||
|
RUN npx vite build
|
||||||
|
|
||||||
|
# --- 阶段 2:Nginx 托管静态文件 ---
|
||||||
|
FROM nginx:alpine
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
EXPOSE 80
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
32
frontend/nginx.conf
Normal file
32
frontend/nginx.conf
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Gzip 压缩
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/css application/javascript application/json image/svg+xml;
|
||||||
|
gzip_min_length 256;
|
||||||
|
|
||||||
|
# 静态文件缓存
|
||||||
|
location /assets/ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# API 代理到后端
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://backend:8000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# SPA 路由回退
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user