Spring Microservice

Configserver 서버 프로젝트

헬로우월드 2025. 3. 13. 13:54

🚀Spring Cloud Config Server 구축 및 최적화된 Docker 이미지 생성 

마이크로서비스 아키텍처(MSA)를 운영할 때 가장 중요한 요소 중 하나는 구성 관리(Configuration Management)입니다. 여러 개의 마이크로서비스가 각각의 설정(applicaiton.properties[또는 yml]) 파일을 관리하는 것은 유지보수 측면에서 비효율적일 수 있습니다. 이를 해결하기 위해 Spring Cloud Config Server를 활용하면 중앙 집중식으로 설정을 관리할 수 있습니다.

이 글에서는 Spring Cloud Config Server 구축부터 Docker 최적화 빌드까지 자세히 살펴보겠습니다.

 

📌 프로젝트 개요

이 프로젝트는 Spring Cloud Config Server를 사용하여 마이크로서비스의 구성 데이터를 중앙에서 관리하는 역할을 합니다.

 

✅ 핵심 기능

✔ Spring Cloud Config Server를 이용한 구성 관리

✔ Spring Boot Actuator를 활용한 서비스 모니터링

✔ Docker를 활용한 컨테이너 이미지 빌드 및 배포 지원

🗂️ 파일 구성

📦 chapter05
├── 📂 configserver             # Spring Cloud Config Server 프로젝트
│   ├── 📂 src
│   │   ├── 📂 main
│   │   │   ├── 📂 java/com/optimagrowth/configserver
│   │   │   │   ├── ConfigServerApplication.java  # Config Server 메인 클래스
│   │   │   ├── 📂 resources
|   |   |   |   |── 📂config
│   │   │   │   ├── application.yml              # Config Server 설정 파일(미사용)
│   │   │   │   ├── bootstrap.yml                # Spring Cloud Config를 위한 설정
│   │   ├── 📂 test
│   ├── pom.xml                                  # Maven 프로젝트 파일
│   ├── Dockerfile                               # Docker 이미지 빌드 파일
│   ├── README.md                                # 프로젝트 설명 파일
│
├── 📂 licensing-service       # 라이선스 관리 서비스 (Licensing Service)
│
├── 📂 docker                        # Docker compose 관련 설정
├── pom.xml                          # 전체 프로젝트 Maven 파일
├── build-for-m1.sh                  # mac os를 위한 빌드 스크립트 파일
└── README.md                        # 프로젝트 전체 설명 파일

🏗 1. pom.xml 분석

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.optimagrowth</groupId>
    <artifactId>configserver</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Configuration Server</name>
    <description>Configuration Server</description>

    <properties>
        <java.version>17</java.version>
        <docker.image.prefix>ostock</docker.image.prefix>        
        <spring-cloud.version>2024.0.0</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>        
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- This plugin is used to create a docker image and publish the image to docker hub-->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.13</version>
                <configuration>
                    <repository>${docker.image.prefix}/${project.artifactId}</repository>
                    <tag>${project.version}</tag>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
                <executions>
                    <execution>
                        <id>default</id>
                        <phase>install</phase>
                        <goals>
                            <goal>build</goal>
                            <goal>push</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

🏗 pom.xml 주요 내용 분석

1️⃣ 프로젝트 속성 설정

<properties>
    <java.version>17</java.version>
    <docker.image.prefix>ostock</docker.image.prefix>        
    <spring-cloud.version>2024.0.0</spring-cloud.version>
</properties>
  • java.version: Java 17 사용
  • docker.image.prefix: Docker 이미지를 빌드할 때 ostock/ 프리픽스 사용
  • spring-cloud.version: Spring Cloud 2024.0.0 사용

2️⃣ 의존성 추가

<dependencies>
    <!-- Spring Cloud Config Server -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>

    <!-- Spring Boot Actuator (서비스 모니터링 기능) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <!-- Spring Boot Test (JUnit 테스트 지원) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>        
</dependencies>

✅ 주요 라이브러리 설명

  1. Spring Cloud Config Server
    • spring-cloud-config-server는 Config Server 기능을 제공
    • 설정 파일을 Git 또는 Vault에서 가져올 수 있음
  2. Spring Boot Actuator
    • spring-boot-starter-actuator는 애플리케이션 모니터링을 위한 엔드포인트 제공
    • /actuator/health, /actuator/info 등의 엔드포인트 활성화 가능
  3. Spring Boot Test
    • spring-boot-starter-test는 테스트 코드 작성 시 필요한 라이브러리
    • junit-vintage-engine을 제외하여 JUnit 4가 아닌 JUnit 5를 기본 사용

