Configserver 서버 프로젝트
🚀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>
✅ 주요 라이브러리 설명
- Spring Cloud Config Server
- spring-cloud-config-server는 Config Server 기능을 제공
- 설정 파일을 Git 또는 Vault에서 가져올 수 있음
- Spring Boot Actuator
- spring-boot-starter-actuator는 애플리케이션 모니터링을 위한 엔드포인트 제공
- /actuator/health, /actuator/info 등의 엔드포인트 활성화 가능
- 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>
✅ 빌드 플러그인 설명
- Spring Boot Maven Plugin
- spring-boot-maven-plugin은 Spring Boot 애플리케이션을 JAR 파일로 패키징
- 실행 가능한 JAR 파일 생성
- 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