Nest.js를 배워보자/13. NestJS + Docker 배포하기

환경변수 관리

_Blue_Sky_ 2025. 12. 3. 12:47
728x90

 

 


⚙️ 2. 환경변수 관리 (Environment Variables)

컨테이너 환경에서 애플리케이션을 실행할 때 환경변수(Environment Variables)를 효율적이고 안전하게 관리하는 것은 매우 중요합니다. NestJS는 @nestjs/config 모듈을 통해 환경변수 관리를 표준화합니다.

A. NestJS 환경변수 관리 베스트 프랙티스

  1. .env 파일 사용: 로컬 개발 환경에서는 .env 파일을 사용하여 변수를 설정하고, Git 저장소에는 절대 커밋하지 않습니다 (.gitignore에 추가).
  2. ConfigModule 사용: NestJS의 ConfigModule을 사용하여 .env 파일의 변수를 읽고 애플리케이션 전체에 주입합니다.
  3. 스키마 유효성 검사: Joi 라이브러리를 사용하여 애플리케이션 시작 시 필요한 환경변수들이 모두 정의되었는지, 그리고 올바른 타입과 포맷을 갖는지 검증합니다.
728x90

B. 컨테이너 환경에서 환경변수 주입

Docker 환경에서 환경변수를 주입하는 방법은 크게 두 가지가 있으며, 이는 개발 환경과 프로덕션 환경에서 다르게 적용됩니다.

1. Dockerfile 빌드 시 주입 (권장하지 않음)

--build-arg를 사용하여 빌드 단계에서 환경변수를 주입할 수 있지만, 이는 보안상의 문제로 인해 런타임 환경변수에는 권장되지 않습니다. 빌드된 이미지 레이어에 값이 남을 수 있기 때문입니다.

2. Docker Compose 또는 docker run 런타임 시 주입 (권장)

컨테이너를 실행(Run)할 때 환경변수를 주입하는 것이 가장 안전하고 유연한 방법입니다.

① docker run 명령 사용:

docker run -p 3000:3000 \
    -e NODE_ENV=production \
    -e DATABASE_URL=postgres://user:pass@host:5432/mydb \
    my-nestjs-app:latest

② Docker Compose 파일 사용 (가장 일반적인 방법):

docker-compose.yml 파일에서 각 서비스 별로 환경변수를 명시적으로 정의하거나, 별도의 .env 파일을 참조하도록 설정합니다.

# docker-compose.yml
version: '3.8'
services:
  nestjs-app:
    image: my-nestjs-app:latest
    container_name: nestjs_api
    restart: always
    ports:
      - "3000:3000"
    environment:
      # 환경변수 명시적 정의
      NODE_ENV: production
      # 민감한 DB 정보는 Secrets (프로덕션) 또는 .env 파일에서 가져오는 것이 좋음
      DATABASE_HOST: database
      DATABASE_PORT: 5432
    # 외부 .env 파일 참조 (로컬 개발 환경에서 유용)
    env_file:
      - .env.production 
728x90

C. NestJS ConfigModule 설정 예시

NestJS 애플리케이션이 Docker 런타임에서 주입된 환경변수를 사용하도록 ConfigModule을 설정합니다.

// src/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi'; // 환경변수 유효성 검사를 위해 Joi 사용

@Module({
  imports: [
    ConfigModule.forRoot({
      // docker run이나 docker-compose로 주입된 변수가 우선적으로 사용됨
      isGlobal: true, 
      // Joi를 사용하여 스키마 유효성 검사
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production', 'test')
          .default('development'),
        DATABASE_HOST: Joi.string().required(),
        DATABASE_PORT: Joi.number().default(5432),
        JWT_SECRET: Joi.string().required(),
        PORT: Joi.number().default(3000),
      }),
    }),
  ],
})
export class AppModule {}

 

728x90