2024-12-16 CH-6 최종 프로젝트 13 MSA 서버 docker-compose 적용 및 트러블 슈팅

MOON·2025년 1월 2일
0

내일배움캠프 과제

목록 보기
46/48

오늘은 MSA 분산 서버를 각각의 dockerfile을 작성하고 docker-compose도 적용해 보았습니다.

dockerfile 코드

# 빌드 스테이지
FROM node:20-alpine AS builder
WORKDIR /app

# 워크스페이스 설정 파일들 복사
COPY package.json yarn.lock turbo.json ./
COPY apps/account/package.json ./apps/account/
COPY packages/common ./packages/common
COPY packages/modules ./packages/modules

# 의존성 설치
RUN yarn install --frozen-lockfile

# account 서비스 소스 복사
COPY apps/account ./apps/account

# Protobuf 파일들 복사
COPY packages/common/protobufs ./protobufs

# 공통 환경 변수 파일 복사
COPY packages/common/config/.env ./packages/common/config/.env

# 빌드
WORKDIR /app/apps/account
RUN yarn add glob@^11.0.0 esbuild del-cli --dev
RUN NODE_ENV=development yarn build

# 실행 스테이지
FROM node:18-alpine AS runner
WORKDIR /app

# package.json 파일들 복사
COPY package.json yarn.lock turbo.json ./
COPY apps/account/package.json ./apps/account/
COPY packages/common ./packages/common
COPY packages/modules ./packages/modules

# 빌드된 파일들 복사
COPY --from=builder /app/apps/account/dist ./dist
COPY --from=builder /app/protobufs ./protobufs
COPY --from=builder /app/packages/common/config/.env ./packages/common/config/.env
COPY --from=builder /app/node_modules ./node_modules

# 실행 환경 설정
ENV NODE_ENV=production
EXPOSE 6020

# 실행
CMD ["node", "dist/account.server.js"]

package.json 코드

{
  "name": "account",
  "version": "1.0.0",
  "description": "회원서비스 담당 서버",
  "main": "account.server.js",
  "type": "module",
  "scripts": {
    "account:start": "node dist/account.server.js",
    "dev": "node src/account.server.js",
    "build": "node esbuild.config.js",
    "clean": "del-cli dist"
  },
  "dependencies": {
    "@peekaboo-ssr/classes": "*",
    "@peekaboo-ssr/config": "*",
    "@peekaboo-ssr/events": "*",
    "@peekaboo-ssr/utils": "*",
    "@peekaboo-ssr/commands": "*",
    "@peekaboo-ssr/error": "*",
    "bcrypt": "^5.1.1",
    "jsonwebtoken": "^9.0.2",
    "uuid": "^11.0.3"
  }
}

esbuild.config.js

import { glob } from 'glob';
import * as esbuild from 'esbuild';

try {
  const entryPoints = await glob('src/**/*.js');

  await esbuild.build({
    entryPoints,
    bundle: true,
    outdir: 'dist',
    platform: 'node',
    target: 'node18',
    format: 'esm',
    sourcemap: true,
    external: [
      // 실제 사용하는 의존성
      '@peekaboo-ssr/classes',
      '@peekaboo-ssr/config',
      '@peekaboo-ssr/events',
      '@peekaboo-ssr/utils',
      '@peekaboo-ssr/commands',
      '@peekaboo-ssr/error',
      'bcrypt',
      'jsonwebtoken',
      'uuid',
      'fs',
      'pidusage',
      // protobuf 관련 (공통 의존성)
      'protobufjs',
      'protobufjs/minimal',
      'express',
      'prom-client',
    ],
    define: {
      'global.XMLHttpRequest': 'undefined',
      'process.env.NODE_ENV': '"production"',
    },
    inject: ['./esm-shims.js'],
  });
} catch (error) {
  console.error('Build failed:', error);
  process.exit(1);
}

각각의 서비스 파일안에 dockerfile, esbuild.config.js, package.json 파일들이 각각의 의존성에 맞게 코드를 작성하여 만들어 두었습니다.

docker-compose 코드

services:
  dedicated:
    build:
      context: .
      dockerfile: apps/game/dedicated/dockerfile
    image: dedicated_server:latest
    command: echo "Image build complete, no container execution."

  distributor:
    build:
      context: .
      dockerfile: apps/distributor/dockerfile
    container_name: distributor
    hostname: distributor
    networks:
      - peekaboo-network
    ports:
      - '6030:6030'
      - '8030:8030'
    env_file:
      - ./packages/common/config/.env

  game:
    build:
      context: .
      dockerfile: apps/game/master/dockerfile
    container_name: game
    hostname: game
    networks:
      - peekaboo-network
    ports:
      - '6050:6050'
      - '8050:8050'
    env_file:
      - ./packages/common/config/.env
    depends_on:
      - distributor
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  lobby:
    build:
      context: .
      dockerfile: apps/lobby/dockerfile
    container_name: lobby
    hostname: lobby
    networks:
      - peekaboo-network
    ports:
      - '6010:6010'
      - '8010:8010'
    env_file:
      - ./packages/common/config/.env
    depends_on:
      - game

  account:
    build:
      context: .
      dockerfile: apps/account/dockerfile
    container_name: account
    hostname: account
    networks:
      - peekaboo-network
    ports:
      - '6020:6020'
      - '8020:8020'
    env_file:
      - ./packages/common/config/.env
    depends_on:
      - lobby

  session:
    build:
      context: .
      dockerfile: apps/session/dockerfile
    container_name: session
    hostname: session
    networks:
      - peekaboo-network
    ports:
      - '6040:6040'
      - '8040:8040'
    env_file:
      - ./packages/common/config/.env
    depends_on:
      - account

  gateway:
    build:
      context: .
      dockerfile: apps/gateway/dockerfile
    container_name: gateway
    hostname: gateway
    networks:
      - peekaboo-network
    ports:
      - '6000:6000'
      - '8000:8000'
    env_file:
      - ./packages/common/config/.env
    depends_on:
      - session

networks:
  peekaboo-network:
    driver: bridge
  • docker-compose.yml 파일은 가장 최상위에 위치해 있으며 해당 파일을 실행하여 한번에 build를 하면서 실행까지하게 만들어두었습니다.
  • 데디게이트 서버는 이미지 빌드만을 실행하고 컨테이너 생성은 중단하였습니다.
  • MSA에서 실행순서도 맟추어 주었습니다.

트러블 슈팅

도커를 사용하면서 트러블 슈팅을 이번에 최종 프로젝트 브로셔 작성할때 같이 notion에 작성해 보았습니다.

오늘의 회고
이번 docker를 도입할떄 ai의 힘을 많이 빌렸습니다. 빠르게 프로젝트에 적용해보고 싶은 욕심이 있었고 어떻게든 써보고 싶은 마음이 컸던거 같습니다. 그럼에도 불구하고 수많은 시행착오를 격고 여러 구글링을 통해 명령어, 키워드도 찾아보고 어떻게 사용하는지에 대해 어느정도 감을 익혔던 시간이였습니다.

지금와서 생각해보니 추후 git action을 이용하여 ci/cd를 간단하게 구현해 보았습니다. 현재 docker-compose에서 데디게이트 서버 파일을 이미지 빌드만하는 것을 action에서 하면 될 거 같다는 생각이 드네요..하핫 그래도 이참에 사용해봤다는 경험이 좋았던거 같습니다. 굿

오늘도 화이팅!

profile
안녕하세요

0개의 댓글

관련 채용 정보