3️⃣ Spring Cloud 의존성 관리

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
  • spring-cloud-dependencies를 import하여 Spring Cloud의 다양한 모듈을 쉽게 추가 가능
  • 버전 충돌 방지 및 일관성 유지

4️⃣ 빌드 플러그인 설정

<build>
    <plugins>
        <!-- Spring Boot Maven Plugin -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>

        <!-- Docker 이미지 빌드 및 푸시 플러그인 -->
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.4.13</version>
            <configuration>
                <repository>${docker.image.prefix}/${project.artifactId}</repository>
                <tag>${project.version}</tag>
                <buildArgs>
                    <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                </buildArgs>
            </configuration>
            <executions>
                <execution>
                    <id>default</id>
                    <phase>install</phase>
                    <goals>
                        <goal>build</goal>
                        <goal>push</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

✅ 빌드 플러그인 설명

  1. Spring Boot Maven Plugin
    • spring-boot-maven-plugin은 Spring Boot 애플리케이션을 JAR 파일로 패키징
    • 실행 가능한 JAR 파일 생성
  2. Dockerfile Maven Plugin (Spotify:세계 최대 음원 제공 사이트)
    • dockerfile-maven-plugin은 Maven을 통해 Docker 이미지를 빌드하고 푸시
    • docker.image.prefix 설정값을 사용하여 ostock/configserver 이미지로 태깅
    • install 단계에서 자동으로 Docker 이미지 빌드 및 푸시

📝 configserver 프로젝트의 pom.xml의 특징

✔ Spring Boot 3.4.3 & Spring Cloud 2024.0.0 사용
✔ Spring Cloud Config Server 설정 포함
✔ Spring Boot Actuator를 사용한 서비스 모니터링 기능 추가
✔ Maven 의존성 관리를 활용하여 안정적인 버전 관리
✔ Docker 이미지 빌드 및 배포 자동화 설정

🛠 bootstrap.yml 파일 설정 분석

spring:
  application:
    name: config-server
  profiles:
    active: vault #, git, native
  cloud:
    config:
      server:
        encrypt.enabled: false
        native:
          search-locations: classpath:/config
        git:
          default-label: master(현재는 github의 디폴트 브렌치 이름은 main임)
          uri: https://github.com/klimtever/config.git
          searchPaths: licensingservice
        vault:
          authentication: TOKEN
          token: myroot  # Docker에서 Vault를 실행할 때 지정한 root 토큰
          port: 8200
          host: ${VAULT_HOST} # vault 서버가 컨테이너에서 실행됨. 그러므로 dns를 이용함.
          scheme: http
          kv-version: 2
          profile-separator: /

server:
  port: 8071

logging:
  level:
    org.springframework.cloud.config.server: DEBUG
    org.springframework.web.client.RestTemplate: DEBUG

encrypt:
  key: fje83Ki8403Iod87dne7Yjsl3THueh48jfuO9j4U2hf64Lo

#Enable all Spring Boot Actuator endpoints.
management:
  endpoints:
    web:
      exposure:
        include: "health,info,configprops,env"
  endpoint:
    health:
      show-details: always

📜 주요 설정 분석

🏷️ 1) Spring 애플리케이션 설정

spring:
  application:
    name: config-server
  profiles:
    active: vault #, git, vault

🔹 application.name: config-server
→ 이 Config Server의 애플리케이션 이름을 config-server로 설정합니다.

🔹 profiles.active: vault
→ 현재 활성화된 프로필을 vault로 지정했습니다.

  • Git 또는 native(config 서버의 로컬 파일 시스템)를 사용할 수도 있지만, 현재는 주석 처리되어 있음 (# git, native).
  • Config Server가 HashiCorp Vault에서 설정을 가져오도록 지정함.

🔑 2) Spring Cloud Config Server 설정

  cloud:
    config:
      server:
        encrypt.enabled: false
        native:
          search-locations: classpath:/config
        git:
          default-label: master
          uri: https://github.com/klimtever/config.git
          searchPaths: licensingservice

🔹 Git 설정 (주석 처리됨)

  • default-label: master → Git의 master 브랜치를 기본 설정으로 사용.
  • uri: https://github.com/klimtever/config.git → Git에서 설정을 불러올 저장소의 URL.
  • searchPaths: licensingservice → licensingservice 폴더 내부에서 설정 파일을 검색.

