Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 72 additions & 53 deletions .github/workflows/app-cd-dev.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
name: ⚙️ MAKERS-DEV-APP-DEPLOY

# 해당 스크립트를 사용하지 않고 있는 상태에서 스크립트 수정이 진행됨. 추후 스크립트 사용 시 점검 필요
on:
workflow_dispatch:
push:
# branches: [ dev ]
# branches: [ 'dev' ]

env:
SPRING_PROFILES_ACTIVE: dev
Expand All @@ -11,100 +13,117 @@ env:
ECR_HOST: ${{ secrets.ECR_HOST }}

jobs:
build:
build-and-deploy:
name: CD Pipeline
runs-on: ubuntu-latest

steps:
- name: checkout
- name: Checkout Source
uses: actions/checkout@v3

- name: set up JDK 21
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '21'

- name: touch yml files
- name: Gradle Build
run: |
touch ./src/main/resources/application-dev.yml
touch ./src/test/resources/application-test.yml

shell: bash

- name: copy application.yml files
run: |
echo "${{ secrets.APPLICATION_DEV_YML }}" > ./src/main/resources/application-dev.yml
echo "${{ secrets.APPLICATION_TEST_YML }}" > ./src/test/resources/application-test.yml
chmod +x ./gradlew
./gradlew clean build -x test

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
aws-region: ap-northeast-2
aws-region: ${{ secrets.AWS_REGION }}

- name: 🐘Gradle Build
run: |
chmod +x ./gradlew
./gradlew clean build -x test

- name: Login to ECR
- name: Login to ECR Public
run: |
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin $ECR_HOST

- name: Delete previous ECR images
run: |
echo "Deleting all images from ECR repository: $ECR_APP_NAME"
aws ecr-public batch-delete-image \
--region us-east-1 \
--repository-name $ECR_APP_NAME \
--image-ids "$(aws ecr-public describe-images --region us-east-1 --repository-name $ECR_APP_NAME --query 'imageDetails[*].{imageDigest:imageDigest}' --output json)" \
|| echo "No images to delete or repository is empty"

- name: 🐳Docker Image Build & Push
- name: Docker Image Build & Push
env:
GITHUB_SHA: ${{ github.sha }}
run: |
IMAGE_TAG=$(echo $GITHUB_SHA | cut -c1-8)

docker build \
--no-cache \
--build-arg SPRING_PROFILES_ACTIVE=$SPRING_PROFILES_ACTIVE \
-t $ECR_APP_NAME .
docker tag $ECR_APP_NAME:latest $APP_ECR_REPO
docker push $APP_ECR_REPO

docker tag $ECR_APP_NAME:latest $APP_ECR_REPO:latest
docker tag $ECR_APP_NAME:latest $APP_ECR_REPO:$IMAGE_TAG

docker push $APP_ECR_REPO:latest
docker push $APP_ECR_REPO:$IMAGE_TAG

- name: Prune old ECR Public images (keep 5 latest)
run: |
echo "Pruning old images, keeping only 5 most recent..."
ECR_REPO_NAME="${{ secrets.ECR_APP_NAME }}-dev"

IMAGES=$(aws ecr-public describe-images \
--region us-east-1 \
--repository-name $ECR_REPO_NAME \
--query 'sort_by(imageDetails,& imagePushedAt)[*].imageDigest' \
--output json)

COUNT=$(echo $IMAGES | jq length)

if [ "$COUNT" -gt 5 ]; then
TO_DELETE=$(echo $IMAGES | jq -c ".[0:$((COUNT-5))] | map({imageDigest: .})")
if [ "$TO_DELETE" != "[]" ]; then
aws ecr-public batch-delete-image \
--region us-east-1 \
--repository-name $ECR_REPO_NAME \
--image-ids "$TO_DELETE"
echo "✅ success delete old image"
fi
else
echo "Less than or equal to 5 images, skipping prune"
fi

- name: Create Config Files Dynamically
env:
GITHUB_SHA: ${{ github.sha }}
run: |
mkdir -p ./config

- name: Copy docker-compose.yml
run: echo "${{ secrets.DOCKER_COMPOSE_DEV_YML }}" > ./docker-compose.yml
IMAGE_TAG=$(echo $GITHUB_SHA | cut -c1-8)

- name: Send docker-compose.yml to EC2 Instance
uses: appleboy/scp-action@master
with:
username: ec2-user
host: ${{ secrets.DEV_SERVER_IP }}
key: ${{ secrets.DEV_PEM_KEY }}
source: "./docker-compose.yml"
target: "/home/ec2-user/app/"
echo "${{ secrets.APPLICATION_DEV_YML }}" > ./config/application-dev.yml
echo "${{ secrets.DOCKER_COMPOSE_DEV_YML }}" > ./docker-compose.yml

