Node.js 환경에서 만든 API를 Docker 이미지로 만들어 배포하기를 해보고 있다. 우선 Docker Desktop 설치에서부터 문제 해결을 하고, Docker image를 만들고 실행하면서 생긴 문제를 기록해본다.
"Cannot enable Hyper-V service" 문제.
1. AMD에 MSI Bios에서 AMD IOMMU 옵션을 찾아서 enable, SVM 옵션을 찾아서 enable로 바꿔주고,
2. 윈도우 시작메뉴 우클릭 > 앱 및 기능 > 프로그램 및 기능 > Windows 기능 켜기/끄기 > Hyper-V 체크, 가상머신 플랫폼 체크
두가지 적용하고나니 Hyper-V 문제가 해결되었다.
그 다음은,
"WSL 2 installation" 에러
이건 팝업에 있는 해결 방법 링크에서 알려주는 단계를 따라하니 해결되었다.
WSL 2 설치까지 마치면, Docker Desktop이 실행된다.
이제 Build를 할 차례.
Docker를 사용하여 Node.js 백엔드 API를 이미지로 만들어 배포하는 방법은,
- Dockerfile 작성: 프로젝트 루트 디렉토리에
Dockerfile
이라는 이름의 파일을 생성한다.
Dockerfile은 Docker 이미지를 빌드하는 데 사용되는 파일인데, 아래처럼 작성하면 된다.
# base 이미지 선택
FROM node:18.16.0
# 작업 디렉토리 생성
WORKDIR /app
# 종속성 설치
COPY package*.json ./
RUN npm install
# 소스 코드 복사
COPY . .
# 포트 노출
EXPOSE 3000
# 컨테이너 시작 시 실행할 명령어
CMD [ "npm", "start" ]
FROM node:18.16.0 으로, 내가 설치한 node.js 버전과 동일하게 18.16.0을 선택했고,
WORKDIR /app 으로 폴더를 설정하고,
COPY package*.json ./ 으로 종속성(의존성) 설치를 위해 package.json과 package-lock.json을 WORKDIR에 COPY하고,
RUN npm install 명령어로 package를 설치 실행하고,
COPY . . 로 현재 프로젝트 디렉토리 전체를 WORKDIR에 복사하고,
(이때, .dockerignore로 node_modules을 무시하도록 설정해야 한다. 뒤에 다시 설명)
EXPOSE 3000 으로 node실행할 때 설정하는 PORT 값을 넣어서, Docker 이미지 외부로 열어줄 포트를 설정해 주고,
CMD ["npm", "start"] 로 컨테이너 시작할 때 실행할 명령어를 적어준다.
(이때, package.json에 script를 설정해줘야 한다.)
- Docker 이미지 빌드: 터미널을 열고 프로젝트 루트 디렉토리로 이동한 후 다음 명령어를 실행하여 Docker 이미지를 빌드한다.
docker build -t 이미지명:태그 .
예를 들어, 이미지명을 my-node-api
로, 태그를 v1.0
으로 설정하려면 다음과 같다.
docker build -t my-node-api:v1.0 .
- Docker 컨테이너 실행: 이미지를 빌드한 후에는 아래 명령어를 사용하여 컨테이너로 실행하여 API를 배포할 수 있다.
docker run -p 호스트포트:컨테이너포트 이미지명:태그
예를 들어, 호스트의 포트 8080을 컨테이너의 포트 3000에 매핑하여 컨테이너를 실행하려면 다음과 같이 실행하면 된다.
docker run -p 8080:3000 my-node-api:v1.0
"Error: /app/node_modules/bcrypt/lib/binding/napi-v3/bcrypt_lib.node: invalid ELF header" 발생
아까 위에서, "(이때, .dockerignore로 node_modules을 무시하도록 설정해야 한다. 뒤에 다시 설명)" 으로 해결되는 오류인데, 해결 방법은 stackoverflow 에서 찾았다. 문제의 요지는, window환경에서 설치한 bcrypt 모듈을 Docker 이미지 빌드할 때, "COPY . ." 명령어로 node_modules까지 모두 복사했기 때문에 윈도우에서 실행되는 bcrypt가 리눅스 환경(Docker는 리눅스 환경인가? 그렇다고 한다. nodejs.org에서 확인)에서 실행되지 않기 때문에 생기는 문제이다.
이 오류를 해결하려면, "COPY . ."할 때, node_modules 폴더를 무시해야 하는데, 무시하기 위해서는 .gitignore같이 .dockerignore 파일을 아래와 같이 만들면 된다.
# 패키지 폴더 복사 제외
node_modules/
그러고 나면 아까 Docker 이미지 파일 빌드에 사용된 명령어에서, RUN npm install 으로 설치된 것들이 그대로 사용되기 때문에 bcrypt 모듈의 바인딩 파일(bcrypt_lib.node)이 올바르지 않은 ELF(Executable and Linkable Format) 헤더를 가지고 있다는 에러가 나타나지 않게 된다.
일단 여기까지 진행하고, docker를 실행시키면 localhost의 호스트 포트로 docker 이미지로 만든 API가 잘 작동하는 것을 확인할 수 있었다.
'daily' 카테고리의 다른 글
Swagger (0) | 2023.05.16 |
---|---|
Dockerization [1] - AWS EB에 docker 배포하기 (1) | 2023.05.15 |
PWM 신호로 Fan 제어해 압력값 세팅하기 (0) | 2023.05.15 |
23, 19주차 (0) | 2023.05.11 |
3-Tier, 3-Layered Architecture (0) | 2023.05.09 |