docs: Nâng cấp hướng dẫn triển khai Kubernetes cục bộ với sơ đồ quy trình, hướng dẫn chi tiết và chú thích song ngữ.

This commit is contained in:
Ho Ngoc Hai
2026-01-05 19:15:09 +07:00
parent d8d013ed2e
commit 4f48eadea8
4 changed files with 694 additions and 1690 deletions

View File

@@ -1,396 +1,273 @@
# Local Kubernetes Deployment Guide
**Last Updated**: 2026-01-04
**Difficulty**: Intermediate
> **EN**: Local Kubernetes Deployment Guide
>
> **VI**: Hướng dẫn triển khai Kubernetes cục bộ
**Last Updated**: 2026-01-05
**Difficulty**: Intermediate
**Duration**: 30-45 minutes
## Workflow
```mermaid
graph TD
Start([Start]) --> EnvPrep[1. Environment Prep]
EnvPrep --> BuildImg[2. Build Docker Image]
BuildImg --> LoadImg[3. Load Image to Cluster<br/>(Kind/Docker Desktop)]
LoadImg --> Secrets[4. Configure Secrets<br/>& Environment]
Secrets --> Deploy[5. Deploy Service<br/>(K8s Manifests)]
Deploy --> Verify[6. Verify Deployment]
Verify --> Test[7. Test Service<br/>(Port Forward & Curl)]
Test --> End([Complete])
subgraph "Deployment Details"
Deploy --> |Apply| ConfigMap
Deploy --> |Apply| Deployment
Deploy --> |Apply| Service
end
style Start fill:#d4edda,stroke:#28a745,stroke-width:2px
style End fill:#d4edda,stroke:#28a745,stroke-width:2px
style EnvPrep fill:#e2e3e5,stroke:#6c757d
style BuildImg fill:#fff3cd,stroke:#ffc107
style LoadImg fill:#fff3cd,stroke:#ffc107
style Secrets fill:#f8d7da,stroke:#dc3545
style Deploy fill:#cce5ff,stroke:#007bff
style Verify fill:#cce5ff,stroke:#007bff
```
## Overview
This guide describes how to deploy the IAM Service to a local Kubernetes cluster using Docker Desktop on macOS.
This guide details how to deploy the IAM Service (or any microservice in the GoodGo ecosystem) to a local Kubernetes cluster using Docker Desktop on macOS.
## Prerequisites
> **Important Note**: This guide assumes you are using **Docker Desktop** with **Kubernetes enabled**. If you are using Minikube or plain Kind, the steps might differ slightly (especially the image loading part).
## 1. Prerequisites
### Software
- Docker Desktop 4.0+ with Kubernetes enabled
- kubectl CLI
- kind CLI (for loading images into cluster)
- pnpm 8+
- **Docker Desktop 4.0+**: [Download Link](https://www.docker.com/products/docker-desktop/)
- Kubernetes must be enabled in settings.
- **kubectl CLI**: Command-line tool for interacting with K8s.
```bash
brew install kubectl
```
- **kind CLI**: Required to load images into the cluster if using Kind backend explicitely.
```bash
brew install kind
```
- **pnpm 8+**: Project package manager.
```bash
npm install -g pnpm
```
### Knowledge
- Basic understanding of Kubernetes (Pods, Deployments, Services)
- Familiarity with Docker and containerization
- Command line proficiency
- Basic understanding of Kubernetes concepts: **Pod**, **Deployment**, **Service**, **Secret**, **ConfigMap**.
- Familiarity with basic Docker commands (`docker build`, `docker images`).
- Ability to navigate and run commands in the Terminal.
## Step 1: Environment Preparation
## 2. Environment Preparation
### 1.1 Enable Kubernetes in Docker Desktop
### 2.1 Enable Kubernetes in Docker Desktop
1. Open **Docker Desktop**
2. Go to **Settings → Kubernetes**
3. Check **Enable Kubernetes**
4. Select cluster provisioning:
- **kind** (recommended for development)
- or **kubeadm**
5. Click **Apply & Restart**
6. Wait 2-3 minutes for Kubernetes to start
1. Open **Docker Desktop**.
2. Click the **Settings (⚙️)** icon.
3. Select the **Kubernetes** tab.
4. Check **Enable Kubernetes**.
5. Select **Show system containers (advanced)** for easier debugging (optional).
6. Click **Apply & Restart**.
7. Wait 2-3 minutes until the Kubernetes icon in the bottom corner turns green.
### 1.2 Verify Kubernetes
### 2.2 Verify Kubernetes Connection
Check if `kubectl` is connected to the correct context:
```bash
# Check kubectl context
# EN: Check current context
# VI: Kiểm tra context hiện tại
kubectl config current-context
# Output: docker-desktop
# Expected Output: docker-desktop
# Check nodes
# EN: List all nodes in the cluster
# VI: Liệt kê các node trong cluster
kubectl get nodes
# Output: docker-desktop Ready control-plane ...
# Check kind cluster name (if using kind)
kind get clusters
# Output: desktop
# Expected Output:
# NAME STATUS ROLES AGE VERSION
# docker-desktop Ready control-plane 10m v1.29.1
```
### 1.3 Install kind CLI
## 3. Build Docker Image
We need to build the service image before deploying. Taking `iam-service` as an example.
```bash
# Install kind
brew install kind
# Verify installation
kind version
```
## Step 2: Build Docker Image
```bash
# Navigate to deployments directory
# EN: Navigate to the kubernetes deployment directory
# VI: Di chuyển đến thư mục deployments/local/kubernetes
cd deployments/local/kubernetes
# Build image (script auto-builds)
# EN: Build the Docker image from the root context
# VI: Build Docker image từ root context
# Note: -f points to service Dockerfile, context is root (../../..)
docker build -t iam-service:local -f ../../../services/iam-service/Dockerfile ../../..
# Verify image
# EN: Verify the image was built successfully
# VI: Kiểm tra image đã build thành công chưa
docker images | grep iam-service
# Output: iam-service:local ... 1.67GB
# Expected Output:
# iam-service local [IMAGE_ID] [SIZE] [CREATED]
```
## Step 3: Load Image into Kubernetes Cluster
## 4. Load Image into Cluster
**⚠️ Important**: Docker Desktop Kubernetes with kind backend **does not automatically share images** with Docker Desktop. You must load the image into the cluster:
**⚠️ IMPORTANT**: Docker Desktop can use different backends. If you are running Kubernetes inside Docker Desktop, sometimes it doesn't immediately see local images if using a `kind` node underneath.
If you are using **Kind** (Kubernetes in Docker) separately or a specific Docker Desktop config, you need to load the image:
```bash
# Load image into kind cluster
# EN: Load image into kind cluster (if using kind explicitly)
# VI: Load image vào kind cluster (nếu dùng kind rõ ràng)
kind load docker-image iam-service:local --name desktop
# Wait for completion (may take 1-2 minutes)
# EN: Validating image presence (optional, hard with Docker Desktop K8s directly)
# VI: Kiểm tra sự tồn tại của image (tùy chọn)
```
**Note**: If using kubeadm instead of kind, you can skip this step as kubeadm shares images better.
> **Tip**: With default Docker Desktop, building the local image (`docker build ...`) is usually automatically available to Docker Desktop's K8s cluster. This loading step is mainly for those using `kind` CLI to create separate clusters.
## Step 4: Configure Secrets
## 5. Configure Secrets & ConfigMap
### 4.1 Prepare Environment Variables
Kubernetes environments need sensitive environment variables (Secrets) and general configuration (ConfigMap).
Create `.env.k8s` file with the following variables:
### 5.1 Create Secrets (Manually)
You can run a script or the following commands to create secrets securely.
```bash
# Database
DATABASE_URL=postgresql://user:password@host:5432/database?sslmode=require
# JWT Secrets (MUST change in production!)
JWT_SECRET=your-strong-jwt-secret-min-32-chars
JWT_REFRESH_SECRET=your-strong-refresh-secret-min-32-chars
JWT_ID_SECRET=your-strong-id-secret-min-32-chars
# Encryption (optional)
ENCRYPTION_KEY=your-32-char-encryption-key-here
```
### 4.2 Create Kubernetes Secrets
The `deploy.sh` script will automatically create secrets, or you can create them manually:
```bash
# Create namespace
# EN: Create a dedicated namespace for local testing
# VI: Tạo namespace riêng cho local testing
kubectl create namespace iam-local
# Create secrets
# EN: Generate random secrets and store in Kubernetes
# VI: Tạo secrets ngẫu nhiên và lưu vào Kubernetes
kubectl create secret generic iam-service-secrets \
--from-literal=DATABASE_URL="postgresql://..." \
--from-literal=DATABASE_URL="postgresql://user:password@host.docker.internal:5432/iam_db?schema=public" \
--from-literal=JWT_SECRET="$(openssl rand -base64 32)" \
--from-literal=JWT_REFRESH_SECRET="$(openssl rand -base64 32)" \
--from-literal=JWT_ID_SECRET="$(openssl rand -base64 32)" \
--from-literal=ENCRYPTION_KEY="$(openssl rand -base64 32)" \
-n iam-local
# Verify secrets
# EN: Verify secrets creation
# VI: Kiểm tra secrets đã tạo
kubectl get secrets -n iam-local
```
## Step 5: Deploy Service
> **Note on `host.docker.internal`**: On macOS, for a K8s pod to connect to PostgreSQL running on the host machine (or another container via port mapping), we use `host.docker.internal`.
### 5.1 Using Automated Script
### 5.2 ConfigMap
The `iam-service-configmap.yaml` file typically contains non-sensitive variables like `NODE_ENV`, `LOG_LEVEL`.
```bash
cd deployments/local/kubernetes
# Run deployment script
./deploy.sh
# Script will:
# 1. Create namespace
# 2. Create secrets
# 3. Apply ConfigMap
# 4. Build Docker image
# 5. Deploy service
# EN: Apply ConfigMap
# VI: Apply ConfigMap
kubectl apply -f iam-service-configmap.yaml -n iam-local
```
### 5.2 Manual Deployment
## 6. Deploy Service
Now we will deploy the main resources.
```bash
# Apply ConfigMap
kubectl apply -f iam-service-configmap.yaml
# EN: Apply Deployment manifest
# VI: Apply file Deployment manifest
kubectl apply -f iam-service-deployment.yaml -n iam-local
# Apply Deployment
kubectl apply -f iam-service-deployment.yaml
# Apply Service
kubectl apply -f iam-service-service.yaml
# EN: Apply Service manifest (LoadBalancer/NodePort)
# VI: Apply file Service manifest
kubectl apply -f iam-service-service.yaml -n iam-local
```
## Step 6: Verify Deployment
## 7. Verify & Debug
### 6.1 Check Pod Status
After deployment, ensure the Pod is stable (Running).
### 7.1 Check Pods
```bash
# View pods
# EN: Get all pods in the namespace
# VI: Lấy danh sách pod trong namespace
kubectl get pods -n iam-local
# Expected output:
# Expected Output:
# NAME READY STATUS RESTARTS AGE
# iam-service-68994fdc79-gh2mj 1/1 Running 0 2m
# iam-service-68994fdc79-gh2mj 1/1 Running 0 30s
```
### 6.2 Check Logs
### 7.2 View Detailed Logs
If Status is not `Running` (e.g., `CrashLoopBackOff` or `ImagePullBackOff`), check logs:
```bash
# View logs
# EN: Stream logs from the pod
# VI: Xem logs thời gian thực từ pod
kubectl logs -f -n iam-local -l app=iam-service
# Successful logs:
# [iam-service] Database connected successfully
# [iam-service] Service started on port 5001
# EN: Describe pod to see events (pull error, mounts, scheduling)
# VI: Xem chi tiết pod để check events (lỗi pull, mount, scheduling)
kubectl describe pod -n iam-local -l app=iam-service
```
### 6.3 Check Service
### 7.3 Common Errors
1. **ImagePullBackOff**:
- **Reason**: K8s cannot find `iam-service:local` image.
- **Fix**: Ensure `imagePullPolicy: IfNotPresent` or `Never` in local deployment yaml. If using Kind, remember to run `kind load`.
2. **CrashLoopBackOff**:
- **Reason**: Runtime error, usually unable to connect to Database.
- **Fix**: Check `DATABASE_URL` in Secret. Ensure Postgres is running and accessible from K8s (use `host.docker.internal`).
3. **Pending Service**:
- **Reason**: `LoadBalancer` type on local sometimes hangs pending IP.
- **Fix**: Not a problem, we can use `port-forward` or access via `localhost`.
## 8. Test Service Access
To access the service from your local machine, the safest way is `port-forward`.
```bash
# View services
kubectl get svc -n iam-local
# Output:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# iam-service LoadBalancer 10.96.187.160 <pending> 80:30577/TCP
```
**Note**: `EXTERNAL-IP` will be `<pending>` because local cluster doesn't have a cloud load balancer.
## Step 7: Test Service
### 7.1 Port Forward
```bash
# Forward port to access service
# EN: Port forward from local port 5002 to service port 80
# VI: Port forward từ cổng local 5002 tới cổng 80 của service
kubectl port-forward svc/iam-service 5002:80 -n iam-local
# Service will be available at http://localhost:5002
# Terminal will hang and show: Forwarding from 127.0.0.1:5002 -> 8000
```
### 7.2 Test Health Endpoints
Open another terminal and test:
```bash
# Test liveness probe
# EN: Test Health Check
# VI: Test Health Check
curl http://localhost:5002/health/live
# Response: {"status":"ok", ...}
# Response:
# {
# "success": true,
# "data": {"status": "live"},
# "timestamp": "2026-01-04T06:04:03.425Z"
# }
# Test readiness probe
curl http://localhost:5002/health/ready
# Test API docs
# EN: View Swagger/OpenAPI docs (if enabled)
# VI: Xem tài liệu Swagger/OpenAPI (nếu bật)
open http://localhost:5002/api-docs
```
## Troubleshooting
## 9. Cleanup
### Issue 1: ImagePullBackOff
**Symptoms**:
```bash
kubectl get pods -n iam-local
# NAME READY STATUS RESTARTS AGE
# iam-service-6b8fbb574d-hn27z 0/1 ImagePullBackOff 0 2m
```
**Cause**: kind cluster cannot find image `iam-service:local`
**Solution**:
```bash
# Load image into kind cluster
kind load docker-image iam-service:local --name desktop
# Restart deployment
kubectl rollout restart deployment/iam-service -n iam-local
```
### Issue 2: CrashLoopBackOff
**Symptoms**:
```bash
kubectl get pods -n iam-local
# NAME READY STATUS RESTARTS AGE
# iam-service-xxx 0/1 CrashLoopBackOff 5 5m
```
**Cause**: Service crashes on startup
**Debug**:
```bash
# View logs
kubectl logs -n iam-local -l app=iam-service --tail=50
# Describe pod
kubectl describe pod -n iam-local -l app=iam-service
```
**Common solutions**:
- Check DATABASE_URL in secrets
- Verify Prisma migrations have run
- Check environment variables in ConfigMap
### Issue 3: Database Connection Failed
**Symptoms**: Logs show `Database connection error`
**Solution**:
```bash
# Verify DATABASE_URL
kubectl get secret iam-service-secrets -n iam-local -o jsonpath='{.data.DATABASE_URL}' | base64 -d
# Test connection from pod
kubectl exec -it -n iam-local deployment/iam-service -- sh
# Inside pod:
# npx prisma db push
```
### Issue 4: Redis Connection Errors
**Symptoms**: Logs show `Redis connection error`
**Cause**: Redis not deployed in cluster
**Solution** (optional - only if Redis needed):
```bash
# Deploy Redis
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: iam-local
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: iam-local
spec:
selector:
app: redis
ports:
- port: 6379
EOF
# Update ConfigMap with REDIS_HOST=redis
kubectl edit configmap iam-service-config -n iam-local
# Restart deployment
kubectl rollout restart deployment/iam-service -n iam-local
```
## Debugging Commands
When done, delete resources to free up capacity.
```bash
# View all resources
kubectl get all -n iam-local
# Describe deployment
kubectl describe deployment iam-service -n iam-local
# Describe pod
kubectl describe pod -n iam-local -l app=iam-service
# View events
kubectl get events -n iam-local --sort-by='.lastTimestamp'
# Exec into pod
kubectl exec -it -n iam-local deployment/iam-service -- sh
# View logs realtime
kubectl logs -f -n iam-local -l app=iam-service
# View logs from previous container (if pod restarted)
kubectl logs -n iam-local -l app=iam-service --previous
```
## Cleanup
```bash
# Delete deployment
kubectl delete -f iam-service-deployment.yaml
kubectl delete -f iam-service-service.yaml
kubectl delete -f iam-service-configmap.yaml
# Delete secrets
kubectl delete secret iam-service-secrets -n iam-local
# Delete namespace (deletes everything)
# EN: Delete the namespace (removes all resources within)
# VI: Xóa namespace (xóa tất cả resource bên trong)
kubectl delete namespace iam-local
```
## Next Steps
1. **Deploy Redis** (optional): To enable caching and rate limiting
2. **Setup Ingress**: To expose service externally
3. **Configure HPA**: Horizontal Pod Autoscaler for auto-scaling
4. **Add Monitoring**: Prometheus + Grafana
5. **Setup CI/CD**: Automated deployment on code changes
## Resources
## References
- [Kubernetes Documentation](https://kubernetes.io/docs/)
- [Docker Desktop Kubernetes](https://docs.docker.com/desktop/kubernetes/)
- [kind Documentation](https://kind.sigs.k8s.io/)
- [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)
- [Local Kubernetes README](../../../deployments/local/kubernetes/README.md)
- [Docker Desktop for Mac](https://docs.docker.com/desktop/mac/networking/)
- [Prisma Deployment Guide](https://www.prisma.io/docs/guides/deployment/deployment-guides/deploying-to-kubernetes)

View File

@@ -1,494 +1,250 @@
# Local Development Guide
Comprehensive guide for running and developing the project locally with real-time hot reload.
> **EN**: Local Development Guide
>
> **VI**: Hướng dẫn phát triển cục bộ
## System Requirements
**Last Updated**: 2026-01-05
**Difficulty**: Intermediate
**Setup Time**: 15-30 minutes
- **Node.js**: >= 20.0.0
- **PNPM**: >= 8.0.0
- **Docker & Docker Compose**: Latest version
- **Git**: For cloning repository
- **Neon Account**: https://neon.tech (for database)
## Workflow
## Quick Start (Recommended)
```mermaid
graph TD
Start([Start]) --> Prerequisites[1. System Prerequisites]
Prerequisites --> Clone[2. Clone & Install]
Clone --> Env[3. Configure Environment<br/>(Shared & Service-Specific)]
Env --> DB[4. Setup Database<br/>(Migrate & Seed)]
DB --> Run[5. Run Project<br/>(Native/Docker/Hybrid)]
Run --> Dev[6. Development Loop<br/>(Watch Mode)]
Dev --> Test[7. Testing & Verify]
Test --> End([Complete])
1. **Clone Repository**:
```bash
git clone <repository-url>
cd Base
```
subgraph "Run Modes"
Run --> Mode1[Mode 1: Native (Fastest)]
Run --> Mode2[Mode 2: Hybrid (Flexible)]
Run --> Mode3[Mode 3: Full Docker (Production-like)]
end
2. **Run Initialization Script**:
```bash
./scripts/setup/init-project.sh
```
This script will install dependencies, generate clients, and setup environment files.
## Manual Setup
### 1. Clone Repository
```bash
git clone <repository-url>
cd Base
style Start fill:#d4edda,stroke:#28a745,stroke-width:2px
style End fill:#d4edda,stroke:#28a745,stroke-width:2px
style Env fill:#fff3cd,stroke:#ffc107
style DB fill:#fff3cd,stroke:#ffc107
style Run fill:#cce5ff,stroke:#007bff
```
### 2. Install Dependencies
## Overview
This guide provides a detailed process for setting up a development environment for the GoodGo Microservices ecosystem. You will learn how to run services, set up databases, and establish an efficient workflow with hot-reload.
## 1. Prerequisites
Before starting, ensure your machine has the following tools installed:
- **Node.js**: Latest LTS version (v20+).
- **PNPM**: Main project package manager (`npm install -g pnpm`).
- **Docker Desktop**: Required for running infrastructure services (Redis, Local Database).
- **Git**: For source code management.
- **Neon Account** (Optional): If using Neon Database on cloud (recommended for dev).
## 2. Initial Setup
### 2.1 Clone and Install Dependencies
```bash
# EN: Clone the repository
# VI: Clone repository về máy
git clone <repository-url>
cd Base
# EN: Install dependencies using pnpm
# VI: Cài đặt các thư viện phụ thuộc bằng pnpm
pnpm install
```
### 3. Setup Database (Neon)
### 2.2 Quick Init Script (Recommended)
Create environment configuration file:
The project includes an automation script for basic initialization:
```bash
# EN: Run initialization script
# VI: Chạy script khởi tạo
./scripts/setup/init-project.sh
```
> This script will:
> - Install dependencies.
> - Copy example environment files (`.env.example` -> `.env`).
> - Generate Prisma client.
## 3. Environment Configuration
The project uses a **Hybrid Environment** strategy to optimize configuration management:
### 3.1 Shared Configuration
File: `deployments/local/.env.local`
Contains variables shared across the entire system (JWT, Redis, Logging).
```bash
# EN: Create shared env file from example
# VI: Tạo file môi trường chung từ file mẫu
cp deployments/local/env.local.example deployments/local/.env.local
```
Edit `.env.local` file and add your Neon DATABASE_URL:
### 3.2 Service-Specific Configuration
Each service (e.g., `iam-service`) needs its own `.env.local` file containing specific details like Database URL and Port.
```bash
# Get connection string from Neon Console: https://console.neon.tech
DATABASE_URL=postgresql://user:password@ep-xxx.region.neon.tech/dbname?sslmode=require&pgbouncer=true
# JWT Secrets (can keep defaults for dev)
JWT_SECRET=dev-jwt-secret-change-in-production
JWT_REFRESH_SECRET=dev-refresh-secret-change-in-production
# EN: Create service-specific env file
# VI: Tạo file môi trường riêng cho service
cp services/iam-service/env.local.example services/iam-service/.env.local
```
**Note**: See [Neon Database Guide](neon-database.md) for detailed setup instructions.
**Key contents to check in `services/iam-service/.env.local`**:
### 4. Run Database Migrations
```properties
# Database URL (Use Neon Tech or Local Postgres)
DATABASE_URL=postgresql://user:password@host:5432/db_name?sslmode=require
# Service Port (Must be unique per service)
PORT=5001
# Service Name
SERVICE_NAME=iam-service
# Redis Host (localhost for Native Dev, redis for Docker Dev)
REDIS_HOST=localhost
```
## 4. Setup Database
After configuring `DATABASE_URL`, you need to sync the schema and seed initial data.
```bash
# EN: Run migrations for iam-service
# VI: Chạy migration cho iam-service
./scripts/db/migrate.sh iam-service dev
```
### 5. Seed Database (Optional)
```bash
# EN: Seed initial data (optional)
# VI: Tạo dữ liệu mẫu (tùy chọn)
./scripts/db/seed.sh iam-service
```
## Ways to Run the Project
## 5. Run Modes
### Method 1: Run All Services (Recommended)
You can run the project in 3 ways depending on your needs:
Best for full-stack development or testing the entire system:
### Mode 1: Native Development (Recommended for Backend Dev)
Run directly on the host machine. Fastest speed, fastest hot-reload.
1. **Start Infrastructure**:
```bash
# EN: Start Redis and Traefik in Docker background
# VI: Khởi động Redis và Traefik chạy ngầm bằng Docker
cd deployments/local
docker-compose up -d redis traefik
cd ../..
```
2. **Run Service**:
```bash
# EN: Start iam-service in watch mode
# VI: Chạy iam-service ở chế độ watch
pnpm --filter @goodgo/iam-service dev
```
### Mode 2: Hybrid Development (Flexible)
Use when you need to run multiple auxiliary services in Docker but want to dev the main service directly.
```bash
./scripts/dev/start-all.sh
```
# EN: Start dependent services in Docker
# VI: Chạy các service phụ thuộc trong Docker
docker-compose -f deployments/local/docker-compose.yml up -d user-service payment-service
This script will:
1. Check if Docker is running
2. Verify DATABASE_URL is configured
3. Start infrastructure (Redis, Traefik)
4. Start all services with hot reload
**Or run manually:**
```bash
# Step 1: Start infrastructure
cd deployments/local
docker-compose up -d
cd ../..
# Step 2: Start all services
pnpm dev
```
### Method 2: Run Specific Service
Best when working on a single service:
```bash
# Using script
./scripts/dev/start-service.sh iam-service
# Or run directly
cd services/iam-service
pnpm dev
```
### Method 3: Run Service Groups
```bash
# Run only backend services
pnpm --filter "./services/*" dev
# Run only frontend apps
pnpm --filter "./apps/*" dev
# Run specific service
# EN: Run the service you are working on natively
# VI: Chạy service bạn đang làm việc trực tiếp trên máy
pnpm --filter @goodgo/iam-service dev
```
### Method 4: Run With Docker Compose (Full Stack)
### Mode 3: Full Docker (Production Simulation)
Run the entire system in Docker. Good for Integration Testing but no hot-reload.
```bash
# EN: Start everything with Docker Compose
# VI: Chạy tất cả bằng Docker Compose
cd deployments/local
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
```
## Access Points
## 6. Access & Verification
When services are running, you can access:
After startup, you can access the following endpoints:
| Service | URL | Description |
|---------|-----|-------------|
| **API Gateway** | http://localhost/api/v1 | Main entry point via Traefik |
| **IAM Service** | http://localhost:5001 | Direct IAM service access |
| **Auth API** | http://localhost/api/v1/auth | Auth API via gateway (backward compatible) |
| **Identity API** | http://localhost/api/v1/identity | Identity management API |
| **Access API** | http://localhost/api/v1/access | Access management API |
| **Governance API** | http://localhost/api/v1/governance | Governance API |
| **Web Admin** | http://admin.localhost or http://localhost:3000 | Admin dashboard |
| **Web Client** | http://localhost or http://localhost:3001 | Client web app |
| **Traefik Dashboard** | http://localhost:8080 | View routing and services |
| **API Gateway** | `http://localhost/api/v1` | Main entry point via Traefik |
| **IAM Service** | `http://localhost:5001` | Direct service access |
| **Health Check** | `http://localhost:5001/health` | Service status check |
| **Metrics** | `http://localhost:5001/metrics` | Prometheus metrics |
| **API Docs** | `http://localhost:5001/api-docs` | Swagger UI |
## Hot Reload & Live Development
### Backend Services (TypeScript)
Backend services use `tsx watch` or `nodemon` for automatic restart on code changes:
### Health Check Validation
```bash
# In services/iam-service/package.json
"scripts": {
"dev": "tsx watch src/main.ts"
}
# EN: Check liveness
# VI: Kiểm tra liveness
curl http://localhost:5001/health/live
# EN: Check readiness
# VI: Kiểm tra readiness
curl http://localhost:5001/health/ready
```
**When you change:**
- `.ts` files → Service auto-restarts (1-2 seconds)
- `.env` files → Manual restart required
- `prisma/schema.prisma` → Need to run migration
## 7. Troubleshooting
### Frontend Apps (Next.js)
### Port Already In Use
Frontend apps use Next.js Fast Refresh:
**Error**: `Error: listen EADDRINUSE: address already in use :::5001`
**Solution**:
```bash
# In apps/web-admin/package.json
"scripts": {
"dev": "next dev"
}
```
# EN: Find process using port 5001
# VI: Tìm process đang chiếm port 5001
lsof -i :5001
**When you change:**
- React components → Updates instantly (no page reload)
- CSS/Tailwind → Updates instantly
- `next.config.js` → Restart required
### Shared Packages
When changing shared packages (in `packages/`):
```bash
# Packages auto-rebuild with Turbo watch mode
pnpm --filter @goodgo/logger dev
```
## Real-World Development Workflow
### Setup 3 Terminals
**Terminal 1: Run Services**
```bash
./scripts/dev/start-all.sh
# Or: pnpm dev
```
**Terminal 2: View Logs**
```bash
# View specific service logs
./scripts/dev/logs.sh iam-service
# Or view Docker logs
docker logs -f redis-cache-local
docker logs -f traefik-local
```
**Terminal 3: Development Tasks**
```bash
# Run tests
pnpm --filter @goodgo/iam-service test --watch
# Run migrations
./scripts/db/migrate.sh iam-service dev
# Format code
pnpm format
```
## Health Checks
### Health Endpoints
```bash
# Check API Gateway
curl http://localhost/api/v1/health
# Check Auth Service directly
curl http://localhost:5001/health
# Check Redis
docker exec redis-cache-local redis-cli ping
```
### Traefik Dashboard
Access http://localhost:8080 to view:
- All active routes
- Registered services
- Service health status
## Database Development
### Schema Changes
```bash
# 1. Edit prisma/schema.prisma
# 2. Create and apply migration
cd services/iam-service
pnpm prisma migrate dev --name add_new_field
# 3. Prisma Client auto-regenerates
```
### Reset Database (Development Only!)
```bash
cd services/iam-service
pnpm prisma migrate reset
```
### View Database
```bash
# Open Prisma Studio
cd services/iam-service
pnpm prisma studio
# Access: http://localhost:5555
```
## Debugging
### VS Code Debugging
Create `.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Auth Service",
"type": "node",
"request": "launch",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["--filter", "@goodgo/iam-service", "dev"],
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
}
]
}
```
### View Detailed Logs
```bash
# Service logs
./scripts/dev/logs.sh iam-service
# Docker logs
docker logs -f iam-service-local
docker logs -f redis-cache-local
docker logs -f traefik-local
# All logs
docker-compose -f deployments/local/docker-compose.yml logs -f
```
## Troubleshooting
### Port Already in Use
```bash
# Find process using port
lsof -i :5001 # Auth service
lsof -i :3000 # Web admin
lsof -i :6379 # Redis
lsof -i :80 # Traefik
# Kill process
# EN: Kill the process
# VI: Tắt process đó
kill -9 <PID>
```
### Docker Not Running
### Database Connection Error
```bash
# Check Docker
docker info
**Error**: `P1001: Can't reach database server`
# Start Docker Desktop (macOS)
open -a Docker
# Restart Docker services
docker-compose -f deployments/local/docker-compose.yml restart
```
### Database Connection Failed
```bash
# Check DATABASE_URL
cat deployments/local/.env.local | grep DATABASE_URL
# Test connection
cd services/iam-service
pnpm prisma db pull
```
**Solution**:
- Re-check `DATABASE_URL` variable.
- If using local Postgres Docker, ensure container is running (`docker ps`).
- If using Neon, check internet connection.
### Module Not Found
**Error**: Cannot find internal packages (e.g., `@goodgo/logger`).
**Solution**:
```bash
# Cleanup and reinstall
./scripts/utils/cleanup.sh
pnpm install
# Or just cleanup node_modules
rm -rf node_modules
rm -rf services/*/node_modules
rm -rf apps/*/node_modules
rm -rf packages/*/node_modules
# EN: Re-install dependencies and build packages
# VI: Cài lại dependencies và build lại packages
pnpm install
pnpm build
```
### Hot Reload Not Working
## References
```bash
# Restart service
# Press Ctrl+C to stop, then:
pnpm dev
# Or restart Docker container
docker-compose -f deployments/local/docker-compose.yml restart iam-service
```
## Tips & Best Practices
### 1. Use Turbo Cache
Turbo cache speeds up builds:
```bash
# First run will be slow
pnpm dev
# Subsequent runs will be faster thanks to cache
# Cache stored in node_modules/.cache/turbo
```
### 2. Dev Selective Services
No need to run everything if working on one service:
```bash
# Run only iam-service
pnpm --filter @goodgo/iam-service dev
# Run iam-service with dependencies
pnpm --filter @goodgo/iam-service... dev
```
### 3. Watch Tests
```bash
# Run tests automatically on code changes
pnpm --filter @goodgo/iam-service test --watch
```
### 4. Auto-format Code
Install Prettier extension in VS Code and enable format on save.
### 5. Use Git Hooks
```bash
# Pre-commit hook will auto-format and lint
git commit -m "feat: add new feature"
```
## Environment Variables
### Development (.env.local)
```bash
# Database
DATABASE_URL=postgresql://user:pass@ep-xxx.neon.tech/db?sslmode=require&pgbouncer=true
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
# JWT
JWT_SECRET=dev-jwt-secret
JWT_REFRESH_SECRET=dev-refresh-secret
# Service
NODE_ENV=development
LOG_LEVEL=debug
```
### Override for Specific Service
Create `.env.local` file in service directory:
```bash
# services/iam-service/.env.local
PORT=5001
LOG_LEVEL=debug
```
## Useful Commands
```bash
# Development
pnpm dev # Run all services
pnpm build # Build all
pnpm test # Test all
pnpm lint # Lint all
pnpm format # Format code
# Cleanup
pnpm clean # Remove build artifacts
./scripts/utils/cleanup.sh # Full cleanup
# Database
./scripts/db/migrate.sh iam-service dev # Migration
./scripts/db/seed.sh iam-service # Seed data
./scripts/db/backup.sh iam-service # Backup
# Docker
docker-compose -f deployments/local/docker-compose.yml up -d # Start
docker-compose -f deployments/local/docker-compose.yml down # Stop
docker-compose -f deployments/local/docker-compose.yml logs -f # Logs
docker-compose -f deployments/local/docker-compose.yml restart # Restart
```
## Additional Resources
- [Getting Started](getting-started.md) - Initial setup
- [Development Guide](development.md) - Development workflow
- [Neon Database Guide](neon-database.md) - Database guide
- [Troubleshooting](troubleshooting.md) - Problem solving
- [Kubernetes Guide](kubernetes-local.md) - Deploy to Local K8s.
- [Project Architecture](../../docs/en/ARCHITECTURE.en.md) - System architecture overview.

View File

@@ -1,396 +1,273 @@
# Hướng Dẫn Deploy Kubernetes Local
**Cập nhật**: 2026-01-04
**Độ khó**: Intermediate
> **EN**: Local Kubernetes Deployment Guide
>
> **VI**: Hướng dẫn triển khai Kubernetes cục bộ
**Cập nhật**: 2026-01-05
**Độ khó**: Trung bình (Intermediate)
**Thời gian**: 30-45 phút
## Tổng Quan
## Workflow / Quy Trình
Hướng dẫn này mô tả cách deploy IAM Service lên local Kubernetes cluster sử dụng Docker Desktop trên macOS.
```mermaid
graph TD
Start([Bắt đầu / Start]) --> EnvPrep[1. Chuẩn bị Môi trường<br/>Environment Prep]
EnvPrep --> BuildImg[2. Build Docker Image]
BuildImg --> LoadImg[3. Load Image vào Cluster<br/>(Kind/Docker Desktop)]
LoadImg --> Secrets[4. Cấu hình Secrets<br/>& Environment]
Secrets --> Deploy[5. Deploy Service<br/>(K8s Manifests)]
Deploy --> Verify[6. Kiểm tra & Verify]
Verify --> Test[7. Test Service<br/>(Port Forward & Curl)]
Test --> End([Hoàn tất / Complete])
## Yêu Cầu
subgraph "Chi tiết Deploy / Deployment Details"
Deploy --> |Apply| ConfigMap
Deploy --> |Apply| Deployment
Deploy --> |Apply| Service
end
style Start fill:#d4edda,stroke:#28a745,stroke-width:2px
style End fill:#d4edda,stroke:#28a745,stroke-width:2px
style EnvPrep fill:#e2e3e5,stroke:#6c757d
style BuildImg fill:#fff3cd,stroke:#ffc107
style LoadImg fill:#fff3cd,stroke:#ffc107
style Secrets fill:#f8d7da,stroke:#dc3545
style Deploy fill:#cce5ff,stroke:#007bff
style Verify fill:#cce5ff,stroke:#007bff
```
### Phần Mềm
- Docker Desktop 4.0+ với Kubernetes enabled
- kubectl CLI
- kind CLI (để load images vào cluster)
- pnpm 8+
## Tổng Quan / Overview
### Kiến Thức
- Hiểu cơ bản về Kubernetes (Pods, Deployments, Services)
- Quen thuộc với Docker và containerization
- Biết cách sử dụng terminal/command line
Hướng dẫn này mô tả chi tiết cách deploy IAM Service (hoặc bất kỳ microservice nào trong hệ sinh thái GoodGo) lên local Kubernetes cluster sử dụng Docker Desktop trên macOS.
## Bước 1: Chuẩn Bị Môi Trường
> **Lưu ý quan trọng**: Hướng dẫn này giả định bạn đang sử dụng **Docker Desktop** với **Kubernetes enabled**. Nếu bạn sử dụng Minikube hoặc Kind thuần, các bước có thể hơi khác một chút (đặc biệt là phần load image).
### 1.1 Enable Kubernetes trong Docker Desktop
## 1. Yêu Cầu / Prerequisites
1. Mở **Docker Desktop**
2. Vào **Settings → Kubernetes**
3. Check **Enable Kubernetes**
4. Chọn cluster provisioning:
- **kind** (recommended cho development)
- hoặc **kubeadm**
5. Click **Apply & Restart**
6. Đợi 2-3 phút để Kubernetes khởi động
### Phần Mềm / Software
- **Docker Desktop 4.0+**: [Download Link](https://www.docker.com/products/docker-desktop/)
- Kubernetes phải được enable trong settings.
- **kubectl CLI**: Công cụ dòng lệnh để tương tác với K8s.
```bash
brew install kubectl
```
- **kind CLI**: Cần thiết để load images vào cluster nếu dùng Kind backend (mặc định cho dev).
```bash
brew install kind
```
- **pnpm 8+**: Package manager của dự án.
```bash
npm install -g pnpm
```
### 1.2 Verify Kubernetes
### Kiến Thức / Knowledge
- Hiểu cơ bản về các khái niệm Kubernetes: **Pod**, **Deployment**, **Service**, **Secret**, **ConfigMap**.
- Quen thuộc với các lệnh Docker cơ bản (`docker build`, `docker images`).
- Biết cách điều hướng và chạy lệnh trong Terminal.
## 2. Chuẩn Bị Môi Trường / Environment Preparation
### 2.1 Enable Kubernetes trong Docker Desktop
1. Mở **Docker Desktop**.
2. Nhấn vào biểu tượng **Settings (⚙️)**.
3. Chọn tab **Kubernetes**.
4. Check vào ô **Enable Kubernetes**.
5. Chọn **Show system containers (advanced)** để dễ debug (tùy chọn).
6. Nhấn **Apply & Restart**.
7. Đợi 2-3 phút cho đến khi icon Kubernetes ở góc dưới chuyển sang màu xanh lá.
### 2.2 Verify Kubernetes Connection
Kiểm tra xem `kubectl` đã kết nối đúng context chưa:
```bash
# Check kubectl context
# EN: Check current context
# VI: Kiểm tra context hiện tại
kubectl config current-context
# Output: docker-desktop
# Output mong đợi: docker-desktop
# Check nodes
# EN: List all nodes in the cluster
# VI: Liệt kê các node trong cluster
kubectl get nodes
# Output: docker-desktop Ready control-plane ...
# Check kind cluster name (nếu dùng kind)
kind get clusters
# Output: desktop
# Output mong đợi:
# NAME STATUS ROLES AGE VERSION
# docker-desktop Ready control-plane 10m v1.29.1
```
### 1.3 Install kind CLI
## 3. Build Docker Image
Chúng ta cần build image của service trước khi deploy. Ở đây lấy ví dụ là `iam-service`.
```bash
# Install kind
brew install kind
# Verify installation
kind version
```
## Bước 2: Build Docker Image
```bash
# Di chuyển đến thư mục deployments
# EN: Navigate to the kubernetes deployment directory
# VI: Di chuyển đến thư mục deployments/local/kubernetes
cd deployments/local/kubernetes
# Build image (script tự động build)
# EN: Build the Docker image from the root context
# VI: Build Docker image từ root context
# Lưu ý: -f trỏ đến Dockerfile của service, context là root (../../..)
docker build -t iam-service:local -f ../../../services/iam-service/Dockerfile ../../..
# Verify image
# EN: Verify the image was built successfully
# VI: Kiểm tra image đã build thành công chưa
docker images | grep iam-service
# Output: iam-service:local ... 1.67GB
# Output mong đợi:
# iam-service local [IMAGE_ID] [SIZE] [CREATED]
```
## Bước 3: Load Image vào Kubernetes Cluster
## 4. Load Image vào Cluster
**⚠️ Quan Trọng**: Docker Desktop Kubernetes với kind backend **không tự đng share images** với Docker Desktop. Bạn phải load image vào cluster:
**⚠️ QUAN TRỌNG / IMPORTANT**: Docker Desktop có thể sử dụng các backend khác nhau. Nếu bạn đang chạy Kubernetes trong Docker Desktop, đôi khi nó không nhìn thấy image local ngay lập tức nếu sử dụng `kind` node dưới nền.
Nếu bạn dùng **Kind** (Kubernetes in Docker) riêng biệt hoặc cấu hình Docker Desktop đặc biệt, bạn cần load image:
```bash
# Load image o kind cluster
# EN: Load image into kind cluster (if using kind explicitly)
# VI: Load image vào kind cluster (nếu dùng kind rõ ràng)
kind load docker-image iam-service:local --name desktop
# Đợi quá trình hoàn tất (có thể mất 1-2 phút)
# EN: Validating image presence (optional, hard with Docker Desktop K8s directly)
# VI: Kiểm tra sự tồn tại của image (tùy chọn)
```
**Lưu ý**: Nếu dùng kubeadm thay vì kind, bạn có thể skip bước này vì kubeadm share images tốt hơn.
> **Mẹo**: Với Docker Desktop mặc định, việc build image local (`docker build ...`) thường tự động khả dụng cho K8s cluster của Docker Desktop. Bước load này chủ yếu dành cho ai dùng `kind` CLI để tạo cluster riêng.
## Bước 4: Cấu Hình Secrets
## 5. Cấu Hình Secrets & ConfigMap
### 4.1 Chuẩn Bị Environment Variables
Môi trường Kubernetes cần các biến môi trường nhạy cảm (Secrets) và cấu hình chung (ConfigMap).
Tạo file `.env.k8s` với các biến sau:
### 5.1 Tạo Secrets (Thủ công)
Bạn có thể chạy script hoặc lệnh sau để tạo secrets an toàn.
```bash
# Database
DATABASE_URL=postgresql://user:password@host:5432/database?sslmode=require
# JWT Secrets (PHẢI thay đổi trong production!)
JWT_SECRET=your-strong-jwt-secret-min-32-chars
JWT_REFRESH_SECRET=your-strong-refresh-secret-min-32-chars
JWT_ID_SECRET=your-strong-id-secret-min-32-chars
# Encryption (optional)
ENCRYPTION_KEY=your-32-char-encryption-key-here
```
### 4.2 Tạo Kubernetes Secrets
Script `deploy.sh` sẽ tự động tạo secrets, hoặc bạn có thể tạo thủ công:
```bash
# Tạo namespace
# EN: Create a dedicated namespace for local testing
# VI: Tạo namespace riêng cho local testing
kubectl create namespace iam-local
# Tạo secrets
# EN: Generate random secrets and store in Kubernetes
# VI: Tạo secrets ngẫu nhiên và lưu vào Kubernetes
kubectl create secret generic iam-service-secrets \
--from-literal=DATABASE_URL="postgresql://..." \
--from-literal=DATABASE_URL="postgresql://user:password@host.docker.internal:5432/iam_db?schema=public" \
--from-literal=JWT_SECRET="$(openssl rand -base64 32)" \
--from-literal=JWT_REFRESH_SECRET="$(openssl rand -base64 32)" \
--from-literal=JWT_ID_SECRET="$(openssl rand -base64 32)" \
--from-literal=ENCRYPTION_KEY="$(openssl rand -base64 32)" \
-n iam-local
# Verify secrets
# EN: Verify secrets creation
# VI: Kiểm tra secrets đã tạo
kubectl get secrets -n iam-local
```
## Bước 5: Deploy Service
> **Lưu ý về `host.docker.internal`**: Trên macOS, để pod trong K8s kết nối được với PostgreSQL chạy trên máy host (hoặc container khác qua port mapping), ta dùng `host.docker.internal`.
### 5.1 Sử Dụng Script Tự Động
### 5.2 ConfigMap
File `iam-service-configmap.yaml` thường chứa các biến không nhạy cảm như `NODE_ENV`, `LOG_LEVEL`.
```bash
cd deployments/local/kubernetes
# Run deployment script
./deploy.sh
# Script sẽ:
# 1. Tạo namespace
# 2. Tạo secrets
# 3. Apply ConfigMap
# 4. Build Docker image
# 5. Deploy service
# EN: Apply ConfigMap
# VI: Apply ConfigMap
kubectl apply -f iam-service-configmap.yaml -n iam-local
```
### 5.2 Deploy Thủ Công
## 6. Deploy Service
Bây giờ chúng ta sẽ deploy các resource chính.
```bash
# Apply ConfigMap
kubectl apply -f iam-service-configmap.yaml
# EN: Apply Deployment manifest
# VI: Apply file Deployment manifest
kubectl apply -f iam-service-deployment.yaml -n iam-local
# Apply Deployment
kubectl apply -f iam-service-deployment.yaml
# Apply Service
kubectl apply -f iam-service-service.yaml
# EN: Apply Service manifest (LoadBalancer/NodePort)
# VI: Apply file Service manifest
kubectl apply -f iam-service-service.yaml -n iam-local
```
## Bước 6: Verify Deployment
## 7. Verify & Debug / Kiểm Tra & Gỡ Lỗi
### 6.1 Check Pod Status
Sau khi deploy, cần đảm bảo Pod đang chạy ổn định (Running).
### 7.1 Kiểm tra Pods
```bash
# Xem pods
# EN: Get all pods in the namespace
# VI: Lấy danh sách pod trong namespace
kubectl get pods -n iam-local
# Output mong đợi:
# NAME READY STATUS RESTARTS AGE
# iam-service-68994fdc79-gh2mj 1/1 Running 0 2m
# iam-service-68994fdc79-gh2mj 1/1 Running 0 30s
```
### 6.2 Check Logs
### 7.2 Xem Logs Chi Tiết
Nếu Status không phải `Running` (ví dụ `CrashLoopBackOff` hoặc `ImagePullBackOff`), hãy xem logs:
```bash
# Xem logs
# EN: Stream logs from the pod
# VI: Xem logs thời gian thực từ pod
kubectl logs -f -n iam-local -l app=iam-service
# Logs thành công:
# [iam-service] Database connected successfully
# [iam-service] Service started on port 5001
# EN: Describe pod to see events (pull error, mounts, scheduling)
# VI: Xem chi tiết pod để check events (lỗi pull, mount, scheduling)
kubectl describe pod -n iam-local -l app=iam-service
```
### 6.3 Check Service
### 7.3 Common Errors / Lỗi Thường Gặp
1. **ImagePullBackOff**:
- **Lý do**: K8s không tìm thấy image `iam-service:local`.
- **Fix**: Đảm bảo `imagePullPolicy: IfNotPresent` hoặc `Never` trong file yaml deployment local. Nếu dùng Kind, nhớ chạy lệnh `kind load`.
2. **CrashLoopBackOff**:
- **Lý do**: Lỗi runtime, thường là không kết nối được Database.
- **Fix**: Check biến `DATABASE_URL` trong Secret. Đảm bảo Postgres đang chạy và accessible từ K8s (dùng `host.docker.internal`).
3. **Pending Service**:
- **Lý do**: Type `LoadBalancer` trên local đôi khi mãi pending IP.
- **Fix**: Không sao cả, chúng ta có thể dùng `port-forward` hoặc truy cập qua `localhost`.
## 8. Test Service Access
Để truy cập service từ máy local, cách an toàn nhất là dùng `port-forward`.
```bash
# Xem services
kubectl get svc -n iam-local
# Output:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
# iam-service LoadBalancer 10.96.187.160 <pending> 80:30577/TCP
```
**Lưu ý**: `EXTERNAL-IP` sẽ là `<pending>` vì local cluster không có cloud load balancer.
## Bước 7: Test Service
### 7.1 Port Forward
```bash
# Forward port để access service
# EN: Port forward from local port 5002 to service port 80
# VI: Port forward từ cổng local 5002 tới cổng 80 của service
kubectl port-forward svc/iam-service 5002:80 -n iam-local
# Service sẽ available tại http://localhost:5002
# Terminal sẽ treo và hiện: Forwarding from 127.0.0.1:5002 -> 8000
```
### 7.2 Test Health Endpoints
Mở terminal khác và test:
```bash
# Test liveness probe
# EN: Test Health Check
# VI: Test Health Check
curl http://localhost:5002/health/live
# Response: {"status":"ok", ...}
# Response:
# {
# "success": true,
# "data": {"status": "live"},
# "timestamp": "2026-01-04T06:04:03.425Z"
# }
# Test readiness probe
curl http://localhost:5002/health/ready
# Test API docs
# EN: View Swagger/OpenAPI docs (if enabled)
# VI: Xem tài liệu Swagger/OpenAPI (nếu bật)
open http://localhost:5002/api-docs
```
## Troubleshooting
## 9. Cleanup / Dọn Dẹp
### Issue 1: ImagePullBackOff
**Triệu chứng**:
```bash
kubectl get pods -n iam-local
# NAME READY STATUS RESTARTS AGE
# iam-service-6b8fbb574d-hn27z 0/1 ImagePullBackOff 0 2m
```
**Nguyên nhân**: kind cluster không thể tìm thấy image `iam-service:local`
**Giải pháp**:
```bash
# Load image vào kind cluster
kind load docker-image iam-service:local --name desktop
# Restart deployment
kubectl rollout restart deployment/iam-service -n iam-local
```
### Issue 2: CrashLoopBackOff
**Triệu chứng**:
```bash
kubectl get pods -n iam-local
# NAME READY STATUS RESTARTS AGE
# iam-service-xxx 0/1 CrashLoopBackOff 5 5m
```
**Nguyên nhân**: Service crash khi start
**Debug**:
```bash
# Xem logs
kubectl logs -n iam-local -l app=iam-service --tail=50
# Describe pod
kubectl describe pod -n iam-local -l app=iam-service
```
**Giải pháp phổ biến**:
- Check DATABASE_URL trong secrets
- Verify Prisma migrations đã chạy
- Check environment variables trong ConfigMap
### Issue 3: Database Connection Failed
**Triệu chứng**: Logs hiển thị `Database connection error`
**Giải pháp**:
```bash
# Verify DATABASE_URL
kubectl get secret iam-service-secrets -n iam-local -o jsonpath='{.data.DATABASE_URL}' | base64 -d
# Test connection từ pod
kubectl exec -it -n iam-local deployment/iam-service -- sh
# Inside pod:
# npx prisma db push
```
### Issue 4: Redis Connection Errors
**Triệu chứng**: Logs hiển thị `Redis connection error`
**Nguyên nhân**: Redis chưa được deploy trong cluster
**Giải pháp** (optional - chỉ nếu cần Redis):
```bash
# Deploy Redis
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: iam-local
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: iam-local
spec:
selector:
app: redis
ports:
- port: 6379
EOF
# Update ConfigMap với REDIS_HOST=redis
kubectl edit configmap iam-service-config -n iam-local
# Restart deployment
kubectl rollout restart deployment/iam-service -n iam-local
```
## Debugging Commands
Khi hoàn tất, hãy xóa resources để giải phóng tài nguyên.
```bash
# Xem tất cả resources
kubectl get all -n iam-local
# Describe deployment
kubectl describe deployment iam-service -n iam-local
# Describe pod
kubectl describe pod -n iam-local -l app=iam-service
# Xem events
kubectl get events -n iam-local --sort-by='.lastTimestamp'
# Exec vào pod
kubectl exec -it -n iam-local deployment/iam-service -- sh
# Xem logs realtime
kubectl logs -f -n iam-local -l app=iam-service
# Xem logs từ container trước (nếu pod restart)
kubectl logs -n iam-local -l app=iam-service --previous
```
## Cleanup
```bash
# Xóa deployment
kubectl delete -f iam-service-deployment.yaml
kubectl delete -f iam-service-service.yaml
kubectl delete -f iam-service-configmap.yaml
# Xóa secrets
kubectl delete secret iam-service-secrets -n iam-local
# Xóa namespace (xóa tất cả)
# EN: Delete the namespace (removes all resources within)
# VI: Xóa namespace (xóa tất cả resource bên trong)
kubectl delete namespace iam-local
```
## Next Steps
1. **Deploy Redis** (optional): Để enable caching và rate limiting
2. **Setup Ingress**: Để expose service ra ngoài
3. **Configure HPA**: Horizontal Pod Autoscaler cho auto-scaling
4. **Add Monitoring**: Prometheus + Grafana
5. **Setup CI/CD**: Tự động deploy khi có code changes
## Resources
## Tài Liệu Tham Khảo / References
- [Kubernetes Documentation](https://kubernetes.io/docs/)
- [Docker Desktop Kubernetes](https://docs.docker.com/desktop/kubernetes/)
- [kind Documentation](https://kind.sigs.k8s.io/)
- [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)
- [Local Kubernetes README](../../../deployments/local/kubernetes/README.md)
- [Docker Desktop for Mac](https://docs.docker.com/desktop/mac/networking/)
- [Prisma Deployment Guide](https://www.prisma.io/docs/guides/deployment/deployment-guides/deploying-to-kubernetes)

View File

@@ -1,756 +1,250 @@
# Hướng Dẫn Development Local
# Hướng Dẫn Phát Triển Local (Local Development)
Hướng dẫn chi tiết cách chạy và phát triển dự án trên máy local với hot reload real-time.
> **EN**: Local Development Guide
>
> **VI**: Hướng dẫn phát triển cục bộ
## Yêu Cầu Hệ Thống
**Cập nhật**: 2026-01-05
**Độ khó**: Trung bình (Intermediate)
**Thời gian thiết lập**: 15-30 phút
- **Node.js**: >= 20.0.0
- **PNPM**: >= 8.0.0
- **Docker & Docker Compose**: Phiên bản mới nhất
- **Git**: Để clone repository
- **Tài khoản Neon**: https://neon.tech (cho database)
## Workflow / Quy Trình
## Bắt Đầu Nhanh (Khuyến Nghị)
```mermaid
graph TD
Start([Bắt đầu / Start]) --> Prerequisites[1. Yêu cầu Hệ thống<br/>Prerequisites]
Prerequisites --> Clone[2. Clone & Install]
Clone --> Env[3. Cấu hình Environment<br/>(Shared & Service-Specific)]
Env --> DB[4. Setup Database<br/>(Migrate & Seed)]
DB --> Run[5. Chạy Dự án<br/>(Native/Docker/Hybrid)]
Run --> Dev[6. Development Loop<br/>(Watch Mode)]
Dev --> Test[7. Testing & Verify]
Test --> End([Hoàn tất / Complete])
1. **Clone Repository**:
```bash
git clone <repository-url>
cd Base
```
subgraph "Các Chế độ Chạy / Run Modes"
Run --> Mode1[Cách 1: Native (Nhanh nhất)]
Run --> Mode2[Cách 2: Hybrid (Linh hoạt)]
Run --> Mode3[Cách 3: Full Docker (Production-like)]
end
2. **Chạy Script Khởi Tạo**:
```bash
./scripts/setup/init-project.sh
```
Script này sẽ cài đặt dependencies, tạo clients, và thiết lập các file môi trường.
## Thiết Lập Thủ Công
### 1. Clone Repository
```bash
git clone <repository-url>
cd Base
style Start fill:#d4edda,stroke:#28a745,stroke-width:2px
style End fill:#d4edda,stroke:#28a745,stroke-width:2px
style Env fill:#fff3cd,stroke:#ffc107
style DB fill:#fff3cd,stroke:#ffc107
style Run fill:#cce5ff,stroke:#007bff
```
### 2. Cài Đặt Dependencies
## Tổng Quan / Overview
Hướng dẫn này cung cấp quy trình chi tiết để thiết lập môi trường phát triển (development environment) cho hệ sinh thái GoodGo Microservices. Bạn sẽ học cách chạy các service, thiết lập cơ sở dữ liệu và quy trình làm việc hiệu quả với hot-reload.
## 1. Yêu Cầu Hệ Thống / Prerequisites
Trước khi bắt đầu, đảm bảo máy của bạn đã cài đặt các công cụ sau:
- **Node.js**: Phiên bản LTS mới nhất (v20+).
- **PNPM**: Package manager chính của dự án (`npm install -g pnpm`).
- **Docker Desktop**: Cần thiết để chạy các dịch vụ hạ tầng (Redis, Database local).
- **Git**: Để quản lý mã nguồn.
- **Neon Account** (Tùy chọn): Nếu sử dụng Neon Database trên cloud (khuyên dùng cho dev).
## 2. Cài Đặt Ban Đầu / Initial Setup
### 2.1 Clone và Cài Đặt Dependencies
```bash
# EN: Clone the repository
# VI: Clone repository về máy
git clone <repository-url>
cd Base
# EN: Install dependencies using pnpm
# VI: Cài đặt các thư viện phụ thuộc bằng pnpm
pnpm install
```
### 3. Thiết Lập Environment Variables
### 2.2 Script Khởi Tạo Nhanh (Khuyến nghị)
Dự án sử dụng **Hybrid Environment Configuration**:
- **Shared configs** (JWT secrets, Redis): `deployments/local/.env.local`
- **Service-specific configs** (DATABASE_URL, PORT): `services/<service>/.env.local`
#### 3.1. Tạo Shared Environment File
Dự án có script tự động hóa các bước khởi tạo cơ bản:
```bash
# EN: Run initialization script
# VI: Chạy script khởi tạo
./scripts/setup/init-project.sh
```
> Script này sẽ:
> - Cài đặt dependencies.
> - Copy các file môi trường mẫu (`.env.example` -> `.env`).
> - Tạo Prisma client.
## 3. Cấu Hình Environment / Environment Configuration
Dự án sử dụng chiến lược **Hybrid Environment** để tối ưu hóa việc quản lý cấu hình:
### 3.1 Shared Configuration (Cấu hình chung)
File: `deployments/local/.env.local`
Chứa các biến dùng chung cho toàn bộ hệ thống (JWT, Redis, Logging).
```bash
# EN: Create shared env file from example
# VI: Tạo file môi trường chung từ file mẫu
cp deployments/local/env.local.example deployments/local/.env.local
```
File này chứa configs dùng chung cho tất cả services:
### 3.2 Service-Specific Configuration (Cấu hình riêng)
Mỗi service (ví dụ `iam-service`) cần file `.env.local` riêng chứa thông tin đặc thù như Database URL và Port.
```bash
# JWT Secrets - MUST be same across all services
JWT_SECRET=dev-jwt-secret-change-in-production-min-32-chars
JWT_REFRESH_SECRET=dev-refresh-secret-change-in-production-min-32-chars
# Redis (Docker)
REDIS_HOST=redis
REDIS_PORT=6379
# Common configs
NODE_ENV=development
LOG_LEVEL=debug
CORS_ORIGIN=http://localhost:3000,http://localhost:3001
```
#### 3.2. Tạo Service-Specific Environment File
Mỗi service cần file `.env.local` riêng cho DATABASE_URL và configs cụ thể:
```bash
# Ví dụ: Auth Service
# EN: Create service-specific env file
# VI: Tạo file môi trường riêng cho service
cp services/iam-service/env.local.example services/iam-service/.env.local
```
Chỉnh sửa `services/iam-service/.env.local`:
**Nội dung quan trọng cần chú ý trong `services/iam-service/.env.local`**:
```bash
# Database riêng cho iam-service
DATABASE_URL=postgresql://user:password@ep-xxx.region.neon.tech/goodgo_auth_dev?sslmode=require&pgbouncer=true
```properties
# Database URL (Sử dụng Neon Tech hoặc Local Postgres)
DATABASE_URL=postgresql://user:password@host:5432/db_name?sslmode=require
# Service configs
# Port của Service (Mỗi service phải khác nhau)
PORT=5001
# Tên Service
SERVICE_NAME=iam-service
# Redis override (native dev - Redis in Docker)
# Redis Host (localhost cho Native Dev, redis cho Docker Dev)
REDIS_HOST=localhost
```
**Lưu ý**:
- Mỗi service có **database riêng** (microservices pattern)
- JWT secrets **phải giống nhau** để services verify tokens của nhau
- Xem [Hướng Dẫn Neon Database](neon-database.md) để tạo databases
## 4. Setup Database
### 4. Chạy Database Migrations
Sau khi cấu hình `DATABASE_URL`, bạn cần đồng bộ schema và tạo dữ liệu mẫu.
```bash
# EN: Run migrations for iam-service
# VI: Chạy migration cho iam-service
./scripts/db/migrate.sh iam-service dev
```
### 5. Seed Database (Tùy chọn)
```bash
# EN: Seed initial data (optional)
# VI: Tạo dữ liệu mẫu (tùy chọn)
./scripts/db/seed.sh iam-service
```
## Các Cách Chạy Dự Án
## 5. Các Chế Độ Chạy / Run Modes
### Cách 1: Chạy Tất Cả Services (Khuyến nghị)
Bạn có thể chạy dự án theo 3 cách tùy thuộc vào nhu cầu:
Cách này phù hợp khi bạn làm full-stack hoặc cần test toàn bộ hệ thống:
### Cách 1: Native Development (Khuyên dùng cho Backend Dev)
Chạy trực tiếp trên máy host. Tốc độ cao nhất, hot-reload nhanh nhất.
1. **Khởi động Hạ tầng (Infrastructure)**:
```bash
# EN: Start Redis and Traefik in Docker background
# VI: Khởi động Redis và Traefik chạy ngầm bằng Docker
cd deployments/local
docker-compose up -d redis traefik
cd ../..
```
2. **Chạy Service**:
```bash
# EN: Start iam-service in watch mode
# VI: Chạy iam-service ở chế độ watch
pnpm --filter @goodgo/iam-service dev
```
### Cách 2: Hybrid Development (Linh hoạt)
Dùng khi bạn cần chạy nhiều service phụ trợ trong Docker, nhưng muốn dev trực tiếp 1 service chính.
```bash
./scripts/dev/start-all.sh
```
Script này sẽ:
1. Kiểm tra Docker đang chạy
2. Kiểm tra DATABASE_URL đã được cấu hình
3. Khởi động infrastructure (Redis, Traefik)
4. Khởi động tất cả services với hot reload
**Hoặc chạy thủ công:**
```bash
# Bước 1: Khởi động infrastructure
cd deployments/local
docker-compose up -d
cd ../..
# Bước 2: Khởi động tất cả services
pnpm dev
```
### Cách 2: Chạy Service Cụ Thể
Cách này phù hợp khi bạn chỉ làm việc với 1 service:
```bash
# Sử dụng script
./scripts/dev/start-service.sh iam-service
# Hoặc chạy trực tiếp
cd services/iam-service
pnpm dev
```
### Cách 3: Hybrid - Native + Docker (Linh hoạt nhất)
Cách này kết hợp tốt nhất của cả hai thế giới: Infrastructure chạy Docker, services đang dev chạy native với hot reload nhanh.
**Phù hợp khi:**
- Làm việc với 1-2 services cụ thể
- Cần services khác chạy background
- Muốn hot reload nhanh cho service đang dev
- Tiết kiệm tài nguyên máy
**Setup:**
```bash
# Bước 1: Khởi động infrastructure (Redis, Traefik)
cd deployments/local
docker-compose up -d redis traefik
cd ../..
# Bước 2: Chạy service đang dev với native (hot reload nhanh)
pnpm --filter @goodgo/iam-service dev
# Bước 3: (Tùy chọn) Chạy services khác trong Docker nếu cần
# EN: Start dependent services in Docker
# VI: Chạy các service phụ thuộc trong Docker
docker-compose -f deployments/local/docker-compose.yml up -d user-service payment-service
```
**Ví dụ workflow thực tế:**
```bash
# Scenario 1: Chỉ dev iam-service
cd deployments/local && docker-compose up -d redis traefik && cd ../..
# EN: Run the service you are working on natively
# VI: Chạy service bạn đang làm việc trực tiếp trên máy
pnpm --filter @goodgo/iam-service dev
# Scenario 2: Dev iam-service + cần web-admin để test
cd deployments/local && docker-compose up -d redis traefik && cd ../..
pnpm --filter @goodgo/iam-service dev &
pnpm --filter @goodgo/web-admin dev
# Scenario 3: Dev frontend, backend chạy Docker
cd deployments/local && docker-compose up -d redis traefik iam-service && cd ../..
pnpm --filter @goodgo/web-admin dev
```
**Lợi ích:**
- ⚡ Hot reload cực nhanh (1-2s) cho service đang dev
- 💻 Tiết kiệm RAM - chỉ chạy Docker cho services cần thiết
- 🐛 Debug dễ dàng - attach debugger trực tiếp
- 🎯 Linh hoạt - chọn service nào chạy native, service nào chạy Docker
### Cách 3: Full Docker (Mô phỏng Production)
### Cách 4: Chạy Nhóm Services
```bash
# Chỉ chạy backend services
pnpm --filter "./services/*" dev
# Chỉ chạy frontend apps
pnpm --filter "./apps/*" dev
# Chạy service cụ thể với dependencies
pnpm --filter @goodgo/iam-service... dev
```
### Cách 5: Chạy Với Docker Compose (Full Stack)
Chạy toàn bộ hệ thống trong Docker. Tốt cho việc kiểm tra tích hợp (Integration Test) nhưng không có hot-reload.
```bash
# EN: Start everything with Docker Compose
# VI: Chạy tất cả bằng Docker Compose
cd deployments/local
docker-compose up -d
# Xem logs
docker-compose logs -f
# Dừng services
docker-compose down
```
**Lưu ý:** Dockerfile hiện tại là production build, không có hot reload. Phù hợp để test môi trường giống production.
## 6. Access & Verification / Truy Cập & Kiểm Tra
## So Sánh Các Phương Án
| Tiêu chí | Cách 1: All Native | Cách 3: Hybrid | Cách 5: Full Docker |
|----------|-------------------|----------------|---------------------|
| **Hot Reload** | ⚡ Cực nhanh (1-2s) | ⚡ Nhanh cho service native | ❌ Không có (production build) |
| **RAM Usage** | 💚 Thấp (~1-2GB) | 💛 Trung bình (~2-3GB) | 🔴 Cao (~3-5GB) |
| **Debug** | ✅ Dễ nhất | ✅ Dễ (native services) | ⚠️ Khó hơn (qua container) |
| **Setup** | 🟢 Đơn giản | 🟡 Trung bình | 🟢 Đơn giản |
| **Giống Production** | ⚠️ Khác biệt | 🟡 Một phần | ✅ Gần giống nhất |
| **Khi nào dùng** | Dev hàng ngày | Dev 1-2 services | Test integration/deployment |
**Khuyến nghị:**
- 🎯 **90% thời gian**: Dùng **Cách 1** (All Native) - nhanh nhất, tiện nhất
- 🔧 **Khi cần linh hoạt**: Dùng **Cách 3** (Hybrid) - chọn service nào chạy native
- 🐳 **Test production-like**: Dùng **Cách 5** (Full Docker) - test networking, deployment
## Điểm Truy Cập
Khi các services đang chạy, bạn có thể truy cập:
Sau khi khởi động, bạn có thể truy cập các điểm cuối sau:
| Service | URL | Mô tả |
|---------|-----|-------|
| **API Gateway** | http://localhost/api/v1 | Điểm truy cập chính qua Traefik |
| **Auth Service** | http://localhost:5001 | Truy cập trực tiếp auth service |
| **Auth API** | http://localhost/api/v1/auth | Auth API qua gateway |
| **Web Admin** | http://admin.localhost hoặc http://localhost:3000 | Admin dashboard |
| **Web Client** | http://localhost hoặc http://localhost:3001 | Client web app |
| **Traefik Dashboard** | http://localhost:8080 | Xem routing và services |
| **API Gateway** | `http://localhost/api/v1` | Cổng truy cập chính qua Traefik |
| **IAM Service** | `http://localhost:5001` | Truy cập trực tiếp service |
| **Health Check** | `http://localhost:5001/health` | Kiểm tra trạng thái service |
| **Metrics** | `http://localhost:5001/metrics` | Prometheus metrics |
| **API Docs** | `http://localhost:5001/api-docs` | Swagger UI |
## Hot Reload & Live Development
### Backend Services (TypeScript)
Backend services sử dụng `tsx watch` hoặc `nodemon` để tự động restart khi code thay đổi:
### Kiểm tra Health Check
```bash
# Trong services/iam-service/package.json
"scripts": {
"dev": "tsx watch src/index.ts"
}
# EN: Check liveness
# VI: Kiểm tra liveness
curl http://localhost:5001/health/live
# EN: Check readiness
# VI: Kiểm tra readiness
curl http://localhost:5001/health/ready
```
**Khi bạn thay đổi:**
- `.ts` files → Service tự động restart (1-2 giây)
- `.env` files → Cần restart thủ công
- `prisma/schema.prisma` → Cần chạy migration
## 7. Troubleshooting / Xử Lý Sự Cố
### Frontend Apps (Next.js)
### Port Already In Use
Frontend apps sử dụng Next.js Fast Refresh:
**Lỗi**: `Error: listen EADDRINUSE: address already in use :::5001`
**Giải pháp**:
```bash
# Trong apps/web-admin/package.json
"scripts": {
"dev": "next dev"
}
```
# EN: Find process using port 5001
# VI: Tìm process đang chiếm port 5001
lsof -i :5001
**Khi bạn thay đổi:**
- React components → Cập nhật ngay lập tức (không reload page)
- CSS/Tailwind → Cập nhật ngay lập tức
- `next.config.js` → Cần restart
### Shared Packages
Khi thay đổi shared packages (trong `packages/`):
```bash
# Packages tự động rebuild với Turbo watch mode
pnpm --filter @goodgo/logger dev
```
## Workflow Development Thực Tế
### Setup 3 Terminals (Khuyến nghị)
#### Option A: Development Hàng Ngày (All Native)
**Terminal 1: Chạy Services**
```bash
./scripts/dev/start-all.sh
# Hoặc: pnpm dev
```
**Terminal 2: Watch Tests**
```bash
# Auto-run tests khi code thay đổi
pnpm --filter @goodgo/iam-service test --watch
```
**Terminal 3: Development Tasks**
```bash
# Prisma Studio
pnpm --filter @goodgo/iam-service prisma studio
# Xem logs
./scripts/dev/logs.sh iam-service
# Migrations
./scripts/db/migrate.sh iam-service dev
```
#### Option B: Hybrid Development (Selective Services)
**Terminal 1: Infrastructure + Service đang dev**
```bash
# Start infrastructure
cd deployments/local && docker-compose up -d redis traefik && cd ../..
# Dev service cụ thể với hot reload
pnpm --filter @goodgo/iam-service dev
```
**Terminal 2: Frontend (nếu cần)**
```bash
pnpm --filter @goodgo/web-admin dev
```
**Terminal 3: Tools & Logs**
```bash
# Watch tests
pnpm --filter @goodgo/iam-service test --watch
# Xem Docker logs
docker logs -f redis-cache-local
# Quick commands
pnpm format
```
### Workflow Theo Use Case
#### Use Case 1: Dev Backend Service
```bash
# Terminal 1
cd deployments/local && docker-compose up -d redis traefik && cd ../..
pnpm --filter @goodgo/iam-service dev
# Terminal 2
pnpm --filter @goodgo/iam-service test --watch
# Terminal 3
pnpm --filter @goodgo/iam-service prisma studio
```
#### Use Case 2: Dev Frontend + Backend
```bash
# Terminal 1: Backend
pnpm --filter @goodgo/iam-service dev
# Terminal 2: Frontend
pnpm --filter @goodgo/web-admin dev
# Terminal 3: Infrastructure
cd deployments/local && docker-compose up -d redis traefik
```
#### Use Case 3: Full Stack Development
```bash
# Terminal 1: All services
./scripts/dev/start-all.sh
# Terminal 2: Watch tests
pnpm test --watch
# Terminal 3: Tools
# Prisma Studio, logs, migrations, etc.
```
## Kiểm Tra Health
### Health Endpoints
```bash
# Kiểm tra API Gateway
curl http://localhost/api/v1/health
# Kiểm tra Auth Service trực tiếp
curl http://localhost:5001/health
# Kiểm tra Redis
docker exec redis-cache-local redis-cli ping
```
### Traefik Dashboard
Truy cập http://localhost:8080 để xem:
- Tất cả routes đang hoạt động
- Services đã đăng ký
- Health status của services
## Database Development
### Thay Đổi Schema
```bash
# 1. Chỉnh sửa prisma/schema.prisma
# 2. Tạo và áp dụng migration
cd services/iam-service
pnpm prisma migrate dev --name add_new_field
# 3. Prisma Client sẽ tự động regenerate
```
### Reset Database (Development Only!)
```bash
cd services/iam-service
pnpm prisma migrate reset
```
### Xem Database
```bash
# Mở Prisma Studio
cd services/iam-service
pnpm prisma studio
# Truy cập: http://localhost:5555
```
## Debugging
### VS Code Debugging
Tạo file `.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Auth Service",
"type": "node",
"request": "launch",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["--filter", "@goodgo/iam-service", "dev"],
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
}
]
}
```
### Xem Logs Chi Tiết
```bash
# Service logs
./scripts/dev/logs.sh iam-service
# Docker logs
docker logs -f iam-service-local
docker logs -f redis-cache-local
docker logs -f traefik-local
# Tất cả logs
docker-compose -f deployments/local/docker-compose.yml logs -f
```
## Troubleshooting
### Port Đã Được Sử Dụng
```bash
# Tìm process đang dùng port
lsof -i :5001 # Auth service
lsof -i :3000 # Web admin
lsof -i :6379 # Redis
lsof -i :80 # Traefik
# Kill process
# EN: Kill the process
# VI: Tắt process đó
kill -9 <PID>
```
### Docker Không Chạy
### Database Connection Error
```bash
# Kiểm tra Docker
docker info
**Lỗi**: `P1001: Can't reach database server`
# Khởi động Docker Desktop (macOS)
open -a Docker
# Restart Docker services
docker-compose -f deployments/local/docker-compose.yml restart
```
### Database Connection Failed
```bash
# Kiểm tra DATABASE_URL trong service-specific env
cat services/iam-service/.env.local | grep DATABASE_URL
# Nếu chưa có file .env.local, tạo từ example
cp services/iam-service/env.local.example services/iam-service/.env.local
# Chỉnh sửa DATABASE_URL với connection string từ Neon
# DATABASE_URL=postgresql://user:pass@ep-xxx.neon.tech/goodgo_auth_dev?sslmode=require&pgbouncer=true
# Test connection
cd services/iam-service
pnpm prisma db pull
```
**Lưu ý**: Mỗi service cần file `.env.local` riêng với DATABASE_URL của service đó.
**Giải pháp**:
- Kiểm tra lại biến `DATABASE_URL`.
- Nếu dùng Docker Postgres local, đảm bảo container đang chạy (`docker ps`).
- Nếu dùng Neon, kiểm tra kết nối internet.
### Module Not Found
**Lỗi**: Không tìm thấy các package nội bộ (ví dụ `@goodgo/logger`).
**Giải pháp**:
```bash
# Cleanup và reinstall
./scripts/utils/cleanup.sh
pnpm install
# Hoặc chỉ cleanup node_modules
rm -rf node_modules
rm -rf services/*/node_modules
rm -rf apps/*/node_modules
rm -rf packages/*/node_modules
# EN: Re-install dependencies and build packages
# VI: Cài lại dependencies và build lại packages
pnpm install
pnpm build
```
### Hot Reload Không Hoạt Động
## Tài Liệu Tham Khảo / References
```bash
# Restart service
# Ctrl+C để dừng, sau đó:
pnpm dev
# Hoặc restart Docker container
docker-compose -f deployments/local/docker-compose.yml restart iam-service
```
## Tips & Best Practices
### 1. Sử Dụng Turbo Cache
Turbo cache giúp build nhanh hơn:
```bash
# Lần đầu chạy sẽ chậm
pnpm dev
# Các lần sau sẽ nhanh hơn nhờ cache
# Cache được lưu trong node_modules/.cache/turbo
```
### 2. Dev Selective Services
Không cần chạy tất cả nếu chỉ làm 1 service:
```bash
# Chỉ chạy iam-service
pnpm --filter @goodgo/iam-service dev
# Chạy iam-service và dependencies
pnpm --filter @goodgo/iam-service... dev
```
### 3. Watch Tests
```bash
# Chạy tests tự động khi code thay đổi
pnpm --filter @goodgo/iam-service test --watch
```
### 4. Format Code Tự Động
Cài đặt Prettier extension trong VS Code và bật format on save.
### 5. Sử Dụng Git Hooks
```bash
# Pre-commit hook sẽ tự động format và lint
git commit -m "feat: add new feature"
```
### 6. Hybrid Development (Best of Both Worlds)
Kết hợp Docker và Native để tối ưu workflow:
```bash
# Infrastructure luôn chạy Docker
cd deployments/local && docker-compose up -d redis traefik
# Service đang dev chạy native (hot reload nhanh)
pnpm --filter @goodgo/iam-service dev
# Services khác có thể chạy Docker nếu cần
docker-compose up -d user-service payment-service
```
**Lợi ích:**
- ⚡ Hot reload nhanh nhất cho service đang làm
- 💻 Tiết kiệm RAM - không chạy tất cả containers
- 🐛 Debug dễ dàng - breakpoints, logs trực tiếp
- 🎯 Linh hoạt - chọn service nào chạy native
### 7. Quản Lý Multiple Services
```bash
# Chạy selective services với pnpm workspace
pnpm --filter "@goodgo/iam-service" --filter "@goodgo/user-service" dev
# Hoặc dùng pattern
pnpm --filter "./services/{auth,user}-service" dev
```
## Environment Variables
Dự án sử dụng **Hybrid Environment Configuration** với 2 levels:
### Level 1: Shared Environment (`deployments/local/.env.local`)
Configs dùng chung cho tất cả services:
```bash
# JWT Secrets - MUST be same across all services
JWT_SECRET=dev-jwt-secret-change-in-production-min-32-chars
JWT_REFRESH_SECRET=dev-refresh-secret-change-in-production-min-32-chars
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
# Redis (Docker hostname)
REDIS_HOST=redis
REDIS_PORT=6379
# Common configs
NODE_ENV=development
LOG_LEVEL=debug
CORS_ORIGIN=http://localhost:3000,http://localhost:3001
# Monitoring (optional)
TRACING_ENABLED=false
```
**Tạo file:**
```bash
cp deployments/local/env.local.example deployments/local/.env.local
```
### Level 2: Service-Specific Environment (`services/<service>/.env.local`)
Configs riêng cho từng service:
```bash
# services/iam-service/.env.local
# Database riêng cho service này
DATABASE_URL=postgresql://user:pass@ep-xxx.neon.tech/goodgo_auth_dev?sslmode=require&pgbouncer=true
# Service configs
PORT=5001
SERVICE_NAME=iam-service
API_VERSION=v1
# Redis override (native dev - Redis in Docker)
REDIS_HOST=localhost
# Service-specific configs
EMAIL_SERVICE_URL=http://notification-service:5003
PROMETHEUS_PORT=9090
```
**Tạo file:**
```bash
cp services/iam-service/env.local.example services/iam-service/.env.local
```
### Cách Hoạt Động
Services load env theo thứ tự:
1. **Shared env** (`deployments/local/.env.local`) - JWT, Redis, common configs
2. **Service env** (`.env.local`) - DATABASE_URL, PORT, overrides
```bash
# Trong package.json
"dev": "dotenv -e ../../deployments/local/.env.local -e .env.local -- tsx watch src/main.ts"
```
**Lợi ích:**
- ✅ JWT secrets giống nhau → services verify tokens của nhau
- ✅ Mỗi service có database riêng → microservices pattern
- ✅ Override configs dễ dàng → REDIS_HOST=localhost cho native dev
- ✅ Không duplicate configs → maintain dễ hơn
### Important Notes
1. **JWT Secrets**: MUST be identical across all services
2. **Database**: Each service has its own database (e.g., `goodgo_auth_dev`, `goodgo_user_dev`)
3. **Redis Host**:
- `redis` (Docker hostname) in shared env
- `localhost` (override) in service env for native dev
4. **Never commit**: `.env.local` files are gitignored
## Các Lệnh Hữu Ích
```bash
# Development
pnpm dev # Chạy tất cả services
pnpm build # Build tất cả
pnpm test # Test tất cả
pnpm lint # Lint tất cả
pnpm format # Format code
# Cleanup
pnpm clean # Xóa build artifacts
./scripts/utils/cleanup.sh # Cleanup toàn bộ
# Database
./scripts/db/migrate.sh iam-service dev # Migration
./scripts/db/seed.sh iam-service # Seed data
./scripts/db/backup.sh iam-service # Backup
# Docker
docker-compose -f deployments/local/docker-compose.yml up -d # Start
docker-compose -f deployments/local/docker-compose.yml down # Stop
docker-compose -f deployments/local/docker-compose.yml logs -f # Logs
docker-compose -f deployments/local/docker-compose.yml restart # Restart
```
## Tài Nguyên Thêm
- [Getting Started](getting-started.md) - Thiết lập ban đầu
- [Development Guide](development.md) - Quy trình development
- [Neon Database Guide](neon-database.md) - Hướng dẫn database
- [Troubleshooting](troubleshooting.md) - Xử lý sự cố
- [Kubernetes Guide](kubernetes-local.md) - Triển khai lên K8s Local.
- [Project Architecture](../../docs/vi/ARCHITECTURE.vi.md) - Tổng quan kiến trúc hệ thống.