feat: add Dockerfile and upgrade Jenkinsfile to full CI/CD

- Multi-stage build: node:22 (pnpm build) → nginx runtime
- nginx.conf with SPA routing and API proxy
- Jenkinsfile: Docker build → push → deploy
This commit is contained in:
向宁 2026-05-17 19:17:07 +08:00
parent 059aebfa28
commit 755517a068
4 changed files with 96 additions and 33 deletions

View File

@ -1,7 +1,10 @@
node_modules
.git
.gitignore
*.md
dist
.turbo
dist
dist.zip
.husky/
.vscode/
.idea/
*.log

15
Dockerfile Normal file
View File

@ -0,0 +1,15 @@
FROM node:22-alpine AS build
WORKDIR /app
RUN corepack enable && corepack prepare pnpm@10 --activate
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
COPY . .
RUN pnpm install --frozen-lockfile
RUN pnpm run build:antd
FROM nginx:alpine AS runtime
COPY --from=build /app/apps/web-antd/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

81
Jenkinsfile vendored
View File

@ -2,59 +2,78 @@ pipeline {
agent any
environment {
NODE_VERSION = '22'
NVM_DIR = "$HOME/.nvm"
CI_REGISTRY = '192.168.1.154:31010'
DOCKER_IMAGE = 'docker/rag-frontend'
DOCKER_TAG = "${BUILD_NUMBER}"
DEPLOY_DIR = '/home/xiangning/deploy/rag-frontend'
}
stages {
stage('Setup Node.js') {
steps {
sh '''
if ! command -v node &> /dev/null; then
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
. "$NVM_DIR/nvm.sh"
nvm install $NODE_VERSION
nvm use $NODE_VERSION
fi
. "$NVM_DIR/nvm.sh"
node -v
npm install -g pnpm@10
pnpm -v
'''
}
}
stage('Install') {
stage('Checkout') {
steps {
sh '''
. "$NVM_DIR/nvm.sh"
pnpm install --frozen-lockfile
'''
echo '=== Checkout ==='
checkout scm
sh 'git log --oneline -5'
}
}
stage('Build') {
steps {
sh '''
. "$NVM_DIR/nvm.sh"
pnpm run build:antd
'''
echo '=== Build Docker Image ==='
sh """
echo "Registry: ${CI_REGISTRY}"
echo "Image: ${DOCKER_IMAGE}:${DOCKER_TAG}"
docker build -t ${DOCKER_IMAGE}:${DOCKER_TAG} .
docker tag ${DOCKER_IMAGE}:${DOCKER_TAG} ${DOCKER_IMAGE}:latest
"""
}
}
stage('Archive') {
stage('Push') {
steps {
archiveArtifacts artifacts: 'apps/web-antd/dist/**', allowEmptyArchive: true, fingerprint: true
echo '=== Push to Registry ==='
sh """
echo 'dockerxn001624.' | docker login -u docker --password-stdin ${CI_REGISTRY}
docker tag ${DOCKER_IMAGE}:${DOCKER_TAG} ${CI_REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG}
docker tag ${DOCKER_IMAGE}:latest ${CI_REGISTRY}/${DOCKER_IMAGE}:latest
docker push ${CI_REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG}
docker push ${CI_REGISTRY}/${DOCKER_IMAGE}:latest
"""
}
}
stage('Deploy') {
steps {
echo '=== Deploy ==='
sh """
mkdir -p ${DEPLOY_DIR}
cd ${DEPLOY_DIR}
cat > docker-compose.yml << 'DCOF'
services:
rag-frontend:
image: ${CI_REGISTRY}/${DOCKER_IMAGE}:latest
container_name: rag-frontend
ports:
- "8080:80"
restart: unless-stopped
DCOF
docker compose pull
docker compose down --remove-orphans || true
docker compose up -d
docker image prune -f
docker compose ps
"""
}
}
}
post {
success {
echo 'Frontend build succeeded!'
echo '=== CI/CD SUCCESS ==='
}
failure {
echo 'Frontend build failed!'
echo '=== CI/CD FAILED ==='
}
always {
deleteDir()

26
nginx.conf Normal file
View File

@ -0,0 +1,26 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
# Proxy API requests to rag-backend
location /api/ {
proxy_pass http://192.168.1.154:5211/api/;
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;
}
# Static file caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}