feat: 新增前端自动化部署

This commit is contained in:
wood911010 committed 2025-07-31 13:44:44 +08:00
1 parent fb0121cced
commit 8741f019fa
5 files changed
+1574 -388

No files matched your search

+96
View File
@@ -0,0 +1,96 @@
name: Deploy Frontend
on:
push:
branches: [ main ]
paths:
- 'frontend/**'
- 'Dockerfile.frontend'
- 'nginx.conf'
- '.github/workflows/deploy_frontend.yml'
workflow_dispatch:
env:
IMAGE_NAME: license-manager-frontend
CONTAINER_NAME: license-manager-frontend
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
run: |
docker build -f Dockerfile.frontend -t ${{ env.IMAGE_NAME }}:latest .
docker save ${{ env.IMAGE_NAME }}:latest > frontend-image.tar
- name: Copy files to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST_1 }}
username: root
password: ${{ secrets.PASS_1 }}
port: 22
source: "frontend-image.tar"
target: "/opt/license-manager/"
- name: Deploy to server
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.HOST_1 }}
username: root
password: ${{ secrets.PASS_1 }}
port: 22
script: |
cd /opt/license-manager
# Stop and remove existing container
docker stop ${{ env.CONTAINER_NAME }} || true
docker rm ${{ env.CONTAINER_NAME }} || true
# Load new image
docker load < frontend-image.tar
# Remove old image
docker rmi ${{ env.IMAGE_NAME }}:old || true
docker tag ${{ env.IMAGE_NAME }}:latest ${{ env.IMAGE_NAME }}:old || true
# Run new container
docker run -d \
--name ${{ env.CONTAINER_NAME }} \
--restart unless-stopped \
-p 18080:80 \
--add-host host.docker.internal:host-gateway \
${{ env.IMAGE_NAME }}:latest
# Clean up
rm -f frontend-image.tar
docker image prune -f
# Check deployment status
sleep 5
if docker ps | grep -q ${{ env.CONTAINER_NAME }}; then
echo "✅ Frontend deployment successful! Container is running."
docker logs --tail 10 ${{ env.CONTAINER_NAME }}
else
echo "❌ Frontend deployment failed! Container is not running."
docker logs ${{ env.CONTAINER_NAME }}
exit 1
fi
- name: Health check
run: |
sleep 10
response=$(curl -s -o /dev/null -w "%{http_code}" http://${{ secrets.HOST_1 }}:18080/ || echo "000")
if [ "$response" = "200" ]; then
echo "✅ Frontend health check passed! Service is responding."
else
echo "⚠️ Frontend health check returned status: $response"
echo "Service may still be starting up..."
fi
+65
View File
@@ -0,0 +1,65 @@
# 前端自动化部署
基于Docker的前端自动化部署方案,使用GitHub Actions实现CI/CD。
## 部署特点
- 🐳 Docker容器化部署
- 🚀 自动构建和部署
- 🔄 零停机更新
- 🌐 内置Nginx服务器
- 📱 支持Vue Router history模式
- 🔗 API代理到后端服务
## 配置要求
### GitHub Secrets
在GitHub仓库设置以下Secrets:
- `HOST_1`: 服务器IP地址
- `PASS_1`: 服务器root密码
### 服务器要求
- 安装Docker
## 部署流程
1. 推送代码到main分支(前端相关文件有变更时)
2. GitHub Actions自动触发
3. 构建Docker镜像(Vue3 + Nginx)
4. 上传镜像到服务器
5. 停止旧容器并启动新容器
6. 健康检查
## 访问地址
部署完成后,前端服务将在以下地址提供:
- **前端地址**: http://服务器IP:18080
- **API代理**: 前端的 `/api/*` 请求会代理到后端 `http://localhost:18888/`
## 手动触发
可以在GitHub Actions页面手动触发部署,无需推送代码。
## 监控和维护
### 查看容器状态
```bash
docker ps | grep license-manager-frontend
```
### 查看容器日志
```bash
docker logs license-manager-frontend
```
### 重启容器
```bash
docker restart license-manager-frontend
```
## 故障排除
1. **部署失败**: 检查GitHub Actions日志
2. **容器无法启动**: 检查Docker镜像和容器配置
3. **页面无法访问**: 检查服务器防火墙18080端口
4. **API请求失败**: 确认后端服务运行在18888端口
+30
View File
@@ -0,0 +1,30 @@
# Multi-stage build for frontend
FROM node:18-alpine AS builder
WORKDIR /app
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run prod
# Production stage with Nginx
FROM nginx:alpine
# Copy built assets
COPY --from=builder /app/dist /usr/share/nginx/html
# Copy custom nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Create log directory
RUN mkdir -p /var/log/nginx
# Expose port
EXPOSE 80
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
+1319 -388
View File
File diff suppressed because it is too large. Load diff
+64
View File
@@ -0,0 +1,64 @@
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/javascript
application/xml+rss
application/json
image/svg+xml;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
# Handle Vue Router history mode
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# API proxy to backend (if backend is on the same server)
location /api/ {
proxy_pass http://host.docker.internal:18888/;
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;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Disable access to hidden files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Custom error pages
error_page 404 /index.html;
error_page 500 502 503 504 /index.html;
}