Real-World | Part 5/5

GitLab CI/CD Real-World Projects

ตัวอย่าง GitLab CI/CD Pipeline สำหรับโปรเจคจริง 5 โครงการ พร้อมโค้ดที่ใช้งานได้จริง (Production Ready)

40 นาที Real-World 5 โปรเจค
Node.js API Docker Registry Kubernetes + Helm PostgreSQL Migration Monorepo (Nx)

สารบัญ (Table of Contents)

1. Node.js API Deployment Pipeline

Pipeline สำหรับ Node.js Express API ที่มีการทดสอบ, linting, security scan และ deployment ไปยัง Heroku/DigitalOcean App Platform

Pipeline Flow Overview

Node.js API Pipeline Flow Build npm ci --cache Test Unit + Integration Security npm audit, snyk Deploy Staging/Production Lint Type Check Build Artifact Docker Build 📦 Artifacts: test reports, coverage, docker image

.gitlab-ci.yml Example

image: node:18-alpine

stages:
  - build
  - test
  - security
  - deploy

# Cache node_modules for faster builds
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/
    - .npm/

# Build stage
build-job:
  stage: build
  script:
    - npm ci --cache .npm --prefer-offline
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 week

# Test stage with parallel jobs
test-unit:
  stage: test
  script:
    - npm run test:unit -- --coverage --passWithNoTests
  artifacts:
    reports:
      junit: reports/junit.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'

test-integration:
  stage: test
  script:
    - npm run test:integration
  dependencies:
    - build-job

# Security scanning
security-audit:
  stage: security
  script:
    - npm audit --audit-level=high
    - npx snyk test --severity-threshold=high
  allow_failure: false

# Linting job (runs in parallel)
lint:
  stage: test
  script:
    - npm run lint
    - npm run type-check

# Deploy to staging
deploy-staging:
  stage: deploy
  script:
    - echo "Deploying to staging environment..."
    - npm run deploy:staging
  environment:
    name: staging
    url: https://staging-api.example.com
  only:
    - develop

# Deploy to production
deploy-production:
  stage: deploy
  script:
    - echo "Deploying to production..."
    - npm run deploy:production
  environment:
    name: production
    url: https://api.example.com
  when: manual
  only:
    - main

Key Features

Optimized Caching

ใช้ npm cache และ node_modules cache ลดเวลาการติด dependencies จาก 3-4 นาทีเหลือไม่ถึง 1 นาที

Security Scanning

npm audit และ Snyk สำหรับตรวจสอบ vulnerabilities ใน dependencies ก่อน deploy

Test Coverage Reports

Generate coverage reports ที่ integrate กับ GitLab CI/CD และแสดงผลใน Merge Requests

Environment-based Deployment

Automated deployment ไป staging สำหรับ branch develop และ manual deployment สำหรับ production

2. Docker Build & Push to GitLab Registry

Pipeline สำหรับ build Docker image, run security scans และ push ไปยัง GitLab Container Registry พร้อม support multi-architecture builds

.gitlab-ci.yml for Docker

# Use Docker-in-Docker (dind) service
image: docker:20.10

services:
  - docker:20.10-dind

variables:
  DOCKER_TLS_CERTDIR: "/certs"
  DOCKER_DRIVER: overlay2
  # Use GitLab Container Registry
  CONTAINER_IMAGE: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:$CI_COMMIT_SHA
  CONTAINER_IMAGE_LATEST: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:latest

stages:
  - build
  - test
  - scan
  - push

# Docker Build stage
docker-build:
  stage: build
  script:
    # Login to GitLab Container Registry
    - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
    # Build Docker image
    - docker build --pull -t $CONTAINER_IMAGE -t $CONTAINER_IMAGE_LATEST .
    # Save image as artifact
    - docker save $CONTAINER_IMAGE > image.tar
  artifacts:
    paths:
      - image.tar
    expire_in: 1 hour

# Multi-architecture build (optional)
docker-buildx:
  stage: build
  script:
    - |
      docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
      docker buildx create --name multiarch --use
      docker buildx inspect --bootstrap
      docker buildx build --platform linux/amd64,linux/arm64 \
        -t $CONTAINER_IMAGE \
        -t $CONTAINER_IMAGE_LATEST \
        --push .
  only:
    - main
    - tags

