Hyowon Yang 3855e78abf gradlew 실행 권한 설정 가이드 추가
- VM 환경에서 permission denied 오류 해결 방법 추가
- chmod +x gradlew 명령어 및 대체 방법(bash gradlew) 안내
- JAR 빌드 및 재배포 섹션에 권한 설정 단계 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 16:43:11 +09:00

10 KiB

백엔드 컨테이너 이미지 작성 결과

작성일: 2025-10-27 작성자: DevOps Engineer

1. 개요

KT 이벤트 마케팅 플랫폼의 백엔드 마이크로서비스들을 컨테이너 이미지로 빌드하는 과정을 문서화합니다.

2. 서비스 현황

2.1 전체 서비스 목록 (settings.gradle 기준)

rootProject.name = 'kt-event-marketing'

// Common module
include 'common'

// Microservices
include 'user-service'
include 'event-service'
include 'ai-service'
include 'content-service'
include 'distribution-service'
include 'participation-service'
include 'analytics-service'

2.2 구현 상태

서비스명 구현 상태 JAR 빌드 컨테이너 이미지 비고
common N/A N/A 공통 라이브러리
user-service ⚠️ ⏸️ 컴파일 에러 (타입 불일치)
event-service ⏸️ Docker Desktop 필요
ai-service 미구현
content-service ⏸️ Docker Desktop 필요
distribution-service 미구현
participation-service ⏸️ Docker Desktop 필요
analytics-service ⏸️ Docker Desktop 필요

빌드 가능 서비스: 4개 (event-service, content-service, participation-service, analytics-service)

3. JAR 파일 빌드

3.1 bootJar 설정 확인

root build.gradle에 이미 설정되어 있음:

// Configure bootJar task for each service
bootJar {
    archiveFileName = "${project.name}.jar"
}

3.2 JAR 빌드 실행

gradlew 실행 권한 설정 (최초 1회)

VM 환경에서 실행 시 권한 오류가 발생할 수 있으므로 먼저 실행 권한을 부여합니다:

chmod +x gradlew

빌드 명령어 실행

명령어:

./gradlew :analytics-service:bootJar :content-service:bootJar :event-service:bootJar :participation-service:bootJar :user-service:bootJar --no-daemon

권한 오류 발생 시 대체 방법:

# gradlew에 실행 권한이 없는 경우
bash gradlew :analytics-service:bootJar :content-service:bootJar :event-service:bootJar :participation-service:bootJar :user-service:bootJar --no-daemon

빌드 결과:

성공한 서비스 (4개):

  • analytics-service/build/libs/analytics-service.jar
  • content-service/build/libs/content-service.jar
  • event-service/build/libs/event-service.jar
  • participation-service/build/libs/participation-service.jar

실패한 서비스 (1개):

  • user-service: 컴파일 에러 발생

user-service 컴파일 에러 상세:

UserController.java:93: error: incompatible types: UUID cannot be converted to Long
        Long userId = principal.getUserId();
                                         ^
UserController.java:109: error: incompatible types: UUID cannot be converted to Long
        Long userId = principal.getUserId();
                                         ^
UserController.java:126: error: incompatible types: UUID cannot be converted to Long
        Long userId = principal.getUserId();
                                         ^
AuthenticationServiceImpl.java:72: error: method createAccessToken in class JwtTokenProvider cannot be applied to given types;
  required: UUID,UUID,String,String,List<String>
  found:    Long,String,String,List<String>
  reason: actual and formal argument lists differ in length

조치 필요: user-service의 User ID 타입을 Long에서 UUID로 변경 필요

4. Dockerfile 작성

파일 위치: deployment/container/Dockerfile-backend

내용:

# Build stage
FROM openjdk:23-oraclelinux8 AS builder
ARG BUILD_LIB_DIR
ARG ARTIFACTORY_FILE
COPY ${BUILD_LIB_DIR}/${ARTIFACTORY_FILE} app.jar

# Run stage
FROM openjdk:23-slim
ENV USERNAME=k8s
ENV ARTIFACTORY_HOME=/home/${USERNAME}
ENV JAVA_OPTS=""

# Add a non-root user
RUN adduser --system --group ${USERNAME} && \
    mkdir -p ${ARTIFACTORY_HOME} && \
    chown ${USERNAME}:${USERNAME} ${ARTIFACTORY_HOME}

WORKDIR ${ARTIFACTORY_HOME}
COPY --from=builder app.jar app.jar
RUN chown ${USERNAME}:${USERNAME} app.jar

USER ${USERNAME}

ENTRYPOINT [ "sh", "-c" ]
CMD ["java ${JAVA_OPTS} -jar app.jar"]

특징:

  • Multi-stage build (빌드 단계와 실행 단계 분리)
  • OpenJDK 23 사용
  • 비root 사용자(k8s)로 실행하여 보안 강화
  • JAVA_OPTS 환경변수로 JVM 옵션 커스터마이징 가능
  • linux/amd64 플랫폼 지원

5. 컨테이너 이미지 빌드

5.1 사전 조건

⚠️ Docker Desktop 실행 필요

이미지 빌드 전에 Docker Desktop이 실행되어 있어야 합니다:

  1. Windows에서 Docker Desktop 실행
  2. 시스템 트레이에서 "Docker Desktop is running" 확인
  3. 확인 명령어: docker ps

5.2 빌드 명령어

analytics-service

docker build \
  --platform linux/amd64 \
  --build-arg BUILD_LIB_DIR="analytics-service/build/libs" \
  --build-arg ARTIFACTORY_FILE="analytics-service.jar" \
  -f deployment/container/Dockerfile-backend \
  -t analytics-service:latest .

