diff --git a/Jenkinsfile b/Jenkinsfile index bfadb9c..1b23c25 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,156 +1,287 @@ -// pipeline { -// agent any -// -// environment { -// AWS_REGION = 'ap-northeast-2' -// DOCKER_TAG = 'test' -// } -// -// stages { -// stage('소스코드 체크아웃') { -// steps { -// script { -// deleteDir() -// git branch: 'develop', -// url: 'https://github.com/KTB-Sixmen/gitfolio_back_spring.git' -// } -// } -// } -// -// stage('환경 설정') { -// steps { -// script { -// def envFile = '/var/lib/jenkins/environments/.env.back.dev' -// -// if (fileExists(envFile)) { -// sh """ -// cp ${envFile} .env -// echo '환경 파일 복사 완료: ${envFile}' -// """ -// } else { -// error "환경 파일을 찾을 수 없습니다: ${envFile}" -// } -// -// // Docker Hub 로그인 - AI 파이프라인 방식으로 변경 -// withCredentials([usernamePassword(credentialsId: 'docker-credentials', -// usernameVariable: 'DOCKER_USER', -// passwordVariable: 'DOCKER_PASS')]) { -// sh """ -// echo ${DOCKER_PASS} | docker login -u ${DOCKER_USER} --password-stdin -// """ -// } -// } -// } -// } -// -// stage('Builder 이미지 빌드') { -// steps { -// script { -// sh """ -// docker build \ -// -f dockerfile \ -// -t aida0/gitfolio_builder:${DOCKER_TAG} \ -// --platform linux/amd64 \ -// . -// -// docker push aida0/gitfolio_builder:${DOCKER_TAG} -// """ -// } -// } -// } -// -// stage('모듈 빌드 및 배포') { -// matrix { -// axes { -// axis { -// name 'MODULE' -// values 'auth', 'member', 'payment', 'resume', 'notification', 'chat' -// } -// } -// stages { -// stage('모듈 빌드') { -// steps { -// script { -// def moduleConfig = [ -// auth: [path: './gitfolio-auth', image: 'aida0/gitfolio_auth', index: '1'], -// member: [path: './gitfolio-member', image: 'aida0/gitfolio_member', index: '1'], -// payment: [path: './gitfolio-payment', image: 'aida0/gitfolio_payment', index: '2'], -// resume: [path: './gitfolio-resume', image: 'aida0/gitfolio_resume', index: '2'], -// notification: [path: './gitfolio-notification', image: 'aida0/gitfolio_notification', index: '3'], -// chat: [path: './gitfolio-chat', image: 'aida0/gitfolio_chat', index: '4'] -// ] -// -// def config = moduleConfig[MODULE] -// -// sh """ -// docker build \ -// -f ${config.path}/dockerfile \ -// -t ${config.image}:${DOCKER_TAG} \ -// ${config.path} -// -// docker push ${config.image}:${DOCKER_TAG} -// """ -// -// // AWS 자격증명 처리를 AI 파이프라인 방식으로 변경 -// withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', -// credentialsId: 'aws-credentials', -// accessKeyVariable: 'AWS_ACCESS_KEY_ID', -// secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { -// -// def instanceIds = sh( -// script: """ -// aws ec2 describe-instances \ -// --region ${AWS_REGION} \ -// --filters 'Name=tag:Service,Values=back' \ -// 'Name=tag:Index,Values=${config.index}' \ -// 'Name=tag:Environment,Values=dev' \ -// 'Name=tag:Type,Values=ec2' \ -// 'Name=instance-state-name,Values=running' \ -// --query 'Reservations[].Instances[].InstanceId' \ -// --output text -// """, -// returnStdout: true -// ).trim() -// -// if (instanceIds) { -// sh """ -// aws ssm send-command \ -// --instance-ids "${instanceIds}" \ -// --document-name "AWS-RunShellScript" \ -// --comment "Deploying ${MODULE} module" \ -// --parameters commands=' -// cd /home/ec2-user -// docker-compose down -v --rmi all -// docker-compose pull -// docker-compose up -d -// ' \ -// --timeout-seconds 600 \ -// --region ${AWS_REGION} -// """ -// } else { -// error "${MODULE} 모듈을 위한 EC2 인스턴스를 찾을 수 없습니다." -// } -// } -// } -// } -// } -// } -// } -// } -// } -// -// post { -// always { -// script { -// sh 'docker logout' -// sh 'rm -f .env' -// } -// } -// success { -// echo "파이프라인이 성공적으로 완료되었습니다." -// } -// failure { -// echo "파이프라인이 실패했습니다. 로그를 확인해주세요." -// } -// } -// } \ No newline at end of file +pipeline { + agent any + + environment { + AWS_REGION = 'ap-northeast-2' + ECR_REGISTRY = credentials('ecr-registry') + DISCORD_CI_WEBHOOK = credentials('dev-discord-ci-webhook') + DISCORD_CD_WEBHOOK = credentials('dev-discord-cd-webhook') + DOCKER_TAG = 'prod' + } + + stages { + stage('소스코드 체크아웃') { + steps { + script { + deleteDir() + git branch: 'develop', + url: 'https://github.com/KTB-Sixmen/gitfolio_back_spring.git' + } + } + } + + stage('환경 설정') { + steps { + script { + def envFile = '/var/lib/jenkins/environments/.env.back.prod' + if (fileExists(envFile)) { + sh """ + cp \"${envFile}\" .env + echo \"환경 파일 복사 완료: \${envFile}\" + + # URL 관련 환경변수 + export REDIRECT_ONBOARDING_URL=\$(grep REDIRECT_ONBOARDING_URL .env | cut -d '=' -f2) + export REDIRECT_MAIN_URL=\$(grep REDIRECT_MAIN_URL .env | cut -d '=' -f2) + export MEMBER_SERVER_URL=\$(grep MEMBER_SERVER_URL .env | cut -d '=' -f2) + export PAYMENT_SERVER_URL=\$(grep PAYMENT_SERVER_URL .env | cut -d '=' -f2) + export NOTIFICATION_SERVER_URL=\$(grep NOTIFICATION_SERVER_URL .env | cut -d '=' -f2) + export AI_SERVER_URL=\$(grep AI_SERVER_URL .env | cut -d '=' -f2) + export PAYMENT_SUCCESS_REDIRECT_URL=\$(grep PAYMENT_SUCCESS_REDIRECT_URL .env | cut -d '=' -f2) + + # gRPC 관련 환경변수 + export MEMBER_GRPC_PORT=\$(grep MEMBER_GRPC_PORT .env | cut -d '=' -f2) + + # 서버 포트 환경변수 + export AUTH_SERVER_PORT=\$(grep AUTH_SERVER_PORT .env | cut -d '=' -f2) + export MEMBER_SERVER_PORT=\$(grep MEMBER_SERVER_PORT .env | cut -d '=' -f2) + export RESUME_SERVER_PORT=\$(grep RESUME_SERVER_PORT .env | cut -d '=' -f2) + export PAYMENT_SERVER_PORT=\$(grep PAYMENT_SERVER_PORT .env | cut -d '=' -f2) + export NOTIFICATION_SERVER_PORT=\$(grep NOTIFICATION_SERVER_PORT .env | cut -d '=' -f2) + export CHAT_SERVER_PORT=\$(grep CHAT_SERVER_PORT .env | cut -d '=' -f2) + # GitHub OAuth 관련 환경변수 + export GH_CLIENT_ID=\$(grep GH_CLIENT_ID .env | cut -d '=' -f2) + export GH_CLIENT_SECRET=\$(grep GH_CLIENT_SECRET .env | cut -d '=' -f2) + export GH_REDIRECT_URI=\$(grep GH_REDIRECT_URI .env | cut -d '=' -f2) + export GH_API_TOKEN=\$(grep GH_API_TOKEN .env | cut -d '=' -f2) + + # JWT 관련 환경변수 + export JWT_SECRET_KEY=\$(grep JWT_SECRET_KEY .env | cut -d '=' -f2) + export ACCESS_TOKEN_EXPIRY=\$(grep ACCESS_TOKEN_EXPIRY .env | cut -d '=' -f2) + export REFRESH_TOKEN_EXPIRY=\$(grep REFRESH_TOKEN_EXPIRY .env | cut -d '=' -f2) + + # Redis 관련 환경변수 + export AUTH_REDIS_HOST=\$(grep AUTH_REDIS_HOST .env | cut -d '=' -f2) + export AUTH_REDIS_PORT=\$(grep AUTH_REDIS_PORT .env | cut -d '=' -f2) + export RESUME_REDIS_HOST=\$(grep RESUME_REDIS_HOST .env | cut -d '=' -f2) + export RESUME_REDIS_PORT=\$(grep RESUME_REDIS_PORT .env | cut -d '=' -f2) + + # MySQL 관련 환경변수 + export MEMBER_MYSQL_DB_HOST=\$(grep MEMBER_MYSQL_DB_HOST .env | cut -d '=' -f2) + export MEMBER_MYSQL_DB_PORT=\$(grep MEMBER_MYSQL_DB_PORT .env | cut -d '=' -f2) + export MEMBER_MYSQL_DB_NAME=\$(grep MEMBER_MYSQL_DB_NAME .env | cut -d '=' -f2) + export MEMBER_MYSQL_DB_PASSWORD=\$(grep MEMBER_MYSQL_DB_PASSWORD .env | cut -d '=' -f2) + export MEMBER_MYSQL_DB_USERNAME=\$(grep MEMBER_MYSQL_DB_USERNAME .env | cut -d '=' -f2) + + export LIKE_MYSQL_DB_HOST=\$(grep LIKE_MYSQL_DB_HOST .env | cut -d '=' -f2) + export LIKE_MYSQL_DB_PORT=\$(grep LIKE_MYSQL_DB_PORT .env | cut -d '=' -f2) + export LIKE_MYSQL_DB_NAME=\$(grep LIKE_MYSQL_DB_NAME .env | cut -d '=' -f2) + export LIKE_MYSQL_DB_PASSWORD=\$(grep LIKE_MYSQL_DB_PASSWORD .env | cut -d '=' -f2) + export LIKE_MYSQL_DB_USERNAME=\$(grep LIKE_MYSQL_DB_USERNAME .env | cut -d '=' -f2) + + export PAYMENT_MYSQL_DB_HOST=\$(grep PAYMENT_MYSQL_DB_HOST .env | cut -d '=' -f2) + export PAYMENT_MYSQL_DB_PORT=\$(grep PAYMENT_MYSQL_DB_PORT .env | cut -d '=' -f2) + export PAYMENT_MYSQL_DB_NAME=\$(grep PAYMENT_MYSQL_DB_NAME .env | cut -d '=' -f2) + export PAYMENT_MYSQL_DB_PASSWORD=\$(grep PAYMENT_MYSQL_DB_PASSWORD .env | cut -d '=' -f2) + export PAYMENT_MYSQL_DB_USERNAME=\$(grep PAYMENT_MYSQL_DB_USERNAME .env | cut -d '=' -f2) + + export NOTIFICATION_MYSQL_DB_HOST=\$(grep NOTIFICATION_MYSQL_DB_HOST .env | cut -d '=' -f2) + export NOTIFICATION_MYSQL_DB_PORT=\$(grep NOTIFICATION_MYSQL_DB_PORT .env | cut -d '=' -f2) + export NOTIFICATION_MYSQL_DB_NAME=\$(grep NOTIFICATION_MYSQL_DB_NAME .env | cut -d '=' -f2) + export NOTIFICATION_MYSQL_DB_PASSWORD=\$(grep NOTIFICATION_MYSQL_DB_PASSWORD .env | cut -d '=' -f2) + export NOTIFICATION_MYSQL_DB_USERNAME=\$(grep NOTIFICATION_MYSQL_DB_USERNAME .env | cut -d '=' -f2) + + # MongoDB 관련 환경변수 + export MEMBER_MONGO_DB_URI=\$(grep MEMBER_MONGO_DB_URI .env | cut -d '=' -f2) + export RESUME_MONGO_DB_URI=\$(grep RESUME_MONGO_DB_URI .env | cut -d '=' -f2) + export CHAT_MONGO_DB_URI=\$(grep CHAT_MONGO_DB_URI .env | cut -d '=' -f2) + + # S3 관련 환경변수 + export S3_ACCESS_KEY=\$(grep S3_ACCESS_KEY .env | cut -d '=' -f2) + export S3_SECRET_KEY=\$(grep S3_SECRET_KEY .env | cut -d '=' -f2) + export S3_URL_PREFIX=\$(grep S3_URL_PREFIX .env | cut -d '=' -f2) + + # Kakao Pay 관련 환경변수 + export KAKAO_API_URL=\$(grep KAKAO_API_URL .env | cut -d '=' -f2) + export KAKAOPAY_SECRET_KEY=\$(grep KAKAOPAY_SECRET_KEY .env | cut -d '=' -f2) + + # Kafka 관련 환경변수 + export KAFKA_HOST1=\$(grep KAFKA_HOST1 .env | cut -d '=' -f2) + export KAFKA_PORT1=\$(grep KAFKA_PORT1 .env | cut -d '=' -f2) + export KAFKA_BROKER_ID=\$(grep KAFKA_BROKER_ID .env | cut -d '=' -f2) + export KAFKA_ZOOKEEPER_CONNECT=\$(grep KAFKA_ZOOKEEPER_CONNECT .env | cut -d '=' -f2) + export KAFKA_LISTENER_DOCKER=\$(grep KAFKA_LISTENER_DOCKER .env | cut -d '=' -f2) + export KAFKA_LISTENER_EXTERNAL=\$(grep KAFKA_LISTENER_EXTERNAL .env | cut -d '=' -f2) + export KAFKA_ADVERTISED_LISTENER_DOCKER=\$(grep KAFKA_ADVERTISED_LISTENER_DOCKER .env | cut -d '=' -f2) + export KAFKA_ADVERTISED_LISTENER_EXTERNAL=\$(grep KAFKA_ADVERTISED_LISTENER_EXTERNAL .env | cut -d '=' -f2) + export KAFKA_INTER_BROKER_LISTENER_NAME=\$(grep KAFKA_INTER_BROKER_LISTENER_NAME .env | cut -d '=' -f2) + export KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=\$(grep KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR .env | cut -d '=' -f2) + """ + } else { + error "환경 파일을 찾을 수 없습니다: ${envFile}" + } + + withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', + credentialsId: 'aws-credentials', + accessKeyVariable: 'AWS_ACCESS_KEY_ID', + secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { + sh """ + aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${ECR_REGISTRY} + echo 'ECR 로그인 완료' + """ + } + } + } + } + stage('Builder 이미지 빌드') { + steps { + script { + sh """ + docker build \\ + -f dockerfile \\ + -t builder:${DOCKER_TAG} \\ + --platform linux/amd64 \\ + . + + # ECR용 태그 추가 + docker tag builder:${DOCKER_TAG} ${ECR_REGISTRY}/gitfolio/builder:${DOCKER_TAG} + """ + } + } + } + + stage('모듈 빌드') { + matrix { + axes { + axis { + name 'MODULE' + values 'auth', 'member', 'payment', 'resume', 'notification' + } + } + stages { + stage('모듈 빌드 및 푸시') { + steps { + script { + def moduleConfig = [ + auth: [path: './gitfolio-auth', index: '1'], + member: [path: './gitfolio-member', index: '1'], + payment: [path: './gitfolio-payment', index: '2'], + resume: [path: './gitfolio-resume', index: '2'], + notification: [path: './gitfolio-notification', index: '3'] + ] + + def config = moduleConfig[MODULE] + def imageTag = "${ECR_REGISTRY}/gitfolio/${MODULE}:${DOCKER_TAG}" + + sh """ + docker build \\ + -f ${config.path}/Dockerfile \\ + -t ${imageTag} \\ + --platform linux/amd64 \\ + --build-arg REDIRECT_ONBOARDING_URL=\${REDIRECT_ONBOARDING_URL} \ + --build-arg REDIRECT_MAIN_URL=\${REDIRECT_MAIN_URL} \ + --build-arg MEMBER_SERVER_URL=\${MEMBER_SERVER_URL} \ + --build-arg PAYMENT_SERVER_URL=\${PAYMENT_SERVER_URL} \ + --build-arg NOTIFICATION_SERVER_URL=\${NOTIFICATION_SERVER_URL} \ + --build-arg AI_SERVER_URL=\${AI_SERVER_URL} \ + --build-arg PAYMENT_SUCCESS_REDIRECT_URL=\${PAYMENT_SUCCESS_REDIRECT_URL} \ + --build-arg MEMBER_GRPC_PORT=\${MEMBER_GRPC_PORT} \ + --build-arg AUTH_SERVER_PORT=\${AUTH_SERVER_PORT} \ + --build-arg MEMBER_SERVER_PORT=\${MEMBER_SERVER_PORT} \ + --build-arg RESUME_SERVER_PORT=\${RESUME_SERVER_PORT} \ + --build-arg PAYMENT_SERVER_PORT=\${PAYMENT_SERVER_PORT} \ + --build-arg NOTIFICATION_SERVER_PORT=\${NOTIFICATION_SERVER_PORT} \ + --build-arg CHAT_SERVER_PORT=\${CHAT_SERVER_PORT} \ + --build-arg GH_CLIENT_ID=\${GH_CLIENT_ID} \ + --build-arg GH_CLIENT_SECRET=\${GH_CLIENT_SECRET} \ + --build-arg GH_REDIRECT_URI=\${GH_REDIRECT_URI} \ + --build-arg GH_API_TOKEN=\${GH_API_TOKEN} \ + --build-arg JWT_SECRET_KEY=\${JWT_SECRET_KEY} \ + --build-arg ACCESS_TOKEN_EXPIRY=\${ACCESS_TOKEN_EXPIRY} \ + --build-arg REFRESH_TOKEN_EXPIRY=\${REFRESH_TOKEN_EXPIRY} \ + --build-arg AUTH_REDIS_HOST=\${AUTH_REDIS_HOST} \ + --build-arg AUTH_REDIS_PORT=\${AUTH_REDIS_PORT} \ + --build-arg RESUME_REDIS_HOST=\${RESUME_REDIS_HOST} \ + --build-arg RESUME_REDIS_PORT=\${RESUME_REDIS_PORT} \ + --build-arg MEMBER_MYSQL_DB_HOST=\${MEMBER_MYSQL_DB_HOST} \ + --build-arg MEMBER_MYSQL_DB_PORT=\${MEMBER_MYSQL_DB_PORT} \ + --build-arg MEMBER_MYSQL_DB_NAME=\${MEMBER_MYSQL_DB_NAME} \ + --build-arg MEMBER_MYSQL_DB_PASSWORD=\${MEMBER_MYSQL_DB_PASSWORD} \ + --build-arg MEMBER_MYSQL_DB_USERNAME=\${MEMBER_MYSQL_DB_USERNAME} \ + --build-arg LIKE_MYSQL_DB_HOST=\${LIKE_MYSQL_DB_HOST} \ + --build-arg LIKE_MYSQL_DB_PORT=\${LIKE_MYSQL_DB_PORT} \ + --build-arg LIKE_MYSQL_DB_NAME=\${LIKE_MYSQL_DB_NAME} \ + --build-arg LIKE_MYSQL_DB_PASSWORD=\${LIKE_MYSQL_DB_PASSWORD} \ + --build-arg LIKE_MYSQL_DB_USERNAME=\${LIKE_MYSQL_DB_USERNAME} \ + --build-arg PAYMENT_MYSQL_DB_HOST=\${PAYMENT_MYSQL_DB_HOST} \ + --build-arg PAYMENT_MYSQL_DB_PORT=\${PAYMENT_MYSQL_DB_PORT} \ + --build-arg PAYMENT_MYSQL_DB_NAME=\${PAYMENT_MYSQL_DB_NAME} \ + --build-arg PAYMENT_MYSQL_DB_PASSWORD=\${PAYMENT_MYSQL_DB_PASSWORD} \ + --build-arg PAYMENT_MYSQL_DB_USERNAME=\${PAYMENT_MYSQL_DB_USERNAME} \ + --build-arg NOTIFICATION_MYSQL_DB_HOST=\${NOTIFICATION_MYSQL_DB_HOST} \ + --build-arg NOTIFICATION_MYSQL_DB_PORT=\${NOTIFICATION_MYSQL_DB_PORT} \ + --build-arg NOTIFICATION_MYSQL_DB_NAME=\${NOTIFICATION_MYSQL_DB_NAME} \ + --build-arg NOTIFICATION_MYSQL_DB_PASSWORD=\${NOTIFICATION_MYSQL_DB_PASSWORD} \ + --build-arg NOTIFICATION_MYSQL_DB_USERNAME=\${NOTIFICATION_MYSQL_DB_USERNAME} \ + --build-arg MEMBER_MONGO_DB_URI=\${MEMBER_MONGO_DB_URI} \ + --build-arg RESUME_MONGO_DB_URI=\${RESUME_MONGO_DB_URI} \ + --build-arg CHAT_MONGO_DB_URI=\${CHAT_MONGO_DB_URI} \ + --build-arg S3_ACCESS_KEY=\${S3_ACCESS_KEY} \ + --build-arg S3_SECRET_KEY=\${S3_SECRET_KEY} \ + --build-arg S3_URL_PREFIX=\${S3_URL_PREFIX} \ + --build-arg KAKAO_API_URL=\${KAKAO_API_URL} \ + --build-arg KAKAOPAY_SECRET_KEY=\${KAKAOPAY_SECRET_KEY} \ + --build-arg KAFKA_HOST1=\${KAFKA_HOST1} \ + --build-arg KAFKA_PORT1=\${KAFKA_PORT1} \ + --build-arg KAFKA_BROKER_ID=\${KAFKA_BROKER_ID} \ + --build-arg KAFKA_ZOOKEEPER_CONNECT=\${KAFKA_ZOOKEEPER_CONNECT} \ + --build-arg KAFKA_LISTENER_DOCKER=\${KAFKA_LISTENER_DOCKER} \ + --build-arg KAFKA_LISTENER_EXTERNAL=\${KAFKA_LISTENER_EXTERNAL} \ + --build-arg KAFKA_ADVERTISED_LISTENER_DOCKER=\${KAFKA_ADVERTISED_LISTENER_DOCKER} \ + --build-arg KAFKA_ADVERTISED_LISTENER_EXTERNAL=\${KAFKA_ADVERTISED_LISTENER_EXTERNAL} \ + --build-arg KAFKA_INTER_BROKER_LISTENER_NAME=\${KAFKA_INTER_BROKER_LISTENER_NAME} \ + --build-arg KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=\${KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR} \ + . + + docker push ${imageTag} + """ + } + } + } + } + } + } + } + + post { + always { + script { + sh """ + docker builder prune -f --filter until=24h + docker image prune -f + rm -f .env + """ + } + } + success { + discordSend description: "백엔드 ECR 이미지 빌드 성공", + footer: "Jenkins Pipeline Success", + link: env.BUILD_URL, + result: currentBuild.currentResult, + title: JOB_NAME, + webhookURL: DISCORD_CI_WEBHOOK + } + failure { + discordSend description: "백엔드 ECR 이미지 빌드 실패", + footer: "Jenkins Pipeline Failed", + link: env.BUILD_URL, + result: currentBuild.currentResult, + title: JOB_NAME, + webhookURL: DISCORD_CI_WEBHOOK + } + } + + + + + } + } \ No newline at end of file diff --git a/Jenkinsfile-dev.md b/Jenkinsfile-dev.md new file mode 100644 index 0000000..14040a0 --- /dev/null +++ b/Jenkinsfile-dev.md @@ -0,0 +1,176 @@ +pipeline { +agent any + + environment { + AWS_REGION = 'ap-northeast-2' + ECR_REGISTRY = credentials('ecr-registry') + DISCORD_CI_WEBHOOK = credentials('dev-discord-ci-webhook') + DISCORD_CD_WEBHOOK = credentials('dev-discord-cd-webhook') + DOCKER_TAG = 'dev' + } + + stages { + stage('소스코드 체크아웃') { + steps { + script { + deleteDir() + git branch: 'develop', + url: 'https://github.com/KTB-Sixmen/gitfolio_back_spring.git' + } + } + } + + stage('환경 설정') { + steps { + script { + def envFile = '/var/lib/jenkins/environments/.env.back.dev' + if (fileExists(envFile)) { + sh """ + cp ${envFile} .env + echo '환경 파일 복사 완료: ${envFile}' + """ + } else { + error "환경 파일을 찾을 수 없습니다: ${envFile}" + } + + withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', + credentialsId: 'aws-credentials', + accessKeyVariable: 'AWS_ACCESS_KEY_ID', + secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { + sh """ + aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${ECR_REGISTRY} + echo 'ECR 로그인 완료' + """ + } + } + } + } + + stage('Builder 이미지 빌드') { + steps { + script { + sh """ + docker build \ + -f dockerfile \ + -t builder:${DOCKER_TAG} \ + --platform linux/amd64 \ + . + """ + } + } + } + + stage('모듈 빌드 및 배포') { + matrix { + axes { + axis { + name 'MODULE' + values 'auth', 'member', 'payment', 'resume', 'notification' + } + } + stages { + stage('모듈 빌드 및 푸시') { + steps { + script { + def moduleConfig = [ + auth: [path: './gitfolio-auth', index: '1'], + member: [path: './gitfolio-member', index: '1'], + payment: [path: './gitfolio-payment', index: '2'], + resume: [path: './gitfolio-resume', index: '2'], + notification: [path: './gitfolio-notification', index: '3'] + ] + + def config = moduleConfig[MODULE] + def imageTag = "${ECR_REGISTRY}/gitfolio/${MODULE}:${DOCKER_TAG}" + + sh """ + docker build \ + -f ${config.path}/Dockerfile \ + -t ${imageTag} \ + --build-arg BUILDER_IMAGE=${ECR_REGISTRY}/gitfolio/builder:${DOCKER_TAG} \ + --platform linux/amd64 \ + . + + docker push ${imageTag} + """ + + withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', + credentialsId: 'aws-credentials', + accessKeyVariable: 'AWS_ACCESS_KEY_ID', + secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { + + def instanceIds = sh( + script: """ + aws ec2 describe-instances \ + --region ${AWS_REGION} \ + --filters 'Name=tag:Service,Values=back' \ + 'Name=tag:Index,Values=${config.index}' \ + 'Name=tag:Environment,Values=dev' \ + 'Name=tag:Type,Values=ec2' \ + 'Name=instance-state-name,Values=running' \ + --query 'Reservations[].Instances[].InstanceId' \ + --output text + """, + returnStdout: true + ).trim() + + if (instanceIds) { + sh """ + aws ssm send-command \ + --instance-ids "${instanceIds}" \ + --document-name "AWS-RunShellScript" \ + --comment "Deploying ${MODULE} module" \ + --parameters commands=' + cd /home/ec2-user + docker-compose down -v --rmi all + docker builder prune -f --filter until=24h + docker image prune -f + docker-compose pull + docker-compose up -d + ' \ + --timeout-seconds 600 \ + --region ${AWS_REGION} + """ + } else { + error "${MODULE} 모듈을 위한 EC2 인스턴스를 찾을 수 없습니다." + } + } + } + } + } + } + } + } + } + + post { + always { + script { + sh """ + docker builder prune -f --filter until=24h + docker image prune -f + rm -f .env + """ + } + } + success { + discordSend description: "dev 백엔드 빌드 및 배포 성공", + footer: "Jenkins Pipeline Success", + link: env.BUILD_URL, + result: currentBuild.currentResult, + title: JOB_NAME, + webhookURL: DISCORD_CI_WEBHOOK + } + failure { + discordSend description: "dev 백엔드 빌드 및 배포 실패", + footer: "Jenkins Pipeline Failed", + link: env.BUILD_URL, + result: currentBuild.currentResult, + title: JOB_NAME, + webhookURL: DISCORD_CI_WEBHOOK + } + + + + } +} \ No newline at end of file diff --git a/docker-compose-dev.yaml b/docker-compose-dev.yaml new file mode 100644 index 0000000..34a850c --- /dev/null +++ b/docker-compose-dev.yaml @@ -0,0 +1,145 @@ +#services: +# builder: +# platform: linux/amd64 +# build: +# context: ./ +# dockerfile: dockerfile +# target: builder +# volumes: +# - gradle-cache:/root/.gradle +# - build-output:/gitfolio_back/build +# image: aida0/gitfolio_builder:test +# profiles: +# - build + +# 1번 모듈 +services: + auth: + platform: linux/amd64 + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/auth:dev + container_name: gitfolio_auth + ports: + - target: 8080 + published: 80 + protocol: tcp + - target: 8080 + published: 443 + protocol: tcp + networks: + - back + member: + platform: linux/amd64 + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/member:dev + container_name: gitfolio_member + ports: + - target: 8080 + published: 81 + protocol: tcp + - target: 8080 + published: 444 + protocol: tcp + networks: + - back +networks: + back: + driver: bridge + attachable: true + +#2번 모듈 +services: + resume: + platform: linux/amd64 + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/resume:dev + container_name: gitfolio_resume + ports: + - target: 8080 + published: 80 + protocol: tcp + - target: 8080 + published: 443 + protocol: tcp + networks: + - back + payment: + platform: linux/amd64 + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/payment:dev + container_name: gitfolio_payment + ports: + - target: 8080 + published: 81 + protocol: tcp + - target: 8080 + published: 444 + protocol: tcp + networks: + - back +networks: + back: + driver: overlay + attachable: true + +#3번모듈 +services: + notification: + platform: linux/amd64 + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/notification:dev + container_name: gitfolio_notification + ports: + - target: 8080 + published: 80 + protocol: tcp + - target: 8080 + published: 443 + protocol: tcp + networks: + - back + + zookeeper: + platform: linux/amd64 + image: zookeeper:3.6 + container_name: gitfolio_zookeeper + ports: + - target: 2181 + published: 2181 + protocol: tcp + volumes: + - zookeeper_data:/var/lib/zookeeper/data + networks: + - back + + kafka: + platform: linux/amd64 + image: confluentinc/cp-kafka:7.4.0 + container_name: gitfolio_kafka + ports: + - target: 9092 + published: 9092 + protocol: tcp + - target: 29092 + published: 29092 + protocol: tcp + # environment: 섹션이 있다면 제거하거나 주석처리 + environment: + KAFKA_BROKER_ID: 1 + KAFKA_LISTENERS: LISTENER_DOCKER://0.0.0.0:29092,LISTENER_EXTERNAL://0.0.0.0:9092 + KAFKA_ADVERTISED_LISTENERS: LISTENER_DOCKER://localhost:29092,LISTENER_EXTERNAL://10.0.105.99:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: LISTENER_DOCKER:PLAINTEXT,LISTENER_EXTERNAL:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: LISTENER_DOCKER + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + + depends_on: + - zookeeper + volumes: + - kafka_data:/var/lib/kafka/data + networks: + - back + +volumes: + zookeeper_data: + kafka_data: + +networks: + back: + driver: overlay + attachable: true \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 95519af..d1bfe4c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,24 +1,22 @@ -services: - builder: - platform: linux/amd64 - build: - context: ./ - dockerfile: dockerfile - target: builder - volumes: - - gradle-cache:/root/.gradle - - build-output:/gitfolio_back/build - image: aida0/gitfolio_builder:test - profiles: - - build +#services: +# builder: +# platform: linux/amd64 +# build: +# context: ./ +# dockerfile: dockerfile +# target: builder +# volumes: +# - gradle-cache:/root/.gradle +# - build-output:/gitfolio_back/build +# image: aida0/gitfolio_builder:test +# profiles: +# - build +# 1번 모듈 +services: auth: platform: linux/amd64 - build: - context: ./gitfolio-auth - dockerfile: dockerfile - target: runner - image: aida0/gitfolio_auth:test + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/auth:dev container_name: gitfolio_auth ports: - target: 8080 @@ -27,16 +25,11 @@ services: - target: 8080 published: 443 protocol: tcp - profiles: - - run - + networks: + - back member: platform: linux/amd64 - build: - context: ./gitfolio-member - dockerfile: dockerfile - target: runner - image: aida0/gitfolio_member:test + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/member:dev container_name: gitfolio_member ports: - target: 8080 @@ -45,17 +38,19 @@ services: - target: 8080 published: 444 protocol: tcp - profiles: - - run + networks: + - back +networks: + back: + driver: bridge + attachable: true - payment: +#2번 모듈 +services: + resume: platform: linux/amd64 - build: - context: ./gitfolio-payment - dockerfile: dockerfile - target: runner - image: aida0/gitfolio_payment:test - container_name: gitfolio_payment + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/resume:dev + container_name: gitfolio_resume ports: - target: 8080 published: 80 @@ -63,17 +58,12 @@ services: - target: 8080 published: 443 protocol: tcp - profiles: - - run - - resume: + networks: + - back + payment: platform: linux/amd64 - build: - context: ./gitfolio-resume - dockerfile: dockerfile - target: runner - image: aida0/gitfolio_resume:test - container_name: gitfolio_resume + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/payment:dev + container_name: gitfolio_payment ports: - target: 8080 published: 81 @@ -81,16 +71,18 @@ services: - target: 8080 published: 444 protocol: tcp - profiles: - - run + networks: + - back +networks: + back: + driver: overlay + attachable: true +#3번모듈 +services: notification: platform: linux/amd64 - build: - context: ./gitfolio-notification - dockerfile: dockerfile - target: runner - image: aida0/gitfolio_notification:test + image: 727646500036.dkr.ecr.ap-northeast-2.amazonaws.com/gitfolio/notification:dev container_name: gitfolio_notification ports: - target: 8080 @@ -99,27 +91,46 @@ services: - target: 8080 published: 443 protocol: tcp - profiles: - - run + networks: + - back - chat: + zookeeper: platform: linux/amd64 - build: - context: ./gitfolio-chat - dockerfile: dockerfile - target: runner - image: aida0/gitfolio_chat:test - container_name: gitfolio_chat + image: zookeeper:3.6 + container_name: gitfolio_zookeeper ports: - - target: 8080 - published: 80 + - target: 2181 + published: 2181 protocol: tcp - - target: 8080 - published: 443 + volumes: + - zookeeper_data:/var/lib/zookeeper/data + networks: + - back + + kafka: + platform: linux/amd64 + image: confluentinc/cp-kafka:7.4.0 + container_name: gitfolio_kafka + ports: + - target: 9092 + published: 9092 protocol: tcp - profiles: - - run + - target: 29092 + published: 29092 + protocol: tcp + # environment: 섹션이 있다면 제거하거나 주석처리 + depends_on: + - zookeeper + volumes: + - kafka_data:/var/lib/kafka/data + networks: + - back volumes: - gradle-cache: - build-output: \ No newline at end of file + zookeeper_data: + kafka_data: + +networks: + back: + driver: overlay + attachable: true \ No newline at end of file diff --git a/dockerfile b/dockerfile index a23ee5d..553dce2 100644 --- a/dockerfile +++ b/dockerfile @@ -20,7 +20,18 @@ RUN chmod +x gradlew && \ COPY . . -RUN ./gradlew clean build -x test && \ +RUN cat .env && \ + ./gradlew clean build -x test && \ # 테스트 후 없앨지 결정 cp .env build && \ - cp */build/libs/*-SNAPSHOT.jar build \ No newline at end of file + cp */build/libs/*-SNAPSHOT.jar build + + # 환경 파일 권한 설정 + +RUN chmod 644 build/.env && \ + cp */build/libs/*-SNAPSHOT.jar build && \ + # 환경 변수 확인을 위한 출력 + # 디버깅을 위한 환경 파일 확인 + echo "===== 환경 파일 내용 확인 =====" && \ + ls -la build/.env && \ + cat build/.env \ No newline at end of file diff --git a/gitfolio-auth/dockerfile b/gitfolio-auth/dockerfile index 1146874..0d24f6a 100644 --- a/gitfolio-auth/dockerfile +++ b/gitfolio-auth/dockerfile @@ -1,8 +1,11 @@ FROM amazoncorretto:17 AS runner + WORKDIR /auth EXPOSE 8080 -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/.env .env -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/*-auth-*-SNAPSHOT.jar auth.jar +# 빌더 스테이지에서 파일 복사 +COPY --from=builder:dev /gitfolio_back/build/.env .env +COPY --from=builder:dev /gitfolio_back/build/*-auth-*-SNAPSHOT.jar auth.jar -CMD [ "java", "-jar", "auth.jar" ] \ No newline at end of file +# 디버깅을 포함한 실행 명령 +CMD [ "java", "-jar", "auth.jar" ] diff --git a/gitfolio-chat/dockerfile b/gitfolio-chat/dockerfile deleted file mode 100644 index a63fe90..0000000 --- a/gitfolio-chat/dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM amazoncorretto:17 AS runner -WORKDIR /chat -EXPOSE 8080 - -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/.env .env -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/*-chat-*-SNAPSHOT.jar chat.jar - -CMD [ "java", "-jar", "chat.jar" ] \ No newline at end of file diff --git a/gitfolio-member/dockerfile b/gitfolio-member/dockerfile index c76e439..53e9d50 100644 --- a/gitfolio-member/dockerfile +++ b/gitfolio-member/dockerfile @@ -1,8 +1,10 @@ FROM amazoncorretto:17 AS runner + WORKDIR /member EXPOSE 8081 -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/.env .env -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/*-member-*-SNAPSHOT.jar member.jar +# 빌더 스테이지에서 파일 복사 +COPY --from=builder:dev /gitfolio_back/build/.env .env +COPY --from=builder:dev /gitfolio_back/build/*-member-*-SNAPSHOT.jar member.jar CMD [ "java", "-jar", "member.jar" ] \ No newline at end of file diff --git a/gitfolio-notification/dockerfile b/gitfolio-notification/dockerfile index a4868b9..f513316 100644 --- a/gitfolio-notification/dockerfile +++ b/gitfolio-notification/dockerfile @@ -1,8 +1,10 @@ FROM amazoncorretto:17 AS runner + WORKDIR /notification EXPOSE 8080 -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/.env .env -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/*-notification-*-SNAPSHOT.jar notification.jar +# 빌더 스테이지에서 파일 복사 +COPY --from=builder:dev /gitfolio_back/build/.env .env +COPY --from=builder:dev /gitfolio_back/build/*-notification-*-SNAPSHOT.jar notification.jar CMD [ "java", "-jar", "notification.jar" ] \ No newline at end of file diff --git a/gitfolio-payment/dockerfile b/gitfolio-payment/dockerfile index a25bf1e..a7065ec 100644 --- a/gitfolio-payment/dockerfile +++ b/gitfolio-payment/dockerfile @@ -1,8 +1,10 @@ FROM amazoncorretto:17 AS runner + WORKDIR /payment EXPOSE 8083 -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/.env .env -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/*-payment-*-SNAPSHOT.jar payment.jar +# 빌더 스테이지에서 파일 복사 +COPY --from=builder:dev /gitfolio_back/build/.env .env +COPY --from=builder:dev /gitfolio_back/build/*-payment-*-SNAPSHOT.jar payment.jar CMD [ "java", "-jar", "payment.jar" ] \ No newline at end of file diff --git a/gitfolio-resume/dockerfile b/gitfolio-resume/dockerfile index dc3865c..c3aac4d 100644 --- a/gitfolio-resume/dockerfile +++ b/gitfolio-resume/dockerfile @@ -1,8 +1,10 @@ FROM amazoncorretto:17 AS runner + WORKDIR /resume EXPOSE 8082 -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/.env .env -COPY --from=aida0/gitfolio_builder:test /gitfolio_back/build/*-resume-*-SNAPSHOT.jar resume.jar +# 빌더 스테이지에서 파일 복사 +COPY --from=builder:dev /gitfolio_back/build/.env .env +COPY --from=builder:dev /gitfolio_back/build/*-resume-*-SNAPSHOT.jar resume.jar CMD [ "java", "-jar", "resume.jar" ] \ No newline at end of file