--- name: Deployment description: Deploy applications ไปยังทุก platform อย่างมืออาชีพ --- # Deployment Skill ## Overview Skill สำหรับ deploy applications ตั้งแต่ containerization จนถึง production deployment ## Docker Containerization ### Frontend Dockerfile (Next.js/React/Vue) ```dockerfile # Build stage FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Production stage FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY --from=builder /app/package*.json ./ COPY --from=builder /app/.next ./.next COPY --from=builder /app/public ./public COPY --from=builder /app/node_modules ./node_modules EXPOSE 3000 CMD ["npm", "start"] ``` ### Angular Dockerfile ```dockerfile # Build stage FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build -- --configuration=production # Production stage FROM nginx:alpine COPY --from=builder /app/dist/*/browser /usr/share/nginx/html COPY nginx.conf /etc/nginx/nginx.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` ### Spring Boot Dockerfile ```dockerfile # Build stage FROM eclipse-temurin:21-jdk-alpine AS builder WORKDIR /app COPY mvnw pom.xml ./ COPY .mvn .mvn RUN ./mvnw dependency:go-offline COPY src ./src RUN ./mvnw package -DskipTests # Production stage FROM eclipse-temurin:21-jre-alpine WORKDIR /app COPY --from=builder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"] ``` ### Node.js Dockerfile ```dockerfile FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY dist ./dist EXPOSE 3000 CMD ["node", "dist/index.js"] ``` ### Python FastAPI Dockerfile ```dockerfile FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app ./app EXPOSE 8000 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] ``` --- ## Docker Compose ### Development Environment ```yaml version: "3.8" services: frontend: build: ./frontend ports: - "3000:3000" volumes: - ./frontend:/app - /app/node_modules environment: - NEXT_PUBLIC_API_URL=http://localhost:8080 depends_on: - backend backend: build: ./backend ports: - "8080:8080" environment: - DATABASE_URL=postgresql://user:pass@db:5432/mydb - JWT_SECRET=dev-secret depends_on: - db db: image: postgres:16-alpine ports: - "5432:5432" environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=mydb volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data: ``` --- ## Kubernetes Deployment ### Namespace ```yaml apiVersion: v1 kind: Namespace metadata: name: myapp ``` ### Deployment ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: backend namespace: myapp spec: replicas: 3 selector: matchLabels: app: backend template: metadata: labels: app: backend spec: containers: - name: backend image: myregistry/backend:latest ports: - containerPort: 8080 env: - name: DATABASE_URL valueFrom: secretKeyRef: name: db-secret key: url resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5 ``` ### Service ```yaml apiVersion: v1 kind: Service metadata: name: backend namespace: myapp spec: selector: app: backend ports: - port: 80 targetPort: 8080 type: ClusterIP ``` ### Ingress ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myapp-ingress namespace: myapp annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - api.myapp.com secretName: myapp-tls rules: - host: api.myapp.com http: paths: - path: / pathType: Prefix backend: service: name: backend port: number: 80 ``` --- ## CI/CD Pipeline ### GitHub Actions ```yaml name: CI/CD on: push: branches: [main] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - run: npm ci - run: npm test - run: npm run lint build-and-push: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Build and push uses: docker/build-push-action@v5 with: push: true tags: myregistry/myapp:${{ github.sha }} deploy: needs: build-and-push runs-on: ubuntu-latest steps: - name: Deploy to Kubernetes run: | kubectl set image deployment/backend \ backend=myregistry/myapp:${{ github.sha }} ``` --- ## Deployment Checklist ### Pre-deployment - [ ] Tests ผ่านหมด - [ ] Build สำเร็จ - [ ] Environment variables ถูกต้อง - [ ] Database migrations พร้อม - [ ] Secrets ถูก configure ### Deployment - [ ] Create/Update Docker images - [ ] Push to container registry - [ ] Update Kubernetes manifests - [ ] Apply to cluster - [ ] Verify pods running ### Post-deployment - [ ] Smoke test endpoints - [ ] ตรวจสอบ logs - [ ] Monitor metrics - [ ] Verify health checks - [ ] Rollback plan พร้อม