Kwon's Study Blog !
[Docker] 도커를 이용한 간단한 Node.js 어플 만들기 본문
현재 글은
https://www.inflearn.com/course/%EB%94%B0%EB%9D%BC%ED%95%98%EB%A9%B0-%EB%B0%B0%EC%9A%B0%EB%8A%94-%EB%8F%84%EC%BB%A4-ci/dashboard
을 수강하며 정리한 내용입니다.
문제시 비공개로 처리 하도록 하겠습니다.
따라하며 배우는 도커와 CI환경 - 인프런 | 강의
이 강의를 통해 도커에 대해서 배울 수 있으며, CI 환경을 구성할 수 있습니다., - 강의 소개 | 인프런...
www.inflearn.com
참고 : https://nodejs.org/fr/docs/guides/nodejs-docker-webapp/
(Node.js 공식 홈페이지에서 도커를 이용해서 Node.js를 이용하는 예시)
Node.js 앱 만들기
일단 node-docker-app폴더를 만들고 VS Code에서 열어줍니다.
그다음 아래 명령어를 입력해주고 진행 해주면 package.json 파일이 생성이 됩니다.
npm init
* npm init을 사용하기 위해선 node js가 컴퓨터에 설치되어 있어야 합니다.
package.json (설정 파일)
main : server.js 인것은 npm init에서 index.js -> server.js 로 변경해줘서 그러합니다.
start 와 dependencies는 추가해주었습니다.
{
"name": "nodejs-docker-app",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"express":"^4.17.3"
},
"author": "soon",
"license": "ISC"
}
server.js (시작점)
이렇게 해서 기본적인 Node.js 애플리케이션을 완성하였습니다.
이제 이 Node.js 앱을 도커 환경에서 실행할 수 있도록
도커와 관련된 부분을 만들어 봅시다.!
Dockerfile 작성하기
Node.js 앱을 도커 환경에서 실행하려면 먼저 이미지를 생성하고
그 이미지를 이용해서 컨테이너를 실행한 후, 그 컨테이너 안에서 Node.js 앱을 실행해야 합니다.
Dockerfile
# 베이스 이미지 명시해준다.
# node: (버전)
FROM node:10
# 추가적으로 필요한 파일들을 다운로드 받는다.
RUN npm install
# 컨테이너 시작 시 실행 될 명령어를 명시해준다.
CMD ["node","server.js"]
저번에는 alpine 베이스 이미지를 썻는데 이번엔 왜 node 이미지를 쓴 이유???
먼저 베이스 이미지를 alpine으로 해서 build를 해보면 에러가 나옵니다. (npm not found)
그 이유는 alpine은 가장 최소화의 경량화된 파일들이 들어있기에
npm을 위한 파일이 들어있지 않아 -> RUN 부분에서 npm install을 할 수가 없습니다.
그렇다면 npm install은 무엇일까요 ?
일단 npm은 Node.js 로 만들어진 모듈을 웹에서 받아서 설치해주고 관리해주는 프로그램입니다.
npm install은 package.json에 적혀있는 종속성을 웹에서 자동으로 다운 받아서 설치해주는 명령어입니다.
결론적으로 현재 Node.js 앱을 만들 때 필요한 모듈들을 다운받아 설치하는 역할을 합니다.
일단 한번 dockerfile을 build를 해봅시다.
docker build --no-cache --progress=plain ./
현재 도커 버전이 높아 빌드가 원활히 되지만?
--no-cache --progress=plain 이 옵션을 주게되면
분명히 같은 디렉토리 안에 있는데... 위와같이 package.json이 없다는 경고가 나옵니다.
Package.json 파일이 없다고 나오는 이유
도커 파일을 build 할 때 Node 베이스 이미지로 임시 컨테이너를 생성합니다.
그리고 그 임시 컨테이너로 이미지를 만듭니다.
하지만, 그 이미지엔 package.json파일이 없기 때문에 임시 컨테이너에도 포함 돼있지 않습니다.
그래서 package.json은 컨테이너 밖에 있는 상황이 됩니다.
즉 다시 정리를 해보자면
이러한 이유 때문에 COPY를 이용해서 package.json 을 컨테이너 안으로 넣어야 합니다.
FROM node:10
# local 파일에 있는 package.json을 컨테이너 ./ 에 복사.
COPY package.json ./
RUN npm install
CMD ["node","server.js"]
이제 다시 build를 해봅시다.
docker build -t ksoon1985/node-app ./
그리고 실행을 시켜보겠습니다.
docker run ksoon1985/node-app
아까 package.json 처럼 server.js 를 못찾는다고 에러가 발생합니다.
다시 dockerfile을 수정해줍시다.
FROM node:10
# local에 있는 모든 파일을 컨테이너 ./ 에 복사.
COPY ./ ./
RUN npm install
CMD ["node","server.js"]
그리고 다시 실행을 시켜주면
server.js가 잘 실행되는 것을 확인할 수 있습니다.
그러나
브라우저를 통해 localhost:8080으로 접근을 하려 했으나 접근이 안됩니다...
생성한 이미지로 애플리케이션 실행 시 접근이 안되는 이유?
위에서 이미지를 만들 때 로컬에 있던 파일(package.json, server.js) 등을 컨테이너에 복사(COPY) 했었습니다.
그것과 비슷하게 네트워크도
로컬 네트워에 있던 것을 컨테이너 내부에 있는 네트워크에 연결 시켜줘야 합니다.
* p : port option
한번 5000번 포트를 이용해서 애플리케이션에 접속해 봅시다.
docker run -p 5000:8080 ksoon1985/node-app
브라우저에 localhost:5000 하면 잘 접속하는 것을 확인할 수 있습니다.
Working Directory 명시해주기
위에서 만든 Node 애플리케이션의 실행중인 컨테이너의 터미널로 들어가보겠습니다.
docker run -it ksoon1985/node-app sh
그리고 ls 명령어를 입력하면
아래와 같은 파일들이 보입니다.
이 중 COPY 를 해서 컨테이너 안으로 들어온 것은
Dockerfile, package.json, package-lock.json, node_module, server.js 등 이 있습니다.
혹시 이 중에서 원래 베이스 이미지에 있던 파일과 같다면 원래 있던 폴더에 덮어 써져 버립니다.
그리고 모든 파일이 한 디렉토리에 들어가다 보니 정리 정돈이 안돼있습니다.
그래서 모든 애플리케이션을 위한 소스들은 워크 디렉토리를 따로 만들어서 보관합니다.
도커 파일을 다시 다음과 같이 수정해줍니다.
FROM node:10
# local에 있는 모든 파일을 컨테이너 ./ (/usr/src/app) 에 복사.
WORKDIR /usr/src/app
COPY ./ ./
RUN npm install
CMD ["node","server.js"]
다시 빌드하고 실행중인 컨테이너 터미널에 들어가서 ls 명령어를 입력해보겠습니다.
docker build -t ksoon1985/node-app ./
docker run -it ksoon1985/node-app sh
ls
위처럼 애플리케이션과 관련된 파일들은 WORKDIR에 명시한 /usr/src/app 에 들어간 것을 볼 수 있습니다.
이는 package.json이 /usr/src/app 에 들어가서 거시서 npm install이 이뤄집니다.
그러면서 node_modules파일도 생기고 ... 합니다.
애플리케이션 소스 변경으로 다시 빌드하는 것에 대한 문제점
dockerfile 이든 server.js든 변경이 됬을 때
변경된 부분을 애플리케이션에 반영시키려면
-> 다시 빌드하고 다시 실행해야 합니다.
이는 너무 비효율적입니다.
dockerfile이면 설정정보가 바뀐것이기 때문에 어쩔 수 없지만
또 package.json 같은경우엔 종속성이 바뀐 것일 수 있어 어쩔 수 없지만
server.js 같은 경우는 설정정보도 아니고, 종속성이 더 추가되거나 빼진 것도 아닌데
다시 빌드하면서 종속성도 다시 받고 하는 이 과정이 너무 불필요합니다.
애플리케이션 소스 변경으로 재 빌드 시 효율적으로 하는 법
위와 같이 dockerfile을 변경합시다.
FROM node:10
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY ./ ./
CMD ["node","server.js"]
원래, 모듈을 다시 받는 것은 모듈에 변화가 생겨야만 다시 받아야 하는데
소스 코드에 조금의 변화만 생겨도 모듈 전체를 다시 받는 문제점이 있었습니다.
위처럼 변경 하면 npm install 할 때 불필요한 다운로드를 피할 수 있습니다.
이렇게 모듈은 모듈에 변화가 생길 때만 다시 다운로드 해주며
소스코드에 변화가 생길 때 모듈을 다시 받는 현상을 없애 줬습니다.
다시 한번 정리하자면
COPY ./ ./
RUN npm install
=> 복사되는 파일 중 하나라도 변경된 사항이 있다면
npm install 에서 package.json 에 있는 종속성들이 다시 다운 받어짐.
COPY package.json ./
RUN npm install
COPY ./ ./
=> package.json 파일을 먼저 옮기고 변경이 됐다면 npm install 에서 종속성들을 다시 다운 받음.
아니라면 캐시에 있는걸 가져옴. 그리고 다시 모든 파일을 복사 시킴.
Docker Volumn
애플리케이션 소스 코드를 변경할 때 모듈을 다시 받는 현상은 없애주었지만 ...
여전히 빌드를 다시 해야하는 문제는 남아있습니다.
무슨... 소스 코드 하나 반영하는데
dockerfile을 다시 빌드하고 컨테이너를 다시 실행해줘야지 변경된 소스가 화면에 반영 됐었습니다.
이를 해결하기 위해 도커 볼륨을 이용합니다.
volumn을 사용해서 애플리케이션을 실행하는 방법은 다음과 같습니다.
window os 사용 환경에선 $(pwd) -> "%cd%" 로 변경해주면 됩니다.
docker run -p 5000:8080 -v /usr/src/app/node_modules -v "%cd%":/usr/src/app ksoon1985/node-app
위의 명령어로 컨테이너를 실행하면
빌드하지않고 변경된 소스코드를 반영시킬 수 있습니다.
물론 컨테이너를 끄고 켜야 합니다. ~ (나중에 compose와 nodemon을 이용하면 해결 가능 ! )
지금까지 도커를 이용해서 간단한 Node.js 애플리케이션을 실행 해봤습니다.
1. Node.js 앱 만들기
2. Dockerfile 작성하기
3. Package.json 파일이 없다고 나온 이유
4. 생성한 이미지로 애플리케이션이 접근 안되는 이유
5. Working Directory 명시해주기
6. 애플리케이션 소스 변경으로 다시 빌드하는 것에대한 문제
7. 애플리케이션 소스 변경으로 재빌드 시 효율적으로 하는 법
8. Docker Volumn
을 알아보았고
다음 글에선 Docker Compose에 대해 알아보겠습니다. !
'Docker' 카테고리의 다른 글
[Docker] 간단한 어플을 실제로 배포해보기(개발 환경 부분) (0) | 2022.03.29 |
---|---|
[Docker] Docker Compose (0) | 2022.03.26 |
[Docker] 직접 도커 이미지 만들어 보기 (0) | 2022.03.24 |
[Docker] 기본적인 Docker Client 명령어 알아보기 (0) | 2022.03.24 |
[Docker] 이미지로 컨테이너 만들기 (0) | 2022.03.23 |