VM 배포를 위한 Docker 컨테이너 설정 추가

- content-service/build.gradle: bootJar 파일명 설정 추가
- deployment/container/Dockerfile-backend: 백엔드 서비스 Docker 이미지 파일
- deployment/container/docker-compose.yml: Docker Compose 설정 (환경변수 포함)
- deployment/container/build-and-run.sh: 자동화 빌드 및 배포 스크립트
- deployment/container/build-image.md: 상세 배포 가이드 문서

주요 환경변수:
- JWT_SECRET: 32자 이상 JWT 서명 키 (JWT 오류 해결)
- REDIS/KAFKA: 외부 서버 연결 정보
- REPLICATE_API_TOKEN: Stable Diffusion API 토큰
- AZURE_STORAGE_CONNECTION_STRING: Azure Blob Storage 연결

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
cherry2250
2025-10-27 17:00:20 +09:00
parent 2da2f124a2
commit 5f8bd7cf68
20 changed files with 1737 additions and 2 deletions
+25
View File
@@ -0,0 +1,25 @@
# 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"]
+67
View File
@@ -0,0 +1,67 @@
#!/bin/bash
# 색상 정의
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Content Service 빌드 및 배포 스크립트${NC}"
echo -e "${GREEN}========================================${NC}"
# 1. Gradle 빌드
echo -e "\n${YELLOW}1단계: Gradle 빌드 시작...${NC}"
./gradlew clean content-service:bootJar
if [ $? -ne 0 ]; then
echo -e "${RED}❌ Gradle 빌드 실패!${NC}"
exit 1
fi
echo -e "${GREEN}✅ Gradle 빌드 완료${NC}"
# 2. Docker 이미지 빌드
echo -e "\n${YELLOW}2단계: Docker 이미지 빌드 시작...${NC}"
DOCKER_FILE=deployment/container/Dockerfile-backend
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="content-service/build/libs" \
--build-arg ARTIFACTORY_FILE="content-service.jar" \
-f ${DOCKER_FILE} \
-t content-service:latest .
if [ $? -ne 0 ]; then
echo -e "${RED}❌ Docker 이미지 빌드 실패!${NC}"
exit 1
fi
echo -e "${GREEN}✅ Docker 이미지 빌드 완료${NC}"
# 3. 이미지 확인
echo -e "\n${YELLOW}3단계: 생성된 이미지 확인...${NC}"
docker images | grep content-service
# 4. 기존 컨테이너 중지 및 삭제
echo -e "\n${YELLOW}4단계: 기존 컨테이너 정리...${NC}"
docker-compose -f deployment/container/docker-compose.yml down
# 5. 컨테이너 실행
echo -e "\n${YELLOW}5단계: Content Service 컨테이너 실행...${NC}"
docker-compose -f deployment/container/docker-compose.yml up -d
if [ $? -ne 0 ]; then
echo -e "${RED}❌ 컨테이너 실행 실패!${NC}"
exit 1
fi
echo -e "\n${GREEN}========================================${NC}"
echo -e "${GREEN}✅ 배포 완료!${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "\n${YELLOW}컨테이너 로그 확인:${NC}"
echo -e " docker logs -f content-service"
echo -e "\n${YELLOW}컨테이너 상태 확인:${NC}"
echo -e " docker ps"
echo -e "\n${YELLOW}서비스 헬스체크:${NC}"
echo -e " curl http://localhost:8084/actuator/health"
echo -e "\n${YELLOW}Swagger UI:${NC}"
echo -e " http://localhost:8084/swagger-ui/index.html"
+287
View File
@@ -0,0 +1,287 @@
# Content Service 컨테이너 이미지 빌드 및 배포 가이드
## 1. 사전 준비사항
### 필수 소프트웨어
- **Docker Desktop**: Docker 컨테이너 실행 환경
- **JDK 23**: Java 애플리케이션 빌드
- **Gradle**: 프로젝트 빌드 도구
### 외부 서비스
- **Redis 서버**: 20.214.210.71:6379
- **Kafka 서버**: 4.230.50.63:9092
- **Replicate API**: Stable Diffusion 이미지 생성
- **Azure Blob Storage**: 이미지 CDN
## 2. 빌드 설정
### build.gradle 설정 (content-service/build.gradle)
```gradle
// 실행 JAR 파일명 설정
bootJar {
archiveFileName = 'content-service.jar'
}
```
## 3. 배포 파일 구조
```
deployment/
└── container/
├── Dockerfile-backend # 백엔드 서비스용 Dockerfile
├── docker-compose.yml # Docker Compose 설정
└── build-and-run.sh # 자동화 배포 스크립트
```
## 4. 수동 빌드 및 배포
### 4.1 Gradle 빌드
```bash
# 프로젝트 루트에서 실행
./gradlew clean content-service:bootJar
```
### 4.2 Docker 이미지 빌드
```bash
DOCKER_FILE=deployment/container/Dockerfile-backend
docker build \
--platform linux/amd64 \
--build-arg BUILD_LIB_DIR="content-service/build/libs" \
--build-arg ARTIFACTORY_FILE="content-service.jar" \
-f ${DOCKER_FILE} \
-t content-service:latest .
```
### 4.3 빌드된 이미지 확인
```bash
docker images | grep content-service
```
예상 출력:
```
content-service latest abc123def456 2 minutes ago 450MB
```
### 4.4 Docker Compose로 컨테이너 실행
```bash
docker-compose -f deployment/container/docker-compose.yml up -d
```
### 4.5 컨테이너 상태 확인
```bash
# 실행 중인 컨테이너 확인
docker ps
# 로그 확인
docker logs -f content-service
# 헬스체크
curl http://localhost:8084/actuator/health
```
## 5. 자동화 배포 스크립트 사용 (권장)
### 5.1 스크립트 실행
```bash
# 프로젝트 루트에서 실행
./deployment/container/build-and-run.sh
```
### 5.2 스크립트 수행 단계
1. Gradle 빌드
2. Docker 이미지 빌드
3. 이미지 확인
4. 기존 컨테이너 정리
5. 새 컨테이너 실행
## 6. 환경변수 설정
`docker-compose.yml`에 다음 환경변수가 설정되어 있습니다:
### 필수 환경변수
- `SPRING_PROFILES_ACTIVE`: Spring Profile (prod)
- `SERVER_PORT`: 서버 포트 (8084)
- `REDIS_HOST`: Redis 호스트
- `REDIS_PORT`: Redis 포트
- `REDIS_PASSWORD`: Redis 비밀번호
- `JWT_SECRET`: JWT 서명 키 (최소 32자)
- `REPLICATE_API_TOKEN`: Replicate API 토큰
- `AZURE_STORAGE_CONNECTION_STRING`: Azure Storage 연결 문자열
- `AZURE_CONTAINER_NAME`: Azure Storage 컨테이너 이름
### JWT_SECRET 요구사항
- **최소 길이**: 32자 이상 (256비트)
- **형식**: 영문자, 숫자 조합
- **예시**: `kt-event-marketing-jwt-secret-key-for-authentication-and-authorization-2025`
## 7. VM 배포
### 7.1 VM에 파일 전송
```bash
# VM으로 파일 복사 (예시)
scp -r deployment/ user@vm-host:/path/to/project/
scp docker-compose.yml user@vm-host:/path/to/project/deployment/container/
scp content-service/build/libs/content-service.jar user@vm-host:/path/to/project/content-service/build/libs/
```
### 7.2 VM에서 이미지 빌드
```bash
# VM에 SSH 접속 후
cd /path/to/project
# 이미지 빌드
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 .
```
### 7.3 VM에서 컨테이너 실행
```bash
# Docker Compose로 실행
docker-compose -f deployment/container/docker-compose.yml up -d
# 또는 직접 실행
docker run -d \
--name content-service \
-p 8084:8084 \
-e SPRING_PROFILES_ACTIVE=prod \
-e SERVER_PORT=8084 \
-e REDIS_HOST=20.214.210.71 \
-e REDIS_PORT=6379 \
-e REDIS_PASSWORD=Hi5Jessica! \
-e JWT_SECRET=kt-event-marketing-jwt-secret-key-for-authentication-and-authorization-2025 \
-e REPLICATE_API_TOKEN=r8_Q33U00fSnpjYlHNIRglwurV446h7g8V2wkFFa \
-e AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=blobkteventstorage;AccountKey=tcBN7mAfojbl0uGsOpU7RNuKNhHnzmwDiWjN31liSMVSrWaEK+HHnYKZrjBXXAC6ZPsuxUDlsf8x+AStd++QYg==;EndpointSuffix=core.windows.net" \
-e AZURE_CONTAINER_NAME=content-images \
content-service:latest
```
## 8. 모니터링 및 로그
### 8.1 컨테이너 상태 확인
```bash
docker ps
```
### 8.2 로그 확인
```bash
# 실시간 로그
docker logs -f content-service
# 최근 100줄
docker logs --tail 100 content-service
```
### 8.3 헬스체크
```bash
curl http://localhost:8084/actuator/health
```
예상 응답:
```json
{
"status": "UP",
"components": {
"ping": {
"status": "UP"
},
"redis": {
"status": "UP"
}
}
}
```
## 9. Swagger UI 접근
배포 후 Swagger UI로 API 테스트 가능:
```
http://localhost:8084/swagger-ui/index.html
```
## 10. 이미지 생성 API 테스트
### 10.1 이미지 생성 요청
```bash
curl -X POST "http://localhost:8084/api/v1/content/images/generate" \
-H "Content-Type: application/json" \
-d '{
"eventDraftId": 1001,
"industry": "고깃집",
"location": "강남",
"trends": ["가을", "단풍", "BBQ"],
"styles": ["FANCY"],
"platforms": ["INSTAGRAM"]
}'
```
### 10.2 Job 상태 확인
```bash
curl http://localhost:8084/api/v1/content/jobs/{jobId}
```
## 11. 컨테이너 관리 명령어
### 11.1 컨테이너 중지
```bash
docker-compose -f deployment/container/docker-compose.yml down
```
### 11.2 컨테이너 재시작
```bash
docker-compose -f deployment/container/docker-compose.yml restart
```
### 11.3 컨테이너 삭제
```bash
# 컨테이너만 삭제
docker rm -f content-service
# 이미지도 삭제
docker rmi content-service:latest
```
## 12. 트러블슈팅
### 12.1 JWT 토큰 오류
**증상**: `Error creating bean with name 'jwtTokenProvider'`
**해결방법**:
- `JWT_SECRET` 환경변수가 32자 이상인지 확인
- docker-compose.yml에 올바르게 설정되어 있는지 확인
### 12.2 Redis 연결 오류
**증상**: `Unable to connect to Redis`
**해결방법**:
- Redis 서버(20.214.210.71:6379)가 실행 중인지 확인
- 방화벽 설정 확인
- 비밀번호 확인
### 12.3 Azure Storage 오류
**증상**: `Azure storage connection failed`
**해결방법**:
- `AZURE_STORAGE_CONNECTION_STRING`이 올바른지 확인
- Storage Account가 활성화되어 있는지 확인
- 컨테이너 이름(`content-images`)이 존재하는지 확인
## 13. 빌드 결과
### 빌드 정보
- **서비스명**: content-service
- **JAR 파일**: content-service.jar
- **Docker 이미지**: content-service:latest
- **노출 포트**: 8084
### 빌드 일시
- **빌드 날짜**: 2025-10-27
### 환경
- **Base Image**: openjdk:23-slim
- **Platform**: linux/amd64
- **User**: k8s (non-root)
+58
View File
@@ -0,0 +1,58 @@
version: '3.8'
services:
content-service:
image: content-service:latest
container_name: content-service
ports:
- "8084:8084"
environment:
# Spring Profile
SPRING_PROFILES_ACTIVE: prod
# Server Configuration
SERVER_PORT: 8084
# Redis Configuration (외부 Redis 서버)
REDIS_HOST: 20.214.210.71
REDIS_PORT: 6379
REDIS_PASSWORD: Hi5Jessica!
# Kafka Configuration (외부 Kafka 서버)
KAFKA_BOOTSTRAP_SERVERS: 4.230.50.63:9092
KAFKA_CONSUMER_GROUP_ID: content-service-consumers
# JWT Configuration
JWT_SECRET: kt-event-marketing-jwt-secret-key-for-authentication-and-authorization-2025
JWT_ACCESS_TOKEN_VALIDITY: 3600000
JWT_REFRESH_TOKEN_VALIDITY: 604800000
# Replicate API (Stable Diffusion)
REPLICATE_API_TOKEN: r8_Q33U00fSnpjYlHNIRglwurV446h7g8V2wkFFa
# Azure Blob Storage Configuration
AZURE_STORAGE_CONNECTION_STRING: DefaultEndpointsProtocol=https;AccountName=blobkteventstorage;AccountKey=tcBN7mAfojbl0uGsOpU7RNuKNhHnzmwDiWjN31liSMVSrWaEK+HHnYKZrjBXXAC6ZPsuxUDlsf8x+AStd++QYg==;EndpointSuffix=core.windows.net
AZURE_CONTAINER_NAME: content-images
# Logging Configuration
LOG_LEVEL_APP: INFO
LOG_LEVEL_ROOT: INFO
# JVM Options
JAVA_OPTS: "-Xmx512m -Xms256m"
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8084/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- kt-event-network
networks:
kt-event-network:
driver: bridge