Tận dụng Docker và Docker Compose để triển khai và chạy liền mạch các ứng dụng Nest.js là lựa chọn thông minh. Dưới đây là hướng dẫn chi tiết.
Docker và Docker Compose là gì?
Docker là một nền tảng phát triển nguồn mở cung cấp công nghệ đóng gói được sử dụng trong việc xây dựng và đóng gói các ứng dụng cùng với các phần phụ thuộc của chúng dưới dạng hình ảnh di động.
Những hình ảnh này sau đó được chạy dưới dạng các thành phần thực thi trong môi trường vùng chứa bị cô lập. Việc chạy các ứng dụng trong các vùng chứa này đảm bảo hiệu suất ứng dụng nhất quán trên các hệ thống sản xuất khác nhau mà không có bất kỳ vấn đề tương thích nào.
Mặt khác, Docker Compose là một công cụ được sử dụng cùng với Docker để đơn giản hóa quá trình xác định và quản lý các ứng dụng nhiều container.
Trong khi Docker chủ yếu được sử dụng để quản lý các vùng chứa riêng lẻ, Docker Compose cho phép bạn quản lý cấu hình của nhiều vùng chứa cần chạy dưới dạng một ứng dụng.
Điều này đặc biệt hữu ích khi một ứng dụng bao gồm nhiều dịch vụ cần hoạt động cùng nhau, chẳng hạn như một số dịch vụ API và cơ sở dữ liệu phụ thuộc.
Trước khi đi sâu vào code, bạn cần cài đặt Docker Desktop trên máy cục bộ.
Thiết lập dự án Nest.js
Hướng dẫn này sẽ giới thiệu quy trình thiết lập hai vùng chứa Docker hoạt động liền mạch như một ứng dụng Nest.js duy nhất. Vùng chứa đầu tiên sẽ chứa một phiên bản image Docker của máy chủ web Nest.js, trong khi vùng chứa thứ hai sẽ thực thi image database PostgreSQL của Docker.
Để bắt đầu, cài đặt công cụ dòng lệnh Nest.js:
npm i -g @nestjs/cli
Bây giờ,tạo một dự án Nest.js mới bằng cách chạy lệnh bên dưới trong terminal của bạn.
nest new docker-nest-app
Tiếp theo, công cụ CLI sẽ hiển thị một số trình quản lý gói để bạn lựa chọn tạo dự án. Click tùy chọn ưa thích. Ví dụ này dùng npm.
Cuối cùng, bạn có thể điều hướng đến thư mục dự án và khởi động máy chủ phát triển.
cd docker-nest-app
npm run start
Tạo mô đun database
Đầu tiên, cài đặt những phần phụ thuộc:
npm install pg typeorm @nestjs/typeorm @nestjs/config
Tiếp theo, trong thư mục gốc của dự án, hãy tạo tệp .env và thêm các giá trị cấu hình kết nối cơ sở dữ liệu sau:
DATABASE_HOST="db"
DATABASE_PORT=5432
DATABASE_USER="testUser"
DATABASE_PASSWORD="mypassword123"
Cuối cùng, hãy tiếp tục và tạo mô-đun cơ sở dữ liệu.
nest g module database
Bây giờ, sau khi mô-đun được tạo, hãy mở tệp cơ sở dữ liệu /database.module.ts và bao gồm code cấu hình cơ sở dữ liệu sau:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
type: 'postgres',
host: configService.get<string>('DATABASE_HOST'),
port: configService.get<number>('DATABASE_PORT'),
username: configService.get<string>('DATABASE_USER'),
password: configService.get<string>('DATABASE_PASSWORD'),
synchronize: true,
}),
inject: [ConfigService],
}),
],
})
export class DatabaseModule {}
Sau khi thiết lập image Docker PostgreSQL bằng cấu hình TypeORM này, ứng dụng Nest.js sẽ thiết lập kết nối với cơ sở dữ liệu.
Update file app.module.ts
Cuối cùng, cập nhật file mô-đun ứng dụng chính để kết hợp cấu hình cho mô-đun cơ sở dữ liệu.
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './database/database.module';
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: '.env',
}),
DatabaseModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Thiết lập Dockerfile
Dockerfile ghi lại bộ hướng dẫn cần thiết mà công cụ Docker cần để tạo image Docker. Nó bao gồm mã nguồn của ứng dụng và tất cả các phần phụ thuộc.
Trong thư mục gốc của dự án, tạo một tệp mới và đặt tên là Dockerfile. Sau đó, thêm các nội dung sau:
FROM node:16.3.0-alpine3.13
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD [ "npm", "run", "start:dev" ]
Trong đó:
- FROM chỉ định hình ảnh cơ sở mà Docker nên sử dụng để xây dựng hình ảnh của ứng dụng.
- WORKDIR hướng dẫn Docker đặt thư mục /app làm thư mục làm việc cho ứng dụng trong vùng chứa.
- COPY package*.json./ sao chép tất cả các file có định dạng tên tệp đó từ thư mục hiện tại trong ứng dụng sang thư mục app.
- RUN npm install cài đặt các gói và phần phụ thuộc bắt buộc mà ứng dụng yêu cầu trong vùng chứa Docker.
- COPY… hướng dẫn Docker sao chép tất cả các tệp mã nguồn của ứng dụng từ thư mục hiện tại vào thư mục /app.
- RUN npm run build xây dựng ứng dụng Nest.js trước khi tạo Docker image. Nó biên dịch mã TypeScript thành JavaScript và lưu trữ kết quả đầu ra của quá trình xây dựng trong một thư mục dist.
- CMD xác định lệnh chạy khi container khởi động. Trong trường hợp này, chúng ta sẽ chạy lệnh npm run start:dev để khởi động máy chủ ở chế độ phát triển.
Cấu hình này cho phép ứng dụng chủ động theo dõi các thay đổi của code. Khi các thay đổi được phát hiện, vùng chứa sẽ tự động được xây dựng lại.
Tạo file Docker Compose
Trong thư mục gốc của thư mục dự án, tạo tệp docker-compose.yml mới và thêm nội dung sau:
version: '3.9'
services:
server:
build: .
ports:
- '3000:3000'
depends_on:
- db
db:
image: 'postgres'
ports:
- '5432:5432'
environment:
POSTGRES_PASSWORD: 'mypassword123'
POSTGRES_USER: 'testUser'
volumes:
- data:/var/lib/postgresql/data
volumes:
data:
Docker Compose sẽ sử dụng các hướng dẫn này để xây dựng và chạy hai hình ảnh trong hai vùng chứa Docker. Vùng chứa đầu tiên, máy chủ, sẽ lưu trữ hình ảnh của ứng dụng; chạy trên cổng 3000.
Vùng chứa thứ hai sẽ lưu trữ hình ảnh cơ sở dữ liệu PostgreSQL. Bạn không cần chỉ định Dockerfile cho hình ảnh này—Docker sẽ sử dụng hình ảnh PostgreSQL có sẵn trên sổ đăng ký hình ảnh của Docker để xây dựng nó.
Khởi động Docker Container
Cuối cùng tiếp tục xây dựng các image và khởi động container bằng cách chạy lệnh sau:
docker compose up
Sau khi quá trình này hoàn tất thành công, bạn sẽ thấy thông tin log tương tự trên terminal.
Bây giờ, khi cả máy chủ web và vùng chứa cơ sở dữ liệu của bạn đều chạy, hãy tiếp tục và bổ sung thêm nhiều chức năng hơn cho ứng dụng Nest.js của bạn. Chẳng hạn, bạn có thể xây dựng API CRUD REST của Nest.js.
Đẩy image Docker vào Docker Hub
Hãy làm theo các bước sau:
1. Tới Docker Hub, đăng ký và đăng nhập trang tổng quan tài khoản.
2. Click nút Create repository, điền tên của repository, xác định khả năng hiển thị nó bằng cách chọn Public hoặc Private, rồi click Create.
3. Bây giờ, bạn cần đăng nhập vào tài khoản thông qua thiết bị đầu cuối bằng cách chạy lệnh bên dưới, sau đó cung cấp tên người dùng và mật khẩu Docker.
docker login
4. Tiếp theo, update tên image của Docker để khớp với định dạng này: <your docker username>/<repo name> bằng lệnh:
docker tag <image> <your docker username>/<repo name>
5. Cuối cùng, đẩy image Docker.
docker push <image>/<repo name>
Công nghệ container hóa của Docker cho phép bạn đóng gói một ứng dụng cùng với tất cả các phần phụ thuộc của nó vào image Docker. Sau đó, những hình ảnh này có thể chạy trơn tru trong các vùng chứa ở các môi trường sản xuất và phát triển khác nhau mà không gặp bất kỳ sự cố nào.