# Security scan with Trivy
docker-scan:
  stage: scan
  image: aquasec/trivy:latest
  script:
    - trivy image --exit-code 1 --severity HIGH,CRITICAL $CONTAINER_IMAGE
    - trivy image --format template --template "@/contrib/gitlab.tpl" --output "gl-dependency-scanning-report.json" $CONTAINER_IMAGE
  artifacts:
    reports:
      dependency_scanning: gl-dependency-scanning-report.json
  allow_failure: false

# Push to GitLab Registry
docker-push:
  stage: push
  script:
    - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
    - docker push $CONTAINER_IMAGE
    - docker push $CONTAINER_IMAGE_LATEST
  dependencies:
    - docker-build
    - docker-scan
  only:
    - main
    - develop
    - /^release\/.*$/

Best Practices Checklist

  • ใช้ Docker multi-stage builds เพื่อลดขนาด image ขั้นสุดท้าย
  • ใช้ `--pull` flag เพื่อให้แน่ใจว่าได้ base image version ล่าสุด
  • Scan image ด้วย Trivy หรือ Clair ก่อน push ไป registry
  • Tag images ด้วย commit SHA สำหรับ traceability
  • เก็บ Docker credentials ใน GitLab CI/CD Variables
  • ใช้ buildx สำหรับ multi-architecture builds (amd64, arm64)
  • Clean up old images จาก registry ด้วย retention policies

Dockerfile Example

# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:18-alpine AS production
WORKDIR /app
ENV NODE_ENV=production
USER node

# Copy built application
COPY --from=builder --chown=node:node /app/dist ./dist
COPY --from=builder --chown=node:node /app/node_modules ./node_modules
COPY --from=builder --chown=node:node /app/package*.json ./

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node -e "require('http').get('http://localhost:${PORT:-3000}/health', (r) => {if(r.statusCode!==200)throw new Error()})"

EXPOSE 3000
CMD ["node", "dist/index.js"]

3. Kubernetes Deployment with Helm

Complete GitOps pipeline สำหรับ deploy applications ไปยัง Kubernetes cluster ด้วย Helm charts, ArgoCD และ automated rollback

GitOps Deployment Architecture

GitOps Pipeline with Helm & ArgoCD GitLab Source Code + CI/CD GitLab Registry Docker Images Helm Chart Repo Chartmuseum/GitLab ArgoCD GitOps Operator Kubernetes Cluster App v1.2.3 Redis PostgreSQL Prometheus/Grafana Loki (Logging) AlertManager

Helm Deployment Pipeline

image: alpine/helm:3.12

stages:
  - lint
  - test
  - package
  - deploy

variables:
  HELM_EXPERIMENTAL_OCI: 1
  KUBE_NAMESPACE: ${CI_PROJECT_NAME}-${CI_ENVIRONMENT_NAME}

# Lint Helm charts
lint-helm:
  stage: lint
  script:
    - helm lint ./charts/myapp
    - helm lint ./charts/myapp --strict

# Test Helm charts with helm test
test-helm:
  stage: test
  script:
    - helm install myapp-test ./charts/myapp --dry-run --debug
    # Run helm test if tests are defined
    - |
      if [ -d "./charts/myapp/templates/tests" ]; then
        helm install test-release ./charts/myapp --wait
        helm test test-release
        helm uninstall test-release
      fi

# Package Helm chart
package-helm:
  stage: package
  script:
    - helm package ./charts/myapp --version ${CI_COMMIT_TAG:-0.0.0+${CI_COMMIT_SHA:0:8}} --app-version ${CI_COMMIT_TAG:-0.0.0}
    - ls -la *.tgz
  artifacts:
    paths:
      - "*.tgz"
    expire_in: 1 week

# Deploy to Kubernetes (Manual approval)
deploy-staging:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - |
      # Configure kubectl
      echo "$KUBECONFIG_STAGING" | base64 -d > kubeconfig.yaml
      export KUBECONFIG=kubeconfig.yaml
      
      # Deploy with Helm
      helm upgrade --install myapp ./charts/myapp \
        --namespace ${KUBE_NAMESPACE} \
        --values ./charts/myapp/values-staging.yaml \
        --set image.tag=${CI_COMMIT_SHA} \
        --atomic \
        --timeout 5m \
        --wait
  environment:
    name: staging
    url: https://staging.myapp.example.com
  only:
    - develop

