이전 글 : 24-12-29


개요

요즘 바빠서 잘 수정하지 못한다.

모든 도메인을 분리하여 msa로 만들기 위해, 기존의 배포 방식인 docker compose를 따로따로 분리해줄 필요가 있다.

Issue

1. docker compose 파일 분리

기존의 코드는 아래와 같다.

접기/펼치기
version: "3"  
  
services:  
  mysql:  
    container_name: mysql  
    image: mysql:8.0  
    ports:  
      - ${MYSQL_BINDING_PORT}:3306  
    volumes:  
      - ${MYSQL_DATA_PATH}:/var/lib/mysql  
    environment:  
      MYSQL_DATABASE: ${MYSQL_DATABASE}  
      MYSQL_USERNAME: ${MYSQL_USERNAME}  
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}  
    restart: unless-stopped  
  
  redis:  
    container_name: redis  
    image: redis:6.2.6-alpine  
    command: redis-server --requirepass ${REDIS_PASSWORD} --port 6379  
    ports:  
      - ${REDIS_BINDING_PORT}:6379  
    restart: unless-stopped  
  
  mongodb:  
    container_name: mongodb  
    image: mongo  
    ports:  
      - ${DANCE_MONGODB_BINDING_PORT}:27017  
    volumes:  
      - ${DANCE_MONGODB_DATA_PATH}:/data/db  
    environment:  
      MONGO_INITDB_DATABASE: dance  
      MONGO_INITDB_ROOT_USERNAME: root  
      MONGO_INITDB_ROOT_PASSWORD: ${DANCE_MONGODB_PASSWORD}  
      DEV_TRIP_MONGODB_BINDING_PORT: ${DANCE_MONGODB_BINDING_PORT}  
  
  spring:  
    container_name: spring  
    image: dance_spring  
    ports:  
      - ${SPRING_BINDING_PORT}:8080  
    build:  
      context: .  
      dockerfile: Dockerfile  
    depends_on:  
      - mysql  
      - redis  
    volumes:  
      - /data/spring/vod/:/data/vod/  
    environment:  
      MYSQL_BINDING_PORT: ${MYSQL_BINDING_PORT}  
      MYSQL_DATABASE: ${MYSQL_DATABASE}  
      MYSQL_USERNAME: ${MYSQL_USERNAME}  
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}  
      REDIS_BINDING_PORT: ${REDIS_BINDING_PORT}  
      KAFKA1_BINDING_PORT: ${KAFKA1_BINDING_PORT}  
      KAFKA2_BINDING_PORT: ${KAFKA2_BINDING_PORT}  
      KAFKA3_BINDING_PORT: ${KAFKA3_BINDING_PORT}  
      JWT_SECRET_KEY: ${JWT_SECRET_KEY}  
      KAKAO_KEY: ${KAKAO_KEY}  
      KAKAO_REDIRECT_URL: ${KAKAO_REDIRECT_URL}  
      FFMPEG_LOCATION: ${FFMPEG_LOCATION}  
      FFPROBE_LOCATION: ${FFPROBE_LOCATION}  
      REDIS_PASSWORD: ${REDIS_PASSWORD}  
      DANCE_MONGODB_PASSWORD: ${DANCE_MONGODB_PASSWORD}  
      DANCE_MONGODB_BINDING_PORT: ${DANCE_MONGODB_BINDING_PORT}  
      S3_ACCESS_KEY: ${S3_ACCESS_KEY}  
      S3_SECRET_KEY: ${S3_SECRET_KEY}  
      S3_BUCKET_NAME: ${S3_BUCKET_NAME}  
    restart: always  
  
  kafka1:  
    image: confluentinc/cp-kafka:7.6.0  
    hostname: kafka1  
    container_name: kafka1  
    ports:  
      - ${KAFKA1_BINDING_PORT}:9092  
    environment:  
      KAFKA1_BINDING_PORT: ${KAFKA1_BINDING_PORT}  
      KAFKA_BROKER_ID: 1  
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT  
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1  
      KAFKA_PROCESS_ROLES: broker,controller  
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER  
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093  
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT  
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9092  
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka1:9093,2@kafka2:9093,3@kafka3:9093  
      KAFKA_AUTO_LEADER_REBALANCE_ENABLE: "true"  
      KAFKA_DELETE_TOPIC_ENABLE: "true"  
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 100  
      CLUSTER_ID: kafka-docker-cluster-1  
      ALLOW_PLAINTEXT_LISTENER: 'yes'  
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'  
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1  
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1  
      KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"  
      KAFKA_MESSAGE_MAX_BYTES: 20971520  
  kafka2:  
    image: confluentinc/cp-kafka:7.6.0  
    hostname: kafka2  
    container_name: kafka2  
    ports:  
      - ${KAFKA2_BINDING_PORT}:9093  
    environment:  
      KAFKA2_BINDING_PORT: ${KAFKA2_BINDING_PORT}  
      KAFKA_BROKER_ID: 2  
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT  
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1  
      KAFKA_PROCESS_ROLES: broker,controller  
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER  
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093  
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT  
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka2:9092  
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka1:9093,2@kafka2:9093,3@kafka3:9093  
      KAFKA_AUTO_LEADER_REBALANCE_ENABLE: "true"  
      KAFKA_DELETE_TOPIC_ENABLE: "true"  
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 100  
      CLUSTER_ID: kafka-docker-cluster-1  
      ALLOW_PLAINTEXT_LISTENER: 'yes'  
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'  
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1  
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1  
      KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"  
      KAFKA_MESSAGE_MAX_BYTES: 20971520  
  kafka3:  
    image: confluentinc/cp-kafka:7.6.0  
    hostname: kafka3  
    container_name: kafka3  
    ports:  
      - ${KAFKA3_BINDING_PORT}:9094  
    environment:  
      KAFKA3_BINDING_PORT: ${KAFKA3_BINDING_PORT}  
      KAFKA_BROKER_ID: 3  
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT  
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1  
      KAFKA_PROCESS_ROLES: broker,controller  
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER  
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093  
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT  
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka3:9092  
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka1:9093,2@kafka2:9093,3@kafka3:9093  
      KAFKA_AUTO_LEADER_REBALANCE_ENABLE: "true"  
      KAFKA_DELETE_TOPIC_ENABLE: "true"  
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 100  
      CLUSTER_ID: kafka-docker-cluster-1  
      ALLOW_PLAINTEXT_LISTENER: 'yes'  
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'  
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1  
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1  
      KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"  
      KAFKA_MESSAGE_MAX_BYTES: 20971520  
  kafka-ui:  
    image: provectuslabs/kafka-ui:latest  
    container_name: kafka-ui  
    ports:  
      - ${KAFKA_UI_BINDING_PORT}:8080  
    depends_on:  
      - kafka1  
      - kafka2  
      - kafka3  
    environment:  
      KAFKA_CLUSTERS_0_NAME: kafka-docker-cluster-1  
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka1:9092,kafka2:9092,kafka3:9092

