项目部署
1. Docker 部署
1.1 服务 Dockerfile
dockerfile
FROM eclipse-temurin:21-jre-alpine AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN apk add --no-cache maven && \
mvn clean package -DskipTests
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
CMD wget -q --spider http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", \
"-Xms256m", \
"-Xmx512m", \
"-XX:+UseContainerSupport", \
"-XX:MaxRAMPercentage=75.0", \
"-jar", "app.jar"]1.2 Docker Compose 完整配置
yaml
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./init:/docker-entrypoint-initdb.d
networks:
- ecommerce-network
redis:
image: redis:7-alpine
ports:
- "6379:6379"
networks:
- ecommerce-network
rabbitmq:
image: rabbitmq:3-management
ports:
- "5672:5672"
- "15672:15672"
networks:
- ecommerce-network
nacos:
image: nacos/nacos-server:v2.3.0
environment:
MODE: standalone
ports:
- "8848:8848"
networks:
- ecommerce-network
zipkin:
image: openzipkin/zipkin
ports:
- "9411:9411"
networks:
- ecommerce-network
gateway-service:
build:
context: ./gateway-service
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR=nacos:8848
depends_on:
- nacos
- redis
networks:
- ecommerce-network
user-service:
build:
context: ./user-service
dockerfile: Dockerfile
ports:
- "8081:8081"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR=nacos:8848
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/user_db
depends_on:
- mysql
- nacos
networks:
- ecommerce-network
product-service:
build:
context: ./product-service
dockerfile: Dockerfile
ports:
- "8082:8082"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR=nacos:8848
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/product_db
depends_on:
- mysql
- nacos
- redis
networks:
- ecommerce-network
order-service:
build:
context: ./order-service
dockerfile: Dockerfile
ports:
- "8083:8083"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR=nacos:8848
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/order_db
depends_on:
- mysql
- nacos
- rabbitmq
networks:
- ecommerce-network
networks:
ecommerce-network:
driver: bridge
volumes:
mysql_data:1.3 启动服务
bash
# 构建所有服务
docker-compose build
# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f gateway-service
# 停止所有服务
docker-compose down2. Kubernetes 部署
2.1 Namespace
yaml
apiVersion: v1
kind: Namespace
metadata:
name: ecommerce2.2 ConfigMap
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: user-service-config
namespace: ecommerce
data:
application.yaml: |
spring:
datasource:
url: jdbc:mysql://mysql:3306/user_db
username: root
jpa:
hibernate:
ddl-auto: update
app:
config:
name: user-service2.3 Secret
yaml
apiVersion: v1
kind: Secret
metadata:
name: user-service-secret
namespace: ecommerce
type: Opaque
stringData:
database-password: password
jwt-secret: your-jwt-secret-key2.4 Deployment
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
namespace: ecommerce
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: myregistry/user-service:latest
ports:
- containerPort: 8081
env:
- name: SPRING_PROFILES_ACTIVE
value: "k8s"
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: user-service-secret
key: database-password
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: user-service-secret
key: jwt-secret
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8081
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8081
initialDelaySeconds: 30
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /config
readOnly: true
volumes:
- name: config
configMap:
name: user-service-config2.5 Service
yaml
apiVersion: v1
kind: Service
metadata:
name: user-service
namespace: ecommerce
spec:
selector:
app: user-service
ports:
- port: 80
targetPort: 8081
type: ClusterIP2.6 Ingress
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ecommerce-ingress
namespace: ecommerce
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: api.example.com
http:
paths:
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
- path: /products
pathType: Prefix
backend:
service:
name: product-service
port:
number: 80
- path: /orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 802.7 HPA
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: user-service-hpa
namespace: ecommerce
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: user-service
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 803. CI/CD 流水线
3.1 GitHub Actions
yaml
name: Build and Deploy
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Build with Maven
run: mvn clean package -DskipTests
- name: Run tests
run: mvn test
- name: Build Docker images
run: |
docker build -t myregistry/user-service:${{ github.sha }} ./user-service
docker build -t myregistry/product-service:${{ github.sha }} ./product-service
docker build -t myregistry/order-service:${{ github.sha }} ./order-service
- name: Push Docker images
run: |
docker push myregistry/user-service:${{ github.sha }}
docker push myregistry/product-service:${{ github.sha }}
docker push myregistry/order-service:${{ github.sha }}
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/user-service \
user-service=myregistry/user-service:${{ github.sha }} \
-n ecommerce
kubectl set image deployment/product-service \
product-service=myregistry/product-service:${{ github.sha }} \
-n ecommerce
kubectl set image deployment/order-service \
order-service=myregistry/order-service:${{ github.sha }} \
-n ecommerce4. 小结
本章完成了项目部署:
| 内容 | 要点 |
|---|---|
| Docker 部署 | Dockerfile、Docker Compose |
| Kubernetes 部署 | Deployment、Service、Ingress、HPA |
| CI/CD | GitHub Actions、自动化部署 |
下一章将学习性能优化。