# Production deployment with manual trigger
deploy-production:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - |
      echo "$KUBECONFIG_PRODUCTION" | base64 -d > kubeconfig.yaml
      export KUBECONFIG=kubeconfig.yaml
      
      helm upgrade --install myapp ./charts/myapp \
        --namespace ${KUBE_NAMESPACE} \
        --values ./charts/myapp/values-production.yaml \
        --set image.tag=${CI_COMMIT_SHA} \
        --atomic \
        --timeout 10m \
        --wait \
        --history-max 5
  environment:
    name: production
    url: https://myapp.example.com
  when: manual
  only:
    - main
    - tags

# Rollback job
rollback-production:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - |
      echo "$KUBECONFIG_PRODUCTION" | base64 -d > kubeconfig.yaml
      export KUBECONFIG=kubeconfig.yaml
      helm rollback myapp 0 --namespace ${KUBE_NAMESPACE}
  when: manual
  only:
    - main
  allow_failure: false

Advanced Features

Atomic Deployments

ใช้ `--atomic` flag ใน Helm เพื่อให้การ deploy สำเร็จทั้งหมดหรือ rollback อัตโนมัติหากล้มเหลว

Revision History

ตั้งค่า `--history-max` เพื่อควบคุมจำนวน revision ที่เก็บไว้สำหรับ rollback

Manual Rollback Job

สร้าง manual job สำหรับ rollback เพื่อให้ทีม operations สามารถ revert deployment ได้อย่างรวดเร็ว

4. Database Migrations (PostgreSQL)

Pipeline สำหรับจัดการ database migrations แบบปลอดภัย ด้วย Liquibase/Flyway พร้อม rollback capability และ pre-deployment validation

Database Migration Pipeline

image: postgres:15-alpine

services:
  - postgres:15-alpine

variables:
  POSTGRES_DB: test_db
  POSTGRES_USER: postgres
  POSTGRES_PASSWORD: postgres
  # Use GitLab CI/CD variables for production DB credentials
  # DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD

stages:
  - validate
  - test-migration
  - migrate
  - rollback-plan