현재 Git 설정은 사용되지 않고, 대신 Vault를 사용하도록 되어 있음.

🔐 3) Vault 설정 (Secrets Engine: KV Version 2)

        vault:
          authentication: TOKEN
          token: myroot  # Docker에서 Vault를 실행할 때 지정한 root 토큰
          port: 8200
          host: ${VAULT_HOST} # 도커일 때와 아닐 때 호스트 주소가 달라진다 -> host.docker.internal
          scheme: http
          kv-version: 2
          profile-separator: /
          application-name-includes-profile: false

🔹 Vault 인증 방식: TOKEN

  • authentication: TOKEN → Vault 서버에 접근할 때 TOKEN 인증 방식 사용.
  • token: myroot → Vault 서버의 root 토큰을 직접 지정.

🔹 Vault 서버 주소 지정

  • port: 8200 → Vault가 실행 중인 포트 (기본값: 8200).
  • host: ${VAULT_HOST}
    • VAULT_HOST 환경 변수에 따라 동적으로 변경됨.

🔹 Vault KV Version 2 설정

  • kv-version: 2 → Vault의 Key-Value Store를 Version 2로 설정.
  • profile-separator: / → 프로필과 애플리케이션 이름을 /로 구분.

🌐 4) 서버 포트 설정

server:
  port: 8071

Config Server가 포트 8071에서 실행됨.

  • 클라이언트 마이크로서비스들은 이 포트로 설정을 요청할 것임.
  • 예: http://localhost:8071/licensing-service/default

📢 5) 로깅 설정 (디버깅 활성화)

logging:
  level:
    org.springframework.cloud.config.server: DEBUG
    org.springframework.web.client.RestTemplate: DEBUG

Config Server 및 HTTP 요청(RestTemplate)에 대한 디버깅 로그를 활성화.

  • Vault에서 설정을 가져올 때 로그를 확인하기 유용

🔒 6) Spring Boot Encrypt 설정

encrypt:
  key: fje83Ki8403Iod87dne7Yjsl3THueh48jfuO9j4U2hf64Lo

🔹 encrypt.key 설정

  • Spring Cloud Config Server는 암호화된 데이터를 저장할 수 있음.
  • 여기서는 고정된 키(encrypt.key)를 사용하여 설정을 복호화할 수 있도록 지정.

🔍 7) Actuator 활성화 (헬스 체크 및 모니터링)

management:
  endpoints:
    web:
      exposure:
        include: "health,info,configprops,env"
  endpoint:
    health:
      show-details: always

🔹 Spring Boot Actuator 설정

  • /actuator/health 및 /actuator/info 같은 엔드포인트를 활성화.
  • configprops와 env도 포함하여 Config Server의 설정 값을 확인할 수 있도록 함.

🚀 Spring Cloud Config Server Dockerfile 분석

#stage 1
#Start with a base image containing Java runtime
FROM openjdk:17 as build

# Add Maintainer Info
LABEL maintainer="jhcode33 <jhcode33@gmail.com>"

# The application's jar file
ARG JAR_FILE=target/configserver-0.0.1-SNAPSHOT.jar

# Add the application's jar to the container
COPY ${JAR_FILE} app.jar

#unpackage jar file
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf /app.jar)

#stage 2
#Same Java runtime
FROM openjdk:17

#Add volume pointing to /tmp
VOLUME /tmp

#Copy unpackaged application to new container
ARG DEPENDENCY=/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app

#execute the application
ENTRYPOINT ["java","-cp","app:app/lib/*","com.optimagrowth.configserver.ConfigurationServerApplication"]

위 Dockerfile은 멀티스테이지 빌드(Multi-stage build) 를 사용하여 Spring Cloud Config Server 를 컨테이너화하는 구성입니다.
구성 요소를 두 개의 빌드 단계(Stage 1, Stage 2) 로 나누어 더 가볍고 최적화된 Docker 이미지 를 생성합니다.

📌 Dockerfile 주요 구조

1️⃣ Stage 1: JAR 파일 빌드 및 압축 해제
2️⃣ Stage 2: 경량 컨테이너에서 애플리케이션 실행

🏗 📌 Stage 1: Java 기반 애플리케이션 빌드

#stage 1
#Start with a base image containing Java runtime
FROM openjdk:17 as build

✅ 기본 베이스 이미지: openjdk:17
✅ as build: 이 단계를 빌드 단계 로 명명하여 이후 참조 가능

# Add Maintainer Info
LABEL maintainer="jhcode33 <jhcode33@gmail.com>"

