Docker 이미지에 Bcrypt 를 설치하고, 호스트 node_modules 을 제외하기 (번역)

chichi·2023년 1월 3일
0

Install Bcrypt in Docker image and exclude host node_modules 의 원문은 여기 에서 확인하실 수 있습니다.

(번역 시작)

이 게시물은 Bcrypt NodeJS를 의존성(dependency) 으로 설치하고, node_modules가 호스트 시스템에서 도커 컨테이너로 연결되는 것을 방지하는 두 가지 주제를 다룹니다.

Bcrypt 패키지를 사용하여 비밀번호를 암호화 하는데는 약간의 문제가 있습니다. 설치할 때 (Bcrypt는) node-gyp과 python2.x 를 사용하여 OS 아키텍쳐로 컴파일되어야 합니다. 이러한 필수 의존성(dependencies)은 문서화해야 하는 개발 머신에서 앱을 빌드하는데 필요합니다. 그러나, docker는 "시작하기"문서에서 이를 전달해야 할 필요성을 제공합니다. 불행하게도, 이것은 개발 중에 느린 피드백 루프라는 문제(a problem of slow feedback loop)를 일으킬 것입니다.

애플리케이션에 코드가 변경될 때마다, 도커 이미지는 해당 변경 사항을 확인하기 위해 다시 빌드해야 합니다. rebuild 는 모든 변경사항을 확인하는데 시간이 더해지는 추가 단계로, 느린 피드백 루프를 만들고 엔지니어링 문제를 만듭니다. 이는 호스트의 응용 프로그램 파일을 도커 컨테이너에 연결하는 도커 볼륨을 사용하여 해결할 수 있습니다.
(역주: 원문 내 링크에 접근할 수 없어, docker 공식 문서의 volumes 항목을 삽입하였습니다.)

다음 문제는, 엔지니어가 docker 컨테이너와는 다른 OS를 가지고 개발하는 중에 있을 것입니다. 예를 들면, 개발자는 Window로 작업하지만 도커 이미지는 Linux 로 빌드되어 있을 때가 있을 것입니다. Bcrypt 의존성은 호스트(Window)에 대해 컴파일 되었지만 Linux 에서 실행되기 때문에, 앱이 실행되는 과정에서 이것은 에러를 뱉을 것입니다.

Error: /app/node_modules/bcrypt/lib/binding/bcrypt_lib.node: invalid ELF header

첫 번째 문제 해결책, Bcrypt 를 빌드하도록 Dockerfile 을 설정

Dockerfile 이 다음을 실행합니다.

RUN apk add --no-cache make gcc g++ python3 && \
  npm install && \
  npm rebuild bcrypt --build-from-source && \
  apk del make gcc g++ python3

(역자 주: 원문은 python 이지만 현재는 에러를 뱉습니다. 그래서 python3 를 설치하도록 변경하였습니다.)

이렇게 하면, Bcrypt 에 필요한 모든 필수 구성 요소가 설치되고, node_modules가 설치되고, Bcrypt 가 컴파일됩니다. 그런 다음 도터 이미지를 가능한 한 작게 유지하기 위해 (설치되었던) 필수 구성 요소는 제거됩니다.

두 번째 문제 해결책, 다른 OS에 대해 컴파일된 Bcrypt

호스트 파일을 컨테이너에 연결하기 위해, 명명된 볼륨(named volumes)을 생성하는 필드가 있는 docker-compose.yaml 파일을 설정할 수 있습니다. volumes 호스트에 컨테이너와 다른 OS가 있는 경우, 위에서 설명한대로 앱은 (작동에) 실패합니다. node_module 의 Bcrypt가 오류를 일으키고 있다는 것이 문제입니다. 호스트에 설치된 node_modules 가 컨테이너에 연결되지 않도록 (해당 폴더를) 제외하는 방법이 필요합니다.
node_modules 가 호스트에서 컨테이너로 연결도지 않도록 하기 위해 할 수 있는 것은, 익명 볼륨(anonymous volume) 을 사용하는 것입니다.
docker-compose 파일의 스니펫 예시:

volumes:
	# named volume
	- ./your-host-app:/usr/src/app
    # anonymous volume for node_modules only
    - /usr/src/app/node_modules

익명 볼륨은 파일이 저장되는 컨테이너 및 도커 핸들의 디렉토리를 참조합니다. 마운트는 프로젝트 바깥에 있습니다. 이렇게 하면 이미지용으로 빌드된 node_modules가 그대로 유지됩니다.

docker-compose up 을 실행할 때마다, 새로 생성된 컨테이너에 대한 또 다른 익명 볼륨이 생성됩니다. 불행하게도 docker-compose down을 실행해도 익명 볼륨이 제거되지는 않습니다. -v 플래그를 사용하면 named & anonymous 볼륨이 모두 제거됩니다. 만약 named 볼륨을 제거하지 않으려면, 컨테이너를 중지(stop)한 후 docker-compose rm -vf를 실행하세요. 오직 anonymous 볼륨만 제거됩니다.

이 게시물은 docker를 사용하여 개발하는 동안 더 나은 엔지니어링 경험을 만드는 데 도움이 됩니다. 당신이 이 게시글에 더 추가할 것이 있다면 아래에 댓글을 달아주세요. 도움이 되었다면, 잠시 시간을 내어 트위터에 공유 해 주세요.

(번역 끝)

역자후기

NestJS advanced 강의를 듣다 비밀번호 암호화 시 bcryptjs 를 쓰게 되었습니다. 공식 문서에서는 bcrypt 사용을 권장하고 있었습니다.
강의에서는 bcryptjs 를 사용해 해당 문제를 넘어갔지만, 강의에서는 쓸 수 있어도 실무에서 쓰기에는 부적합하다고 느꼈습니다. bcrypt 라이브러리를 도커에서 쓰려다 괜찮은 글을 찾아 번역하게 되었습니다.
해당 글은 2019년에 발행되었지만, 몇 가지 기술적 차이를 제외한다면 정석적인 방법으로 문제를 해결하고 있습니다. bcrypt 대신 bcryptjs 를 쓰라고 하거나, volume 이 문제니 volume 을 지우라는 식의 해결책을 보다 이 글을 보면, 오아시스를 만난 기분이지요.
bcrypt 를 도커 내에 설치하는 과정에서는 OS 내에 기본으로 설치된 프로그램이 당연한 것을 아님을 알았습니다. node_modules 를 volumns 에 설정하는 부분에서는, OS 차이가 개발에 미치는 영향을 배웠습니다. 앞으로 한국에서도 이런, 기술적 깊이에 기반해 문제를 정석으로 해결하는 글을 더 많이 볼 수 있었으면 좋겠습니다.

고민1. be documented 번역

문서화해야하는 으로 번역되었습니다. 다른 문구를 찾기도 어려웠고, 해당 문구를 아예 빼고 읽어도 의미는 이해할 수 있었습니다. 해당 문구의 정확한 의미를 아시는 분은 댓글 달아주시면 바로 반영하도록 하겠습니다.

profile
번역글 위주로 다루려 합니다. 오역 및 기타 사항은 해당 게시글에 댓글로 남겨주시면 답변드리겠습니다. 좋은 하루 되세요!

0개의 댓글