touch .env
echo "SPRING_PROFILES_ACTIVE=dev" >> .env
echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_ID }}" >> .env
echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_KEY }}" >> .env
echo "AWS_REGION=${{ secrets.AWS_REGION }}" >> .env
echo "IMAGE_TAG=${IMAGE_TAG}" >> .env

- name: Send deploy script to EC2 Instance
- name: Send Files to EC2
uses: appleboy/scp-action@master
with:
username: ec2-user
host: ${{ secrets.DEV_SERVER_IP }}
key: ${{ secrets.DEV_PEM_KEY }}
source: "./script/"
source: ".env,docker-compose.yml,script/,config/"
target: "/home/ec2-user/app/"

- name: Docker Container Run
- name: Execute Deployment on EC2
uses: appleboy/ssh-action@master
with:
username: ec2-user
host: ${{ secrets.DEV_SERVER_IP }}
key: ${{ secrets.DEV_PEM_KEY }}
script: |
cd ~
cd ./app
echo "Creating .env file..."
echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_ID }}" > .env
echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_KEY }}" >> .env
cd /home/ec2-user/app
chmod 600 .env
chmod 600 ./config/application-dev.yml
chmod +x ./script/*.sh

sudo chmod +x ./script/*.sh
./script/deploy.sh
docker image prune -f
116 changes: 72 additions & 44 deletions .github/workflows/release-prod.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: 🚀MAKERS-APP-RELEASE!
name: 🚀 MAKERS-APP-RELEASE!

on:
workflow_dispatch:
push:
branches: [ 'main' ]
tags: [ 'makers-app-prod' ]
Expand All @@ -12,91 +13,118 @@ env:
ECR_HOST: ${{ secrets.ECR_HOST }}

jobs:
build:
build-and-deploy:
name: CD Pipeline
runs-on: ubuntu-latest

steps:
- name: checkout
- name: Checkout Source
uses: actions/checkout@v3

- name: set up JDK 21
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '21'

- name: touch yml files
- name: Gradle Build (No Secrets)
run: |
touch ./src/main/resources/application-prod.yml
touch ./src/test/resources/application-test.yml
shell: bash

- name: copy application.yml files
run: |
echo "${{ secrets.APPLICATION_PROD_YML }}" > ./src/main/resources/application-prod.yml
echo "${{ secrets.APPLICATION_TEST_YML }}" > ./src/test/resources/application-test.yml
chmod +x ./gradlew
./gradlew clean build -x test

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
aws-region: ap-northeast-2
aws-region: ${{ secrets.AWS_REGION }}

- name: 🐘Gradle Build
run: |
chmod +x ./gradlew
./gradlew clean build -x test

- name: Login to ECR
- name: Login to ECR Public
run: |
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin $ECR_HOST

- name: 🐳Docker Image Build & Push
- name: Docker Image Build & Push
env:
GITHUB_SHA: ${{ github.sha }}
run: |
IMAGE_TAG=$(echo $GITHUB_SHA | cut -c1-8)

docker build \
--no-cache \
-f Dockerfile-prod \
--build-arg SPRING_PROFILES_ACTIVE=$SPRING_PROFILES_ACTIVE \
-t $ECR_APP_NAME .
docker tag $ECR_APP_NAME:latest $APP_ECR_REPO
docker push $APP_ECR_REPO

docker tag $ECR_APP_NAME:latest $APP_ECR_REPO:latest
docker tag $ECR_APP_NAME:latest $APP_ECR_REPO:$IMAGE_TAG

docker push $APP_ECR_REPO:latest
docker push $APP_ECR_REPO:$IMAGE_TAG

- name: Prune old ECR Public images (keep 5 latest)
run: |
echo "Pruning old images, keeping only 5 most recent..."
ECR_REPO_NAME="${{ secrets.ECR_APP_NAME }}-prod"

IMAGES=$(aws ecr-public describe-images \
--region us-east-1 \
--repository-name $ECR_REPO_NAME \
--query 'sort_by(imageDetails,& imagePushedAt)[*].imageDigest' \
--output json)

- name: Copy docker-compose.yml
run: echo "${{ secrets.DOCKER_COMPOSE_PROD_YML }}" > ./docker-compose.yml
COUNT=$(echo $IMAGES | jq length)

- name: Send docker-compose.yml to EC2 Instance
uses: appleboy/scp-action@master
with:
username: ubuntu
host: ${{ secrets.PROD_SERVER_IP }}
key: ${{ secrets.PROD_PEM_KEY }}
source: "./docker-compose.yml"
target: "/home/ubuntu/app/"
if [ "$COUNT" -gt 5 ]; then
TO_DELETE=$(echo $IMAGES | jq -c ".[0:$((COUNT-5))] | map({imageDigest: .})")
if [ "$TO_DELETE" != "[]" ]; then
aws ecr-public batch-delete-image \
--region us-east-1 \
--repository-name $ECR_REPO_NAME \
--image-ids "$TO_DELETE"
echo "✅ success delete old image"
fi
else
echo "Less than or equal to 5 images, skipping prune"
fi

- name: Create Config Files Dynamically
env:
GITHUB_SHA: ${{ github.sha }}
run: |
mkdir -p ./config

IMAGE_TAG=$(echo $GITHUB_SHA | cut -c1-8)

echo "${{ secrets.APPLICATION_PROD_YML }}" > ./config/application-prod.yml
echo "${{ secrets.DOCKER_COMPOSE_PROD_YML }}" > ./docker-compose.yml

touch .env
echo "SPRING_PROFILES_ACTIVE=prod" >> .env
echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_ID }}" >> .env
echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_KEY }}" >> .env
echo "AWS_REGION=${{ secrets.AWS_REGION }}" >> .env
echo "IMAGE_TAG=${IMAGE_TAG}" >> .env

- name: Send deploy script to EC2 Instance
- name: Send Files to EC2
uses: appleboy/scp-action@master
with:
username: ubuntu
host: ${{ secrets.PROD_SERVER_IP }}
key: ${{ secrets.PROD_PEM_KEY }}
source: "./script/"
source: ".env,docker-compose.yml,script/,config/"
target: "/home/ubuntu/app/"

- name: Docker Container Run
- name: Execute Deployment on EC2
uses: appleboy/ssh-action@master
with:
username: ubuntu
host: ${{ secrets.PROD_SERVER_IP }}
key: ${{ secrets.PROD_PEM_KEY }}
script: |
cd ~
cd ./app
echo "Creating .env file..."
echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_ID }}" > .env
echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_KEY }}" >> .env
cd /home/ubuntu/app
chmod 600 .env
chmod 600 ./config/application-prod.yml
chmod +x ./script/*.sh

sudo chmod +x ./script/*.sh
./script/deploy.sh
docker image prune -f
docker image prune -f
6 changes: 1 addition & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
FROM amazoncorretto:21
WORKDIR /app
COPY ./build/libs/app-server-0.0.1-SNAPSHOT.jar /app/app-application.jar
COPY ./src/main/resources/application-dev.yml /app/application-dev.yml

ARG SPRING_PROFILES_ACTIVE
ENV SPRING_PROFILES_ACTIVE=$SPRING_PROFILES_ACTIVE

CMD ["java", "-jar", "-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "-Dspring.config.location=file:/app/application-dev.yml", "app-application.jar"]
CMD ["java", "-jar", "app-application.jar"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 Docker 이미지에 환경별 yml을 포함하지 않고, 실행 시점에 외부에서 주입하려고 이렇게 단순화하신 걸까요? 이미지 자체는 환경에 독립적으로 유지하려는 의도로 이해했습니다 👍 너무 좋아요!!

6 changes: 1 addition & 5 deletions Dockerfile-prod
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
FROM amazoncorretto:21
WORKDIR /app
COPY ./build/libs/app-server-0.0.1-SNAPSHOT.jar /app/app-application.jar
COPY ./src/main/resources/application-prod.yml /app/application-prod.yml

ARG SPRING_PROFILES_ACTIVE
ENV SPRING_PROFILES_ACTIVE=$SPRING_PROFILES_ACTIVE

CMD ["java", "-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "-Dspring.config.location=file:/app/application-prod.yml", "-jar", "app-application.jar"]
CMD ["java", "-jar", "app-application.jar"]
2 changes: 1 addition & 1 deletion script/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ BLUE_PORT=9090
GREEN_CONTAINER_NAME="app-green"
GREEN_PORT=9091

DOCKER_PS_OUTPUT=$(docker ps --format "{{.Names}}" | grep -E "(${BLUE_CONTAINER_NAME}|${GREEN_CONTAINER_NAME})" || true)
DOCKER_PS_OUTPUT=$(docker ps --format "{{.Names}}" | grep -E "(${BLUE_CONTAINER_NAME}|${GREEN_CONTAINER_NAME})" | head -n 1 || true)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 이건 여러 컨테이너 잡힐 때 딱 하나만 하는 용도인가요..?

RUNNING_CONTAINER_NAME="${DOCKER_PS_OUTPUT:-}"

ALL_PORTS=("${BLUE_PORT}" "${GREEN_PORT}")
Expand Down
Loading
Loading