Files
school-meal/deploy.sh
T

116 lines
3.3 KiB
Bash

#!/usr/bin/env bash
# 学校订餐菜单生成器 - 一键部署脚本 (Ubuntu/Debian)
# 用法: bash deploy.sh <域名>
set -e
DOMAIN="${1:-_}"
APP_DIR=/opt/school-meal
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
echo "==> [1/8] 安装系统依赖"
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y python3 python3-venv python3-pip nginx curl
echo "==> [2/8] 安装 Node.js 20"
if ! command -v node >/dev/null 2>&1; then
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
fi
echo "==> [3/8] 放置代码到 $APP_DIR"
mkdir -p "$APP_DIR"
cp -r "$SCRIPT_DIR/backend" "$SCRIPT_DIR/frontend" "$APP_DIR/"
echo "==> [4/8] 后端环境、迁移与初始化"
cd "$APP_DIR/backend"
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt -q
.venv/bin/python manage.py migrate
.venv/bin/python manage.py seed_dishes
.venv/bin/python manage.py collectstatic --noinput
.venv/bin/python manage.py shell -c "
from django.contrib.auth import get_user_model
U = get_user_model()
if not U.objects.filter(username='admin').exists():
U.objects.create_superuser('admin', 'admin@example.com', 'admin123')
print('已创建管理员 admin / admin123')
else:
print('管理员 admin 已存在')
"
echo "==> [5/8] 后端 systemd 服务 (gunicorn)"
cat > /etc/systemd/system/school-meal.service <<EOF
[Unit]
Description=School Meal Django
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=$APP_DIR/backend
ExecStart=$APP_DIR/backend/.venv/bin/gunicorn config.wsgi:application --bind 127.0.0.1:8000 --workers 3 --timeout 60
Restart=always
[Install]
WantedBy=multi-user.target
EOF
chown -R www-data:www-data "$APP_DIR/backend/db.sqlite3" "$APP_DIR/backend/staticfiles" 2>/dev/null || true
systemctl daemon-reload
systemctl enable --now school-meal.service
systemctl restart school-meal.service
echo "==> [6/8] 前端构建"
cd "$APP_DIR/frontend"
npm install --silent
npm run build
echo "==> [7/8] 配置 Nginx (域名: $DOMAIN)"
cat > /etc/nginx/sites-available/school-meal <<EOF
server {
listen 80;
server_name $DOMAIN;
client_max_body_size 20M;
location /api/ {
proxy_pass http://127.0.0.1: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;
}
location /admin/ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
}
location /static/ {
alias $APP_DIR/backend/staticfiles/;
}
location / {
root $APP_DIR/frontend/dist;
index index.html;
try_files \$uri /index.html;
}
}
EOF
ln -sf /etc/nginx/sites-available/school-meal /etc/nginx/sites-enabled/school-meal
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl enable nginx
systemctl reload nginx
echo "==> [8/8] 验证"
sleep 2
curl -s -o /dev/null -w "后端 API: HTTP %{http_code}\n" http://127.0.0.1:8000/api/dishes/
curl -s -o /dev/null -w "前端页面: HTTP %{http_code}\n" http://127.0.0.1/$DOMAIN
echo ""
echo "部署完成!"
echo " 前台页面: http://$DOMAIN/"
echo " 后台管理: http://$DOMAIN/admin/ (admin / admin123,请尽快修改密码)"
echo " 域名解析: 请确保 $DOMAIN 的 A 记录指向本服务器 IP"