1. 노드 애플리케이션 도커 이미지 만들기
노드 애플리케이션 생성
- 적당한 디렉토리를 생성해 노드 패키지를 설정
npm init
pnpm init
…
package.json
파일에 스크립트 추가"start": "node index.js"
- express 애플리케이션 만들기
- express 모듈 설치 이후
const express = require("express"); const app = express(); const PORT = 8080; app.get("/", (req, res) => { res.send("Hello World"); }); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
도커파일 작성하기
FROM node:20-alpine RUN npm install -g pnpm RUN pnpm install CMD ["pnpm", "start"]
- 다음과 같이 도커파일 작성 시, 실행 환경에
package.json
을 찾을 수 없다는 에러 발생 - 노드앱 파일스냅샷에
package.json
이 존재하지 않기 때문에 컨테이너 환경에서 확인 ❌
- 마찬가지로
index.js
파일도 찾을 수 없다는 에러 발생
- 해결방법 : 파일스냅샷에
pacakge.json
파일을 복사
FROM node:20-alpine COPY ./ ./ RUN npm install -g pnpm RUN pnpm install CMD ["pnpm", "start"]
- 도커 이미지화 :
docker build ./
- 태그 추가:
docker build -t yeongsan/test ./
- 도커 실행 :
docker run -it yeongsan/test
위 과정을 진행 후 브라우저에서
http://localhost:8080
으로 접근해보면 접근이 불가한 것을 확인 할 수 있다.생성한 도커이미지로 애플리케이션 접근하기
- 로컬 네트워크와 컨테이너 네트워크를 연결시켜주는 작업이 필요
- 포트 맵핑 :
docker run -p 5000:8080 yeongsan/test
- 컨테이너 네트워크 8080포트를 로컬 네트워크 5000 포트로 매핑시켜 이미지를 실행하겠다
Working Directory 설정하기
Working Directory
: 이미지 안에서 애플리케이션 소스 코드를 보유할 디렉토리
- Working Directory 설정하기 전 파일시스템 조회
docker run -it yeongsan/test ls
- 스냅샷의 루트 경로 파일들과 애플리케이션 내부의 파일 이름이 중복될 경우 파일 삭제될 우려
- Working Directory 설정
docker build -t yeongsa/test ls
- 이전과 달리 루트 디렉토리에 프로젝트 파일을 복사하지 않은 것을 확인
FROM node:20-alpine WORKDIR /user/src/app COPY ./ ./ RUN npm install -g pnpm RUN pnpm install CMD ["pnpm", "start"]
소스코드 수정 시 도커 재빌드 효율적으로 하기
- 현재까지 도커 컨테이너 애플리케이션 실행 흐름
- 소스코드 수정 →
docker build .
→ 도커 이미지 생성 →docker run
→ 컨테이너 생성 후 앱 실행
- detect 모드로 실행 :
docker run -d -p 5000:8080 yeongsan/test
비효율성
- 도커파일에서 프로젝트 전체 파일을 복사하기 때문에, 이미지 빌드시 매번 node_modules의 종속성을 반복해서 설치
- 소스코드만 수정해도 종속성 설치
비효율성 개선하기
- 종속성 설치 이후에 모든 파일을 복사하는 방식으로 Dockerfile 수정
- 소스 코드에만 변화가 있을때는 종속성 설치 ❌
FROM node:20-alpine WORKDIR /user/src/app COPY package.json ./ RUN npm install -g pnpm RUN pnpm install COPY ./ ./ CMD ["pnpm", "start"]
도커 볼륨을 이용해 파일 참조하기
- 도커 볼륨을 이용하면 파일을 참조하기 때문에 소스코드의 변화를 감지해
- 도커 이미지 빌드를 반복하지 않아도 된다
docker run -p 5000:8080 -v /usr/src/app/node_modules -v$(pwd):/usr/src/app yeongsan/test
- 호스트(도커) 디렉토리에
node_modules
존재하지 않기에 컨테이너에 맵핑하지 말라는 의미 pwd
경로에 있는 디렉토리 or 파일을/usr/src/app
경로에서 참조하라는 의미
Docker Compose 알아보기
Docker Compose란
- 다중 컨테이너 애플리케이션을 정의하고 실행하기 위한 도구
노드 애플리케이션 + 레디스 실행하기
- Redis(REmote Dictionary Server) : 메모리 기반 key-value 구조 데이터 저장소
- 데이터를 메모리에 저장해 빠르게 조회 가능한 비관계형 데이터베이스(NoSQL)
- MySQL과 같은 데이터베이스와 비교해 조회 속도가 월등하며, 데이터를 영속적으로 보관이 가능해 데이터 유지가 가능하다는 장점이 있다.
서버코드 작성
const express = require("express"); const redis = require("redis"); const client = redis.createClient({ socket: { host: "redis-server", port: 6379, }, }); const app = express(); app.get("/", async (req, res) => { await client.connect(); let count = await client.get("count"); if (!count) count = 0; console.log("Count: " + count); res.send("새로고침 시 카운트가 1씩 올라갑니다. 카운트: " + count); await client.set("count", parseInt(count) + 1); await client.disconnect(); }); app.listen(8080, () => { console.log("Server is running on port 8080"); });
Dockerfile 작성
FROM node:20-alpine WORKDIR /usr/src/app COPY ./ ./ RUN npm install -g pnpm RUN pnpm install CMD ["pnpm", "start"]
- 해당 도커 파일 기반으로 도커 실행시 연결할 레디스 서버를 찾을 수 없다는 에러 발생
docker compose 파일 작성하기
- 컨테이너 간 설정 필요
# docker-compose.yml services: redis-server: image: redis # 레디스 이미지 파일 사용 node-app: build: . ports: - 5000:8080 # 포트맵핑 depends_on: - redis-server # redis-server와 의존 관계 명시
docker compose up
docker compose 컨테이너 정지시키기
docker compose down
docker compose up with build option
docker compose up
: 이미지가 없을때 이미지를 빌드하고 컨테이너 시작
docker compose up —build
: 이미지가 있든 없든 이미지를 빌드하고 컨테이너 시작