Multi-Module Deployment to AWS ECR and EC2 #258
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Multi-Module Deployment to AWS ECR and EC2 | |
on: | |
workflow_dispatch: | |
inputs: | |
profile: | |
description: '프로파일을 선택하세요 (dev 또는 prod)' | |
required: true | |
default: 'dev' | |
type: choice | |
options: | |
- dev | |
- prod | |
package: | |
description: '배포할 패키지를 선택하세요' | |
required: true | |
default: 'peauty-customer-api' | |
type: choice | |
options: | |
- customer | |
- designer | |
permissions: | |
contents: read | |
jobs: | |
deploy: | |
runs-on: ubuntu-latest | |
steps: | |
# 1. 코드 체크아웃 | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
# 2. 환경 변수 설정 | |
- name: Set environment variables | |
run: | | |
echo "DEPLOY_PROFILE=${{ github.event.inputs.profile }}" >> $GITHUB_ENV | |
echo "DEPLOY_DOMAIN=${{ github.event.inputs.package }}" >> $GITHUB_ENV | |
echo "TARGET_PACKAGE=peauty-${{ github.event.inputs.package }}-api" >> $GITHUB_ENV | |
# 프로파일과 패키지에 따라 호스트와 사용자 설정 | |
if [[ "${{ github.event.inputs.profile }}" == "prod" && "${{ github.event.inputs.package }}" == "customer" ]]; then | |
echo "HOST_SECRET=EC2_CUSTOMER_PROD" >> $GITHUB_ENV | |
elif [[ "${{ github.event.inputs.profile }}" == "prod" && "${{ github.event.inputs.package }}" == "designer" ]]; then | |
echo "HOST_SECRET=EC2_DESIGNER_PROD" >> $GITHUB_ENV | |
elif [[ "${{ github.event.inputs.profile }}" == "dev" && "${{ github.event.inputs.package }}" == "customer" ]]; then | |
echo "HOST_SECRET=EC2_CUSTOMER_DEV" >> $GITHUB_ENV | |
elif [[ "${{ github.event.inputs.profile }}" == "dev" && "${{ github.event.inputs.package }}" == "designer" ]]; then | |
echo "HOST_SECRET=EC2_DESIGNER_DEV" >> $GITHUB_ENV | |
else | |
echo "Invalid profile or package selection" | |
exit 1 | |
fi | |
# 환경 변수 검증 | |
- name: Debug environment variables | |
run: | | |
echo "DEPLOY_PROFILE: $DEPLOY_PROFILE" | |
echo "DEPLOY_DOMAIN: $DEPLOY_DOMAIN" | |
echo "TARGET_PACKAGE: $TARGET_PACKAGE" | |
echo "HOST_SECRET: $HOST_SECRET" | |
# 2. Java 17 설치 | |
- name: Set up JDK 17 | |
uses: actions/setup-java@v3 | |
with: | |
java-version: '17' | |
distribution: 'corretto' | |
package: 'jdk' | |
jdk-version: '17.0.12' | |
# 3. 선택된 패키지 빌드 (로컬에서 JAR 생성) | |
- name: Build Selected Package | |
run: | | |
echo "Building $TARGET_PACKAGE with profile $DEPLOY_PROFILE..." | |
# 선택한 패키지 디렉토리로 이동 후 Gradle 빌드 | |
# $TARGET_PACKAGE-$DEPLOY_PROFILE => profile 이름이 customer-prod라서 | |
./gradlew clean build -Pspring.profiles.active=$TARGET_DOMAIN-$DEPLOY_PROFILE -p $TARGET_PACKAGE | |
# 빌드 완료 확인 | |
if [ ! -f $TARGET_PACKAGE/build/libs/*SNAPSHOT.jar ]; then | |
echo "Build failed: JAR file not found in $TARGET_PACKAGE/build/libs/" | |
exit 1 | |
fi | |
echo "Build successful. JAR file located at $TARGET_PACKAGE/build/libs/" | |
# 4-1. ECR 자격 증명 | |
- name: Configure AWS credentials | |
uses: aws-actions/configure-aws-credentials@v3 | |
with: | |
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
aws-region: ap-northeast-2 | |
# 4-2. ECR 로그인 | |
- name: Log in to Amazon ECR | |
id: ecr-login | |
uses: aws-actions/amazon-ecr-login@v2 | |
# 5. 하루 이전에 푸시된 이미지 삭제 | |
- name: Delete Images Older Than 1 Day | |
env: | |
ECR_REGISTRY: ${{ steps.ecr-login.outputs.registry }} | |
ECR_REPOSITORY: peauty/server | |
run: | | |
echo "Fetching and deleting images older than 1 day..." | |
# 현재 시간에서 1일 전 날짜 계산 | |
ONE_DAY_AGO=$(date -d '1 day ago' +%Y-%m-%dT%H:%M:%S) | |
# 하루 이전에 푸시된 이미지 조회 및 삭제 | |
aws ecr describe-images \ | |
--repository-name $ECR_REPOSITORY \ | |
--query 'imageDetails[?imagePushedAt<`'$ONE_DAY_AGO'`].[imageDigest]' \ | |
--output text | while read DIGEST; do | |
echo "Deleting image with digest: $DIGEST" | |
aws ecr batch-delete-image \ | |
--repository-name $ECR_REPOSITORY \ | |
--image-ids imageDigest=$DIGEST | |
done | |
echo "Old images deleted successfully!" | |
# 5. Docker 이미지 빌드 및 푸시 | |
- name: Build and Push Docker Image to ECR | |
env: | |
ECR_REGISTRY: ${{ steps.ecr-login.outputs.registry }} | |
ECR_REPOSITORY: peauty/server | |
IMAGE_TAG: ${{env.DEPLOY_DOMAIN}}-${{ env.DEPLOY_PROFILE }} | |
run: | | |
echo "Building Docker image for $TARGET_PACKAGE with profile $DEPLOY_PROFILE..." | |
docker build -t $ECR_REPOSITORY:$IMAGE_TAG -f $TARGET_PACKAGE/Dockerfile $TARGET_PACKAGE | |
docker tag $ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG | |
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG | |
# 6. EC2 서버에 배포 | |
- name: Deploy to EC2 Server | |
uses: appleboy/[email protected] | |
env: | |
DEPLOY_PROFILE: ${{ github.event.inputs.profile }} | |
DEPLOY_DOMAIN: ${{ github.event.inputs.package }} | |
TARGET_PACKAGE: peauty-${{ github.event.inputs.package }}-api | |
ECR_REGISTRY: ${{ steps.ecr-login.outputs.registry }} | |
ECR_REPOSITORY: peauty/server | |
IMAGE_TAG: ${{ github.event.inputs.package }}-${{ github.event.inputs.profile }} | |
with: | |
host: ${{ secrets[env.HOST_SECRET] }} | |
username: ${{ secrets.EC2_USER }} | |
key: ${{ secrets.EC2_SSH_KEY }} | |
envs: DEPLOY_PROFILE,DEPLOY_DOMAIN,TARGET_PACKAGE,ECR_REGISTRY,ECR_REPOSITORY,IMAGE_TAG | |
script: | | |
echo "Deploying to EC2 for $TARGET_PACKAGE with profile $DEPLOY_PROFILE" | |
# AWS CLI 설정 | |
aws configure set aws_access_key_id ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws configure set aws_secret_access_key ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
aws configure set region ap-northeast-2 | |
# 기존 컨테이너 중지 및 삭제 | |
echo "Docker Container Status" | |
docker ps | |
echo "STOP $DEPLOY_DOMAIN-$DEPLOY_PROFILE" | |
docker stop $DEPLOY_DOMAIN-$DEPLOY_PROFILE || { echo "Failed to stop container"; } | |
docker rm $DEPLOY_DOMAIN-$DEPLOY_PROFILE || { echo "Failed to remove container"; } | |
# 사용하지 않는 이전 도커 이미지 삭제 | |
echo "=== Cleaning up unused Docker images ===" | |
docker image prune -af || { echo "Failed to prune Docker images"; } | |
# .env 파일 생성 | |
echo "Generating .env file..." | |
rm -f .env | |
echo "${{ secrets.ALL_SECRET }}" > .env | |
echo ".env file generated:" | |
# Docker 이미지 Pull | |
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin $ECR_REGISTRY | |
docker pull $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG | |
# 새로운 컨테이너 실행 | |
docker run --env-file ./.env -d -p 8080:8080 --name $DEPLOY_DOMAIN-$DEPLOY_PROFILE \ | |
--env SPRING_PROFILES_ACTIVE=$DEPLOY_DOMAIN-$DEPLOY_PROFILE \ | |
$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG | |
# 새로운 컨테이너 상태 확인 | |
echo "=== Verifying the new container ===" | |
sleep 10 # 컨테이너 초기화를 위한 대기 시간 | |
if ! docker ps --filter "name=$DEPLOY_DOMAIN-$DEPLOY_PROFILE" --filter "status=running" | grep $DEPLOY_DOMAIN-$DEPLOY_PROFILE; then | |
echo "새로운 컨테이너가 실행 중이지 않습니다. 로그를 확인하세요." | |
docker logs --tail 50 $DEPLOY_DOMAIN-$DEPLOY_PROFILE | |
exit 1 | |
fi | |
# 컨테이너 상태 확인 | |
docker ps | |
# 7. Gradle 빌드 및 Docker 이미지 빌드/푸시 | |
# - name: Gradle Build and Docker Image Push | |
# run: | | |
# echo "=== Starting Gradle Build and Docker Push ===" | |
# | |
# - name: Login to Docker Hub | |
# env: | |
# DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | |
# DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | |
# IMAGE_TAG: ${{env.DEPLOY_DOMAIN}}-${{ env.DEPLOY_PROFILE }} | |
# run: | | |
# echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin | |
# | |
# - name: Build and Push Docker Image | |
# run: | | |
# # echo "Using Dockerfile in $TARGET_PACKAGE with build context $TARGET_PACKAGE" | |
# docker build -t 93ed43223fb8/docker-peauty:$IMAGE_TAG . | |
# | |
# # echo "Pushing Docker image to ECR..." | |
# docker push 93ed43223fb8/docker-peauty:$IMAGE_TAG | |
# # Docker 빌드 컨텍스트 설정 | |
# echo "Using Dockerfile in $TARGET_PACKAGE with build context $TARGET_PACKAGE" | |
# | |
# # Docker 이미지 빌드 | |
# echo "Building Docker image..." | |
# docker build -t 93ed43223fb8/docker-peauty:$IMAGE_TAG . | |
# | |
# # Docker 이미지 태그 및 푸시 | |
# echo "Pushing Docker image to ECR..." | |
# docker push 93ed43223fb8/docker-peauty:$IMAGE_TAG | |
# | |
# echo "=== Gradle Build and Docker Image Push Completed ===" |