이를 서비스마다 나누고, 다른 도커 네트워크 상에 배치되는 것을 막기 위해 host 네트워크를 사용해주었다.

하나의 예시만 들면 충분할 것이라 생각한다.

분리 후 redis 도커 컴포즈 파일

version: "3"
 
services:
  redis:
    container_name: redis
    image: redis:6.2.6-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD} --port 6379
    ports:
      - ${REDIS_BINDING_PORT}:6379
    restart: unless-stopped
 
networks:
  host:
    driver: host
    external: true

2. 환경 배포 환경 만들기 (jenkins)

젠킨스의 groovy 언어를 아름답게 사용해서, 현재 디렉토리의 모든 yml 파일을 배포하는 코드를 꿈꿨다.


하지만 groovy 내에서 자바 코드를 이용하여 현재 디렉토리의 파일들을 파악할 수 있었는데,

자바 코드를 사용하는 블럭인 script를 사용하면, 디렉토리 위치가 바뀌어 현재 디렉토리의 파일을 실행하는 과정이 훨씬 어려워졌다.


예전같았으면 머리를 싸매고 고민했을 수도 있을 부분이지만… 빠르게 넘어가기로 했다.

무엇보다, 파일만 추가한다고 배포가 되는 환경이면 이 또한 위험성이 있기 때문이다.

pipeline {
    agent any
 
    stages {
        stage('Make & Execute Docker Containers') {
            steps {
                script {
                    // 대상 파일 이름 리스트
                    def files = [
                        "kafka",
                        "mongodb",
                        "mysql",
                        "redis"
                    ]
 
                    // compose-files 디렉토리로 이동
                    dir('../compose-files') {
                        files.each { file ->
                            echo "Executing: docker-compose -f ${file}.yml up -d"
                            sh "docker-compose -f ${file}.yml up -d"
                        }
                    }
                }
            }
        }
    }
}

이를 배포하였고, 우여곡절이 많았지만, 환경을 따로 배포하는 데 성공했다.

3. 도메인 배정하기

NPM을 이용할 때의 장점은 쉽게 SSL을 설정할 수 있다는 점도 있다.

이 SSL 인증서를 받기 위해서는 제대로 된 도메인이 필요하다.

나는 가비아에서 사서, 내 프로젝트로 연결해 주었다.

아직 서버를 나누어 올리지 않았기에, SSL 등록은 후순위로 미루겠다.

후기

본격적으로 발전시킬 틀이 이제야 왼성이 되고있다는 생각이 든다.

신년을 맞아 약속도 많아지고, 다른 할일도 많다보니 시간이 계속 미뤄지고 있다.

2025년은 모두 이겨낼 수 있는 한 해가 될 수 있기를 바라고, 프로젝트도 원활하게 진행되었으면 좋겠다.