Phone:

+84 344184570

Email:

nguyentamhoang12a@gmail.com

© 2025 Hoang Nguyen.

Posted by:

Hoang Nguyen

Posted on:

09 April 2025

Build docker NestJs sử dụng

Build docker NestJs sử dụng

Hướng dẫn này giúp bạn cấu hình Docker và thiết lập workflow CI/CD trên GitHub để:

  • 1.Build và push Docker image lên GitHub Container Registry (GHCR)

  • 2.Tự động SSH vào server và chạy script deploy.sh để làm mới container ( thật ra có thể dùng watchtower để watch thay vì như mình)

1. 🐳 Tạo Dockerfile cho NestJS

1# =====================================================
2# GIAI ĐOẠN BUILD (BUILD STAGE)
3# =====================================================
4# Sử dụng Node.js 20 với Alpine Linux làm base image
5# Alpine Linux được chọn vì nhẹ và bảo mật tốt
6FROM node:20-alpine AS builder
7
8# Thiết lập thư mục làm việc trong container
9WORKDIR /app
10
11# Cài đặt các công cụ cần thiết để build
12# python3: Cần cho một số package native
13# make và g++: Cần cho việc biên dịch các dependencies C++
14RUN apk add --no-cache python3 make g++
15
16# Kích hoạt corepack để quản lý yarn
17# Corepack là công cụ quản lý package manager của Node.js
18RUN corepack enable
19
20# Copy các file quản lý dependencies
21# Chỉ copy những file này trước để tận dụng cache layer của Docker
22COPY package*.json yarn.lock ./
23
24# Cài đặt tất cả dependencies với cache
25# --mount=type=cache: Sử dụng BuildKit để cache node_modules
26# --frozen-lockfile: Đảm bảo versions khớp với yarn.lock
27# --prefer-offline: Ưu tiên dùng cache thay vì tải lại
28RUN --mount=type=cache,target=/root/.yarn/cache \
29    --mount=type=cache,target=/root/.yarn/berry/cache \
30    yarn install --frozen-lockfile --prefer-offline
31
32# Copy toàn bộ source code vào container
33# .dockerignore sẽ loại bỏ các file không cần thiết
34COPY . .
35
36# Build ứng dụng cho production
37RUN yarn build:prod
38
39# =====================================================
40# GIAI ĐOẠN PRODUCTION (PRODUCTION STAGE)
41# =====================================================
42# Tạo image mới cho production, giảm kích thước
43FROM node:20-alpine AS production
44
45# Thiết lập thư mục làm việc
46WORKDIR /app
47
48# Copy các file quản lý dependencies
49COPY package*.json yarn.lock ./
50
51# Kích hoạt corepack cho yarn
52RUN corepack enable
53
54# Cài đặt chỉ dependencies cho production
55# Không cài đặt devDependencies để giảm kích thước
56RUN --mount=type=cache,target=/root/.yarn/cache \
57    --mount=type=cache,target=/root/.yarn/berry/cache \
58    yarn install --frozen-lockfile --production --prefer-offline
59
60# Copy các file đã build từ stage trước
61# Chỉ copy những gì cần thiết cho production
62COPY --from=builder /app/dist ./dist
63COPY --from=builder /app/public ./public
64COPY --from=builder /app/.env.production ./.env
65
66# Thiết lập biến môi trường
67# NODE_ENV=production: Chạy ở chế độ production
68# PORT=5005: Port mà ứng dụng sẽ lắng nghe
69ENV NODE_ENV=production \
70    PORT=5005
71
72# Khai báo port sẽ được sử dụng
73EXPOSE 5005
74
75# Tạo user không có quyền root để tăng bảo mật
76# addgroup: Tạo group mới
77# adduser: Tạo user mới và thêm vào group
78RUN addgroup -S appgroup && adduser -S appuser -G appgroup
79USER appuser
80
81# Lệnh khởi động ứng dụng
82# Sử dụng CMD thay vì ENTRYPOINT để có thể override khi cần
83CMD ["yarn", "start:prod"] 

