From ddaa1ad87376cde7c9e97070ed928be355d92cb2 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Tue, 31 Mar 2026 07:16:53 +0000 Subject: [PATCH] fix: change from static execute to dynamic execute (#19) Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/frontend/pulls/19 --- .gitea/workflows/release.yaml | 5 +++- dockerfile | 52 +++++++++++++++++++++++------------ k8s.yaml | 19 ++++++++----- next.config.ts | 2 +- scripts/release.ts | 47 ++++++++++++++++++++++++++----- tsconfig.json | 2 +- 6 files changed, 92 insertions(+), 35 deletions(-) diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index e7726d5..b20fc73 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -4,7 +4,10 @@ on: push: branches: - main - - dev-* + + pull_request: + branches: + - main jobs: release: diff --git a/dockerfile b/dockerfile index b3fc8f1..abb550e 100644 --- a/dockerfile +++ b/dockerfile @@ -1,32 +1,48 @@ -# --- Giai đoạn 1: Build --- -FROM node:25-alpine AS builder +# --- Giai đoạn 1: Dependencies --- +FROM node:25-alpine AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app # Cài đặt pnpm RUN npm install -g pnpm -WORKDIR /app - -# Copy file định nghĩa package +# Copy file định nghĩa package để tận dụng cache của Docker COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile -# Cài đặt dependencies (sử dụng --frozen-lockfile để đảm bảo đúng phiên bản) -RUN pnpm install --prod --frozen-lockfile - -# Copy toàn bộ code +# --- Giai đoạn 2: Builder --- +FROM node:25-alpine AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules COPY . . -# Build Next.js (Yêu cầu next.config.js có output: 'export') +# Tắt dữ liệu thu thập của Next.js trong quá trình build +ENV NEXT_TELEMETRY_DISABLED 1 + +RUN npm install -g pnpm RUN pnpm run build -# --- Giai đoạn 2: Run (Sản phẩm cuối) --- -FROM nginx:alpine +# --- Giai đoạn 3: Runner (Sản phẩm cuối) --- +FROM node:25-alpine AS runner +WORKDIR /app -# Xóa file mặc định của nginx (tùy chọn nhưng nên làm) -RUN rm -rf /usr/share/nginx/html/* +ENV NODE_ENV production +ENV NEXT_TELEMETRY_DISABLED 1 -# Copy folder out từ giai đoạn builder -COPY --from=builder /app/out /usr/share/nginx/html +# Tạo user để chạy app (bảo mật hơn chạy root) +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs -EXPOSE 80 +# Copy các file cần thiết từ builder +# Standalone chỉ copy code cần chạy, bỏ qua devDependencies và file thừa +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file +USER nextjs + +EXPOSE 3000 +ENV PORT 3000 + +# Chạy bằng server.js được sinh ra bởi output: 'standalone' +CMD ["node", "server.js"] \ No newline at end of file diff --git a/k8s.yaml b/k8s.yaml index 249a544..9d8f544 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -17,13 +17,18 @@ spec: containers: - name: frontend-container image: git.demonkernel.io.vn/foodsurf/frontend:latest + ports: + - containerPort: 3000 resources: limits: - cpu: "50m" - memory: "32Mi" + cpu: "200m" + memory: "256Mi" requests: - cpu: "10m" - memory: "16Mi" + cpu: "50m" + memory: "128Mi" + env: + - name: NODE_ENV + value: "production" --- apiVersion: v1 kind: Service @@ -35,6 +40,6 @@ spec: app: web ports: - protocol: TCP - port: 80 - targetPort: 80 - nodePort: 30080 \ No newline at end of file + port: 80 + targetPort: 3000 + nodePort: 30080 \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index 6c34cdd..83e90cf 100644 --- a/next.config.ts +++ b/next.config.ts @@ -10,7 +10,7 @@ import type { NextConfig } from "next"; * Docs: https://nextjs.org/docs/app/api-reference/next-config-js */ const nextConfig: NextConfig = { - output: "export", + output: 'standalone', images: { remotePatterns: [ { diff --git a/scripts/release.ts b/scripts/release.ts index 3aecb0b..2e10ce1 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -1,4 +1,5 @@ import { execSync } from "node:child_process"; +import fs from "node:fs"; const version = process.argv[2]; if (!version) { @@ -6,14 +7,46 @@ if (!version) { process.exit(1); } -const zipPath = "release.zip"; +const zipPath = `release-v${version}.zip`; // Thêm version vào tên file cho dễ quản lý -console.log(`📦 Đang nén file cho version: ${version}...`); +console.log(`📦 Đang chuẩn bị đóng gói App Router Standalone cho version: ${version}...`); -execSync(`cd out && zip -r ../${zipPath} .`, { - stdio: "inherit", -}); +// Kiểm tra xem đã build chưa +if (!fs.existsSync(".next/standalone")) { + console.error("❌ Thư mục .next/standalone không tồn tại. Hãy chạy 'pnpm build' trước!"); + process.exit(1); +} -console.log(`✅ Đã tạo file zip: ${zipPath}`); +/** + * Với Next.js Standalone, ta cần: + * 1. Nội dung trong .next/standalone (copy ra ngoài hoặc nén trực tiếp) + * 2. .next/static (phải nằm trong .next/static của gói release) + * 3. public (phải nằm trong public của gói release) + */ -execSync("pnpm format"); +try { + // Tạo thư mục tạm để cấu trúc lại file trước khi nén + execSync("rm -rf temp_release && mkdir -p temp_release"); + + console.log("🚚 Đang sao chép các file standalone..."); + execSync("cp -r .next/standalone/. temp_release/"); + + console.log("🚚 Đang sao chép static và public..."); + execSync("mkdir -p temp_release/.next/static"); + execSync("cp -r .next/static/. temp_release/.next/static/"); + execSync("cp -r public temp_release/ 2>/dev/null || : "); // Bỏ qua nếu không có thư mục public + + console.log("🗜️ Đang nén thành file zip..."); + // Di chuyển vào temp_release để nén các file bên trong nó + execSync(`cd temp_release && zip -r ../${zipPath} .`, { stdio: "inherit" }); + + // Xóa thư mục tạm + execSync("rm -rf temp_release"); + + console.log(`✅ Đã tạo file thành công: ${zipPath}`); + + execSync("pnpm format"); +} catch (error) { + console.error("❌ Có lỗi xảy ra trong quá trình nén:", error.message); + process.exit(1); +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 5a92bdd..1a07657 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -31,5 +31,5 @@ ".next/dev/types/**/*.ts", "types/**/*.d.ts" ], - "exclude": ["node_modules", "script", "*.ts"] + "exclude": ["node_modules", "scripts", "*.ts"] }