✅ LABEL maintainer 는 이미지 메타데이터 로, 관리자 정보 를 포함

# The application's jar file
ARG JAR_FILE=target/configserver-0.0.1-SNAPSHOT.jar

✅ ARG 를 사용해 빌드 시점에 설정 가능한 변수 지정
✅ 빌드된 JAR 파일의 경로를 JAR_FILE 변수로 설정

# Add the application's jar to the container
COPY ${JAR_FILE} app.jar

✅ COPY 명령어로 JAR 파일을 컨테이너 내부로 복사
✅ 복사된 파일을 /app.jar 로 저장

# Unpackage jar file
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf /app.jar)

✅ mkdir -p target/dependency → JAR 압축을 풀 저장 폴더 생성
✅ (cd target/dependency; jar -xf /app.jar) → JAR 파일을 압축 해제
✅ jar -xf 명령을 사용해 JAR 내부의 BOOT-INF/lib, BOOT-INF/classes, META-INF 폴더를 추출

🚀 📌 Stage 2: 최적화된 실행 컨테이너

#stage 2
#Same Java runtime
FROM openjdk:17

✅ 새로운 컨테이너 이미지 시작 (이번에는 빌드 단계 없음)
✅ openjdk:17 베이스 이미지 사용

#Add volume pointing to /tmp
VOLUME /tmp

✅ VOLUME /tmp 설정을 통해 임시 파일을 저장할 볼륨을 생성
✅ 컨테이너를 재시작해도 /tmp 데이터를 유지 가능

#Copy unpackaged application to new container
ARG DEPENDENCY=/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app

✅ COPY --from=build → 첫 번째 빌드 단계에서 추출한 JAR 내부 파일만 복사
✅ /app/lib, /app/META-INF, /app 디렉토리에 각각 라이브러리, 메타데이터, 클래스 파일 배치
✅ 전체 JAR 파일을 복사하는 대신, 필요한 파일만 배포하여 이미지 크기 최적화

#execute the application
ENTRYPOINT ["java","-cp","app:app/lib/*","com.optimagrowth.configserver.ConfigurationServerApplication"]

✅ Java 애플리케이션 실행 명령어 설정
✅ -cp app:app/lib/* → 클래스패스를 설정하여 모든 라이브러리를 포함
✅ Spring Boot 애플리케이션 실행:

   java -cp app:app/lib/* com.optimagrowth.configserver.ConfigurationServerApplication

✅ ENTRYPOINT 를 사용하여 기본 실행 명령어로 설정 (컨테이너 시작 시 자동 실행)

📦 🔹 최적화된 Docker 이미지 빌드

이 Dockerfile은 멀티스테이지 빌드 를 활용하여 불필요한 빌드 도구를 포함하지 않은 최적화된 이미지 를 생성합니다.

✅ 멀티스테이지 빌드의 장점

비교 항목일반적인 빌드멀티스테이지 빌드

이미지 크기 📌 JDK + 전체 JAR 포함 (크기 큼) 🚀 JRE + 필요한 파일만 포함 (경량화)
빌드 속도 ⏳ 매번 전체 JAR 복사 ⚡ JAR 압축 해제 후 파일 단위로 복사
실행 성능 ❌ JAR 압축 해제 필요 ✅ 즉시 실행 가능

✔ COPY --from=build을 활용하여 필요한 파일만 컨테이너에 복사하여 용량 절감

✔ ENTRYPOINT 설정으로 컨테이너 시작 시 자동으로 애플리케이션 실행

 

📢 Summary

이번 글에서는 Spring Cloud Config Server를 활용한 중앙 집중식 설정 관리와 함께 Docker 최적화 빌드 방법을 살펴보았습니다.

Spring Cloud Config Server를 활용하여 Git 또는 Vault에서 설정 파일을 로드할 수 있음

Spring Boot Actuator를 활용한 모니터링 기능 제공

멀티스테이지 빌드를 사용하여 최적화된 Docker 이미지 생성

✅ COPY --from=build을 통해 필요한 파일만 컨테이너에 포함하여 성능 향상

 

이제 여러분의 프로젝트에서도 Spring Cloud Config Server를 도입하여 구성 관리를 간소화하고, 최적화된 컨테이너 배포를 적용해보세요! 🚀

 

출처 : https://github.com/ihuaylupo/manning-smia/tree/master/chapter5/configserver

 

manning-smia/chapter5/configserver at master · ihuaylupo/manning-smia

Spring Microservices in Action - Second Edition - Code Examples - ihuaylupo/manning-smia

github.com