2. ⚙️ Tạo GitHub Actions Workflow

Tạo file .github/workflows/docker-build.yml:

1# Tên của workflow, sẽ hiển thị trong tab Actions của GitHub
2name: Build and Push Docker Image
3
4# Xác định khi nào workflow này sẽ được trigger
5on:
6  push:
7    branches: ['master'] # Chạy khi có push vào nhánh master
8  pull_request:
9    branches: ['master'] # Chạy khi có pull request vào nhánh master
10
11# Định nghĩa các biến môi trường dùng trong workflow
12env:
13  # Địa chỉ registry để push Docker image
14  REGISTRY: ghcr.io
15  # Tên image sẽ được tạo, sử dụng tên repository
16  IMAGE_NAME: ${{ github.repository }}
17
18# Định nghĩa các jobs sẽ được thực thi
19jobs:
20  build-and-push:
21    # Chọn hệ điều hành để chạy job
22    runs-on: ubuntu-latest
23
24    # Cấp quyền cần thiết cho job
25    permissions:
26      contents: read # Quyền đọc code từ repository
27      packages: write # Quyền ghi vào GitHub Packages (để push image)
28
29    # Các bước thực hiện trong job
30    steps:
31      # Bước 1: Check out code từ repository
32      - name: Checkout repository
33        uses: actions/checkout@v4
34
35      # Bước 2: Tạo file .env.production từ GitHub secrets
36      - name: Create .env.production file
37        run: |
38          echo "${{ secrets.ENV_PRODUCTION }}" > .env.production
39
40      # Bước 3: Cài đặt Docker Buildx
41      # Buildx là plugin của Docker cho phép build đa nền tảng và có nhiều tính năng mở rộng
42      - name: Set up Docker Buildx
43        uses: docker/setup-buildx-action@v3
44
45      # Bước 4: Đăng nhập vào GitHub Container Registry
46      # Sử dụng GITHUB_TOKEN tự động được GitHub cung cấp
47      - name: Log in to the Container registry
48        uses: docker/login-action@v3
49        with:
50          registry: ${{ env.REGISTRY }}
51          username: ${{ github.actor }}
52          password: ${{ secrets.ACCESS_TOKEN }}
53
54      # Bước 5: Trích xuất metadata cho Docker image
55      # Tạo các tags và labels phù hợp dựa trên context của GitHub
56      - name: Extract metadata (tags, labels) for Docker
57        id: meta
58        uses: docker/metadata-action@v5
59        with:
60          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
61          # Cấu hình các loại tags sẽ được tạo:
62          tags: |
63            type=ref,event=branch     # Tag theo tên nhánh
64            type=ref,event=pr         # Tag cho pull request
65            type=semver,pattern={{version}}  # Tag theo version (vd: v1.0.0)
66            type=semver,pattern={{major}}.{{minor}}  # Tag theo major.minor (vd: v1.0)
67            type=sha,format=long      # Tag theo SHA của commit
68
69      # Bước 6: Build và push Docker image
70      - name: Build and push Docker image
71        uses: docker/build-push-action@v5
72        with:
73          context: . # Thư mục chứa Dockerfile
74          push: true # Push image sau khi build
75          tags: ${{ steps.meta.outputs.tags }} # Sử dụng tags đã tạo ở bước trước
76          labels: ${{ steps.meta.outputs.labels }} # Sử dụng labels đã tạo ở bước trước
77          # Sử dụng cache để tối ưu quá trình build
78          cache-from: type=gha # Lấy cache từ GitHub Actions
79          cache-to: type=gha,mode=max # Lưu cache lại cho các lần build sau

3. 🔐 Cấu hình Secrets trong GitHub

Vào GitHub > Settings > Secrets and Variables > Actions > Add secrets:

Tên secretGiá trị
ACCESS_TOKENPersonal Access Token có quyền write:packages
ENV_PRODUCTIONNội dung file .env.production