Docker

Node 마이크로서비스를 Docker 컨테이너화 해보자 [REST]

rexondex 2024. 11. 14. 13:12

 

노드 마이크로서비스를 도커 컨테이너화하여 실행 성공하는것이 이번 게시글의 목표입니다.

 

# 준비물 :


폴더 구조

 

0. Node 프로젝트를 초기화하고 express와 axios 설치합니다.

# Node 프로젝트 초기화 (package.json 파일 생성)
npm init -y

# express와 axios 설치
npm install express axios

 

1. index.js 작성합니다

const express = require('express');
const axios = require('axios');
const app = express();
const PORT = 3000;

const SPRINGBOOT_API = 'http://userservice:8080/users';  // Spring Boot 서비스 이름을 올바르게 수정

app.use(express.static('public'));  // public 폴더에 HTML, CSS, JS 파일 배치
app.use(express.json());

// Spring Boot에서 데이터 가져오기
app.get('/api/get-data', async (req, res) => {
    try {
        const response = await axios.get(SPRINGBOOT_API);  // 수정된 API 주소
        res.json(response.data);
    } catch (error) {
        console.error(error);  // 오류 로깅 추가
        res.status(500).json({ error: 'Failed to fetch data' });
    }
});

// Spring Boot에 데이터 추가하기
app.post('/api/add-data', async (req, res) => {
    try {
        const { name, email } = req.body;
        const response = await axios.post(SPRINGBOOT_API, { name, email });  // 수정된 API 주소
        res.json(response.data);
    } catch (error) {
        console.error(error);  // 오류 로깅 추가
        res.status(500).json({ error: 'Failed to add data' });
    }
});

app.listen(PORT, () => {
    console.log(`Node.js server running on port ${PORT}`);
});

 

2. 루트 경로에서 public 폴더를 만들고 안에 index.html을 작성합니다

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Data Management</title>
    <script>
      async function fetchData() {
        const response = await fetch("/api/get-data");
        const data = await response.json();
        document.getElementById("data").innerText = JSON.stringify(
          data,
          null,
          2
        );
      }

      async function addData() {
        const name = document.getElementById("name").value;
        const email = document.getElementById("email").value; // email 입력 받기
        await fetch("/api/add-data", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ name, email }), // name과 email을 함께 보냄
        });
        fetchData();
      }
    </script>
  </head>
  <body>
    <h1>Manage Data</h1>
    <input type="text" id="name" placeholder="Enter name" />
    <input type="email" id="email" placeholder="Enter email" />
    <!-- 이메일 입력 -->
    <button onclick="addData()">Add Data</button>
    <button onclick="fetchData()">Refresh</button>
    <pre id="data"></pre>
  </body>
</html>

 

3. Dockerfile 작성합니다.

# node/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["node", "index.js"]

 

4. 도커 이미지를 빌드합니다.

// 자신의 노드 프로젝트명으로 대체하세요
docker build -t 프로젝트명 .

 

5. 컨테이너를 실행합니다.

docker run -d -p 3000:3000 --name 프로젝트명-container 프로젝트명

/*
-d: 백그라운드에서 컨테이너를 실행합니다.
-p 3000:3000: 호스트의 포트 3000을 컨테이너의 포트 3000에 매핑합니다.
--name 프로젝트명-container: 프로젝트명-container라는 이름으로 컨테이너를 지정합니다.

프로젝트명: 이전에 docker build -t 명령어에서 사용한 이미지 이름입니다.
*/

 

* myapp 예시 *

// 이미지 빌드
docker build -t my-app .

// 컨테이너 실행
docker run -d -p 3000:3000 --name my-app-container my-app

// 실행중인 컨테이너 확인
docker ps

// 애플리케이션 접속
http://localhost:3000

// 컨테이너 중지
docker stop my-node-container

// 컨테이너 삭제
docker rm my-node-container

 


:: 실행결과 ::

localhost:3000 / 도커 컨테이너 실행 확인

 

JSON 문자열에서 "error"가 난 이유는

이 노드 마이크로서비스는 스프링부트 8080포트에 통신하지만,

현재 스프링부트 컨테이너가 실행되지 않았기 때문입니다.

 

스프링부트 컨테이너와 노드 컨테이너를 docker-compose로 묶으면 같은 환경에서 동시에 실행할 수 있습니다.

도커 컴포즈로 실행하면, 스프링부트의 H2DB에 노드 컨테이너가 데이터를 조작할 수 있게 됩니다.

 

RestController로 가는 URI가 제대로 매핑되있다면, 두 컨테이너를 동시에 실행하여 노드의 3000번 포트에서 스프링부트 8080번 포트로 통신할 수 있습니다.

 


 

[ # 참고 : Docker로 스프링부트 jar를 컨테이너화 해보자 ]

 

이 스프링부트 컨테이너와 노드 컨테이너를 docker-compose로 묶어 같은 환경에서 실행할 수 있습니다.

https://rexondex.tistory.com/36

 

Docker로 스프링부트 jar를 컨테이너화 해보자 [H2DB]

자바 스프링부트와 AWS 클라우드 배포를 생각하던 중 도커와 쿠버네티스의 역할이 궁금해졌습니다. 그래서 이번엔 도커에 대한 궁금증을 풀기 위해 스프링부트 jar 파일을 도커 컨테이너화하고,

rexondex.tistory.com

 


:: 정리 ::

위의 코드는 Node.js 미들웨어 마이크로서비스로서, 다음 목적을 갖습니다.

Spring Boot API 활용: axios를 사용해 Spring Boot 컨테이너의 REST API (http://userservice:8080/users)와 상호작용합니다. 이 Node.js 서비스는 Spring Boot 서비스의 API를 호출하여 데이터를 가져오거나 추가할 수 있습니다.

Static 파일 제공: public 폴더를 정적 파일 경로로 설정하여, HTML, CSS, JavaScript 파일 등을 제공합니다. 이렇게 하면 Node.js 서버가 사용자 인터페이스를 제공할 수 있습니다.

API 엔드포인트 제공: /api/get-data 및 /api/add-data 엔드포인트를 통해 프런트엔드 요청을 처리하고, 필요한 경우 Spring Boot 서비스와의 데이터 전송을 중개합니다.

즉, 이 Node.js 서버는 Spring Boot API와 프론트엔드 간의 미들웨어 역할을 하는 마이크로서비스로 작동하며, 사용자가 Spring Boot API와 간접적으로 상호작용할 수 있도록 돕습니다.