content-service

docker build \
  --platform linux/amd64 \
  --build-arg BUILD_LIB_DIR="content-service/build/libs" \
  --build-arg ARTIFACTORY_FILE="content-service.jar" \
  -f deployment/container/Dockerfile-backend \
  -t content-service:latest .

event-service

docker build \
  --platform linux/amd64 \
  --build-arg BUILD_LIB_DIR="event-service/build/libs" \
  --build-arg ARTIFACTORY_FILE="event-service.jar" \
  -f deployment/container/Dockerfile-backend \
  -t event-service:latest .

participation-service

docker build \
  --platform linux/amd64 \
  --build-arg BUILD_LIB_DIR="participation-service/build/libs" \
  --build-arg ARTIFACTORY_FILE="participation-service.jar" \
  -f deployment/container/Dockerfile-backend \
  -t participation-service:latest .

5.3 일괄 빌드 스크립트

모든 서비스를 한 번에 빌드하려면 다음 스크립트를 사용하세요:

Windows (PowerShell):

# 빌드 가능한 서비스 목록
$services = @(
    "analytics-service",
    "content-service",
    "event-service",
    "participation-service"
)

# 각 서비스 빌드
foreach ($service in $services) {
    Write-Host "Building $service..." -ForegroundColor Green
    docker build `
        --platform linux/amd64 `
        --build-arg BUILD_LIB_DIR="$service/build/libs" `
        --build-arg ARTIFACTORY_FILE="$service.jar" `
        -f deployment/container/Dockerfile-backend `
        -t ${service}:latest .

    if ($LASTEXITCODE -eq 0) {
        Write-Host "✅ $service build completed" -ForegroundColor Green
    } else {
        Write-Host "❌ $service build failed" -ForegroundColor Red
    }
}

Linux/Mac (Bash):

#!/bin/bash

# 빌드 가능한 서비스 목록
services=(
    "analytics-service"
    "content-service"
    "event-service"
    "participation-service"
)

# 각 서비스 빌드
for service in "${services[@]}"; do
    echo "Building $service..."
    docker build \
        --platform linux/amd64 \
        --build-arg BUILD_LIB_DIR="${service}/build/libs" \
        --build-arg ARTIFACTORY_FILE="${service}.jar" \
        -f deployment/container/Dockerfile-backend \
        -t ${service}:latest .

    if [ $? -eq 0 ]; then
        echo "✅ $service build completed"
    else
        echo "❌ $service build failed"
    fi
done

6. 이미지 확인

6.1 빌드된 이미지 목록 확인

docker images | grep -E "analytics-service|content-service|event-service|participation-service"

예상 출력:

analytics-service        latest    <IMAGE_ID>   <TIME>   <SIZE>
content-service          latest    <IMAGE_ID>   <TIME>   <SIZE>
event-service            latest    <IMAGE_ID>   <TIME>   <SIZE>
participation-service    latest    <IMAGE_ID>   <TIME>   <SIZE>

6.2 개별 서비스 이미지 확인

# analytics-service
docker images analytics-service:latest

# content-service
docker images content-service:latest

# event-service
docker images event-service:latest

# participation-service
docker images participation-service:latest

6.3 이미지 상세 정보 확인

# 이미지 레이어 확인
docker history <service-name>:latest

# 이미지 메타데이터 확인
docker inspect <service-name>:latest

7. 테스트 실행

7.1 로컬에서 컨테이너 실행 테스트

# analytics-service 실행 예시
docker run -d \
  --name analytics-service-test \
  -p 8080:8080 \
  -e JAVA_OPTS="-Xms256m -Xmx512m" \
  -e SPRING_PROFILES_ACTIVE=dev \
  analytics-service:latest

# 로그 확인
docker logs -f analytics-service-test

# 헬스체크
curl http://localhost:8080/actuator/health

# 컨테이너 정리
docker stop analytics-service-test
docker rm analytics-service-test

8. 문제 해결

8.1 user-service 컴파일 에러

문제: UUID와 Long 타입 불일치

해결 방법:

  1. UserController.java에서 Long userIdUUID userId 변경
  2. AuthenticationServiceImpl.javaUserServiceImpl.java에서 createAccessToken 메서드 호출 시 첫 번째 파라미터로 sessionId 추가
  3. 변경 후 재빌드:
    ./gradlew :user-service:bootJar --no-daemon
    

8.2 ai-service 및 distribution-service

문제: 소스 코드 미구현

조치: 해당 서비스의 구현이 완료된 후 컨테이너 이미지 빌드 진행

8.3 Docker Desktop 연결 실패

에러 메시지:

error during connect: open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.

해결 방법:

  1. Docker Desktop 실행
  2. 완전히 시작될 때까지 대기 (트레이 아이콘 확인)
  3. docker ps 명령으로 정상 동작 확인
  4. 빌드 명령 재실행

9. 다음 단계

  1. 완료: Dockerfile 작성 및 JAR 빌드
  2. ⏸️ 대기 중: Docker Desktop 실행 후 이미지 빌드
  3. 📋 예정:
    • user-service 컴파일 에러 수정
    • ai-service 및 distribution-service 구현 완료 후 빌드
    • 이미지 레지스트리에 푸시 (ACR 등)
    • Kubernetes 배포 매니페스트 작성

10. 참고 자료

  • Dockerfile: deployment/container/Dockerfile-backend
  • JAR 위치: <service-name>/build/libs/<service-name>.jar
  • 빌드 스크립트: 본 문서의 5.3 섹션 참조
  • OpenJDK 23 Documentation: https://openjdk.org/projects/jdk/23/