타입스크립트 express 빌드 배포(운영환경 도커)

오늘은 타입스크립트로 만들어진 Node.js express 앱을 운영환경 용 도커에 배포하는 방법을 정리해 보았습니다.

구글링이나 유튜브 등에 개발 Docker 버전의 Node.js 예제나 운영환경일지라도 리액트+Nginx 버전의 예제는 많은데, 빌드 과정이 한번 더 있게 되는 타입스크립트 버전의 Node.js 익스프레스 도커 배포 내용은 많지 않았습니다.

그래서 운영 환경용 도커로 빌드하기 위한 간단한 절차만을 담아 정리해 보았습니다.

※ “dist” 폴더에 build 된 결과가 담기게 되고, 수동 복사할 내역은 build 작업과 함께 gulp 등의 모듈로 배포했다고 가정합니다.

타입스크립트용 build 스크립트 점검

현재 package.json에는 다음과 같이 정의되어 있습니다.

예를 들면, dev 스크립트는 개발시에, start 스크립트를 사용한다고 가정합니다.

"scripts": {
    "start": "node ./dist/server.js",
    "build": "rimraf ./dist    tsc -p .    npx gulp",
    "dev": "nodemon --watch \"src/**/*.ts\" --exec \"ts-node\" src/server.ts",
  }

우선 로컬 상에서도 빌드시 오류가 없는지 확인합니다.

npm run build

정상적으로 빌드가 됨을 확인하면 다음 절차로 넘어갑니다.

Docker 운영 배포 환경 구성

Dockerfile을 작성하고, docker-compose 파일을 작성한 후, volume 등을 조정하도록 하겠습니다.

운영 배포용 Dockerfile 작성

아래와 같이 pacakge.json을 복사 후 dependancy를 설치한 후 build 커맨드로 빌드 작업을 수행하도록 설정합니다.

FROM node:20

WORKDIR "/app"

COPY ./package.json ./

RUN npm install

COPY . .

RUN npm run build

CMD ["npm", "run", "start"]

운영 배포용 docker-compose.yml 파일 작성

다음과 같이 docker-compose 파일을 생성하였습니다.

  backend:
    container_name: backend
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    volumes:
      - ./backend:/app
      - /app/node_modules

실행 및 오류 수정

이 상태에서 도커 이미지를 빌드 후 실행하면

docker-compose --file "docker-compose.prod.yml" up --build

정상적으로 build 되었음에도, 아래와 같이 app/dist/server.js 를 찾을 수 없다는 수행 오류가 발생하게 되고

  Error: Cannot find module '/app/dist/server.js'
      at Module._resolveFilename (node:internal/modules/cjs/loader:1048:15)
      at Module._load (node:internal/modules/cjs/loader:901:27)
      at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
      at node:internal/main/run_main_module:23:47 {
    code: 'MODULE_NOT_FOUND',
    requireStack: []

해당 Docker 컨테이너에 들어가서 보더라도 dist 폴더는 존재하지 않습니다.

빌드된 DOCKER 내에도 dist 디렉토리는 존재하지 않음

※ 확인 방법) start 커맨드에서 에러가 나는 것이고, build 프로세스가 정상인지 확인하기 위함 이므로, Dockerfile에서 다른 스크립트는 그대로 두고 아래의 라인만 다른 개발용 버전의 스크립트로만 교체하면 정상 실행되므로,

CMD ["npm", "run", "start"]

===>

CMD ["npm", "run", "dev"]

일단 정상 실행 컨테이너를 만들어 둔 후 아래의 커맨드 쉘로 확인하면 됩니다.

docker exec -it 컨테이너ID sh

dist 빌드 디렉토리 유지하기

해당 폴더가 volume으로 유지되지 않기 때문에 사라지는 것이 원인입니다.

따라서 아래와 같이 docker-compose.yaml 파일을 수정하거나 docker run 시에 볼륨을 추가해 주면 됩니다.

/app/dist 폴더를 docker-compose 파일에 추가하기

volumes:
      - ./backend:/app
      - /app/node_modules
      - /app/dist

/app/dist 폴더를 docker run 실행시 추가하기

docker run .......-v /app/dist .....

이제 이렇게 수정한 후 다시 빌드하여 컨테이너를 실행하면 정상적으로 실행됨을 확인할 수 있고, 컨테이너 내부에도 아래와 같이 dist 폴더 및 관련 빌드 파일 들을 확인할 수 있습니다.

볼륨 추가 후 DOCKER 내 dist 디렉토리 생성

이제 좀 더 최적화를 위해 가다듬어 봐야겠습니다.

이상으로 타입스크립트 빌드 배포를 위해 Docker 운영 환경 구성 방법을 정리해 보았습니다.

그 밖에 도움 되는 글

Docker invalid ELF header bcrypt 오류 해결 방법

AWS 라이트세일 Docker 개발 환경 Todo(2023)

윈도우 WSL2 Docker 개발 환경,리액트+Node.js 핫리로디드 요약(2023)