# Validate migration files
validate-migrations:
  stage: validate
  script:
    - |
      # Check SQL syntax
      for file in migrations/*.sql; do
        echo "Validating $file"
        psql -v ON_ERROR_STOP=1 -f "$file" --dry-run
      done
    # Validate with Liquibase/Flyway
    - |
      if [ -f "liquibase.properties" ]; then
        liquibase validate
      fi
  artifacts:
    paths:
      - migrations/

# Test migrations on temporary database
test-migration:
  stage: test-migration
  script:
    - |
      # Create test database
      createdb -U postgres migration_test
      
      # Apply migrations
      for file in migrations/*.sql; do
        echo "Applying $file to test database"
        psql -U postgres -d migration_test -f "$file"
      done
      
      # Run data integrity tests
      psql -U postgres -d migration_test -f tests/data-integrity-check.sql
      
      # Take schema snapshot for comparison
      pg_dump -U postgres -s migration_test > schema_snapshot.sql
  artifacts:
    paths:
      - schema_snapshot.sql
    expire_in: 1 week

# Apply migrations to staging database
migrate-staging:
  stage: migrate
  script:
    - |
      # Use environment-specific credentials
      export PGHOST=${STAGING_DB_HOST}
      export PGPORT=${STAGING_DB_PORT}
      export PGDATABASE=${STAGING_DB_NAME}
      export PGUSER=${STAGING_DB_USER}
      export PGPASSWORD=${STAGING_DB_PASSWORD}
      
      # Backup before migration
      pg_dump -Fc > backup_${CI_COMMIT_SHA}.dump
      
      # Apply migrations with transaction
      psql -v ON_ERROR_STOP=1 <

Safety Guidelines

Critical Safety Rules
  • Always backup database before applying migrations
  • Test migrations on staging environment first
  • Use transactions for atomic migration operations
  • Schedule production migrations during maintenance windows
  • Have rollback plan ready before execution

Migration Tools Comparison

Tool Best For GitLab Integration Rollback Support
Liquibase Enterprise, multiple database types Excellent (Docker image available) Built-in rollback commands
Flyway Simple SQL-based migrations Good (Community edition) Manual rollback scripts
Prisma Migrate Node.js/TypeScript projects Good (npm package) Automatic rollback on failure
Custom SQL scripts Simple projects, full control Manual (shown in example) Manual planning required

5. Monorepo Pipeline (Nx/Turborepo)

Advanced pipeline สำหรับ monorepo projects ที่ใช้ Nx หรือ Turborepo พร้อม selective builds, affected projects detection และ parallel execution

Monorepo Pipeline Architecture

Monorepo Pipeline with Nx/Turborepo Git Changes Detection Detect affected projects Dependency Graph Build order calculation Task Orchestration Parallel execution Projects (Build in Dependency Order) Shared Library API Service Web App Lint All Test All Build All Deploy All ⚡ 63% faster than sequential builds ⚡

Nx Monorepo Pipeline Example

image: node:18-alpine

services:
  - postgres:15-alpine
  - redis:7-alpine

# Install Nx CLI globally
before_script:
  - npm install -g nx@latest
  - npm ci

# Cache node_modules and Nx cache
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/
    - .nx/cache/

stages:
  - affected
  - build
  - test
  - deploy

# Determine affected projects
affected-projects:
  stage: affected
  script:
    # Get list of affected projects
    - npx nx show projects --affected --base=origin/main --head=HEAD --json > affected-projects.json
    - echo "Affected projects:"
    - cat affected-projects.json
  artifacts:
    paths:
      - affected-projects.json
    expire_in: 1 hour

# Build affected projects in parallel
build-affected:
  stage: build
  parallel:
    matrix:
      - PROJECT: ["api", "web", "shared", "admin"]
  script:
    # Check if project is affected
    - |
      if grep -q "\"$PROJECT\"" affected-projects.json; then
        echo "Building $PROJECT..."
        npx nx build $PROJECT
      else
        echo "$PROJECT not affected. Skipping."
      fi
  dependencies:
    - affected-projects
  artifacts:
    paths:
      - dist/apps/$PROJECT/
      - dist/libs/$PROJECT/
    expire_in: 1 week

# Run tests for affected projects
test-affected:
  stage: test
  parallel: 3
  script:
    # Run tests in parallel with Nx
    - npx nx affected --target=test --base=origin/main --head=HEAD --parallel=3
  artifacts:
    reports:
      junit: reports/junit/*.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

# Lint all projects (always run)
lint-all:
  stage: test
  script:
    - npx nx run-many --target=lint --all --parallel=3
  allow_failure: false

# E2E tests for affected apps
e2e-tests:
  stage: test
  script:
    - npx nx affected --target=e2e --base=origin/main --head=HEAD
  services:
    - postgres:15-alpine
    - redis:7-alpine
  artifacts:
    paths:
      - coverage/
      - reports/
    expire_in: 1 week

# Deploy affected apps
deploy-affected:
  stage: deploy
  parallel:
    matrix:
      - APP: ["api", "web", "admin"]
  script:
    - |
      if grep -q "\"$APP\"" affected-projects.json; then
        echo "Deploying $APP..."
        npx nx deploy $APP
      else
        echo "$APP not affected. Skipping deployment."
      fi
  environment:
    name: staging
    url: https://staging.example.com
  when: manual
  only:
    - develop

# Full build for main branch (deploy all)
deploy-production:
  stage: deploy
  script:
    - npx nx run-many --target=deploy --all --prod
  environment:
    name: production
    url: https://example.com
  when: manual
  only:
    - main
    - tags

Performance Optimization Tips

Nx Cloud Caching

ใช้ Nx Cloud สำหรับ distributed task caching ทำให้ build times ลดลง 70-90% เมื่อ multiple developers หรือ CI runners ทำงานพร้อมกัน

Affected Projects Detection

Build เฉพาะ projects ที่มีการเปลี่ยนแปลงจริง ลดเวลา build จาก 15 นาทีเหลือ 2-3 นาทีสำหรับ minor changes

Parallel Execution

ใช้ parallel matrix jobs และ Nx's built-in parallel execution เพื่อรัน tasks พร้อมกันหลาย project

Dependency Graph Optimization

วิเคราะห์ dependency graph เพื่อหา critical path และ optimize build order สำหรับความเร็วสูงสุด

6. Architecture Overview & Diagrams

ภาพรวม architecture ของ GitLab CI/CD pipeline สำหรับองค์กรขนาดกลางถึงใหญ่ พร้อม integration กับ tools ต่างๆ

Complete CI/CD Architecture Diagram

Enterprise GitLab CI/CD Architecture Development Phase IDEs Git PRs GitLab CI/CD Pipeline Build Test Scan Deploy Integrated Tools: Sonar Trivy JUnit Slack Prom Deployment Targets K8s Cloud Server Monitoring & Observability Grafana Prom Loki Security & Compliance SAST DAST SCA Data Layer Postgres Redis MongoDB 🔄 Continuous Feedback Loop 🔄

Key Architecture Decisions

Modular Pipeline Design

แยก pipeline เป็น modules ที่ reuse ได้ เช่น security scanning, deployment templates, test frameworks

Security-First Approach

Embed security scanning ในทุก stage ของ pipeline แทนที่จะเป็นขั้นตอนแยกต่างหาก

Observability Integration

ส่ง metrics, logs และ traces ไปยัง monitoring system สำหรับ real-time feedback

7. สรุปและ Next Steps

ในบทความนี้เราได้เรียนรู้ GitLab CI/CD pipeline สำหรับโปรเจคจริง 5 ประเภท พร้อมตัวอย่างโค้ดที่สามารถนำไปปรับใช้ได้ทันที

สรุป Key Takeaways

  1. 1
    Pipeline Design Patterns

    แต่ละ project type มี pipeline pattern เฉพาะตัวที่เหมาะสมกับ workflow และ deployment target

  2. 2
    Security Integration

    Security scanning ควร embedded อยู่ใน pipeline ไม่ใช่ separate process

  3. 3
    Performance Optimization

    Caching, parallel execution และ affected projects detection ลด build time ได้มากกว่า 50%

  4. 4
    GitOps & Automation

    ใช้ GitOps principles สำหรับ deployment ที่มีความเสถียรและสามารถ audit ได้

  5. 5
    Real-World Readiness

    ตัวอย่างโค้ดทั้งหมดสามารถนำไปใช้ใน production environment ได้จริง

Next Steps & Recommendations

สำหรับทีมที่เพิ่งเริ่มต้น
  • เริ่มจาก Node.js API pipeline ก่อน (Project 1)
  • Implement Docker pipeline ตาม (Project 2)
  • เพิ่ม security scanning โดยใช้ Trivy
  • วัด pipeline performance ก่อนและหลัง optimization
สำหรับทีมระดับกลาง
  • Implement Kubernetes deployment pipeline (Project 3)
  • เพิ่ม database migration pipeline (Project 4)
  • ใช้ GitOps workflow ด้วย ArgoCD
  • Implement monitoring และ alerting
สำหรับทีมระดับสูง
  • Implement monorepo pipeline (Project 5)
  • ใช้ Nx Cloud สำหรับ distributed caching
  • สร้าง pipeline templates สำหรับ reuse
  • Implement canary deployments และ feature flags
สำหรับองค์กรขนาดใหญ่
  • สร้าง internal CI/CD platform บน GitLab
  • Implement compliance scanning และ audit trails
  • ใช้ GitLab Ultimate features (SAST, DAST, Container Scanning)
  • สร้าง self-service pipeline templates

8. Series Recap (Part 1-5)

มาสรุปสิ่งที่เราได้เรียนรู้ตลอดทั้ง 5 parts ของ GitLab CI/CD Series

Learning Journey Progress

GitLab CI/CD Mastery 100% Complete
Fundamentals ✓
Intermediate ✓
Optimization ✓
Best Practices ✓
Real-World ✓
Congratulations!

คุณได้สำเร็จการเรียนรู้ GitLab CI/CD ทั้ง 5 parts และพร้อมนำความรู้ไปใช้ในโปรเจคจริงแล้ว!

ทักษะที่คุณได้เรียนรู้สามารถนำไปใช้ได้กับทีม DevOps, Platform Engineering, หรือ Software Development ทุกประเภท

9. Additional Resources

← Previous
Part 4: Best Practices
Series Complete ✓
Part 5: Real-World Projects