💡 자동화 배포 아키텍처
위 아키텍처와 같이 GitHub에 push하면 GitHub Actions에서 CI/CD가 진행된다.
- GitHub Actions에서 프로젝트 빌드 및 Docker 이미지 생성
- ECR에 접속 후 이미지 push
- EC2에 접속하여 ECR에서 이미지 pull 후 Docker로 실행
배포 환경
- AWS EC2 Ubuntu
- JDK 17
- RDS MySQL
EC2와 RDS 생성 과정은 생략함(프리티어로 설정)
인스턴스 생성이 완료되면 EC2 내부에 접속.
ssh -i 생성된키.pem ubuntu@퍼블릭 IPv4 주소
생성된 인스턴스에 ubuntu
사용자로 접속한다.
aws 명령어 사용을 위해 aws-cli 설치.
sudo snap install aws-cli --classic
Docker를 설치하고 EC2 인스턴스에서 권한을 부여한다.
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
sudo apt update
sudo apt install docker-ce
설치가 완료되면 아래 명령어로 Docker가 제대로 설치되었는지 확인
docker --version
마지막으로 Docker 실행 권한을 인스턴스 사용자에게 부여한다.
sudo usermod -a -G docker ubuntu
AWS ECR(Elastic Container Registry)은 AWS에서 제공하는 Docker 이미지 저장소다.
ECR 메뉴에서 '레포지토리 생성'을 클릭한 후 이름을 설정하고 생성한다.
생성된 레포지토리를 클릭해 '푸시 명령 보기'를 통해 명령어를 확인할 수 있다.
IAM 메뉴로 들어가 '사용자 생성' 클릭 후, '직접 정책 연결'에서 AmazonEC2ContainerRegistryFullAccess
권한을 부여한다.
사용자 생성 후 액세스 키와 비밀 액세스 키를 발급받고, EC2에 접속하여 AWS CLI 설정을 진행하기 위해 아래 명령어를 입력하여 엑세스키와 시크릿키를 입력한다.
aws configure
ap-northeast-2
입력GitHub에서 Actions
탭으로 들어가 set up a workflow
를 클릭한 후 아래와 같은 YAML 파일을 작성.
먼저, main
브랜치에 push될 때 Docker 이미지를 빌드하고 Amazon ECR로 푸시하는 작업을 진행한다.
name: Build and Deploy to EC2
on:
push:
branches:
- main
jobs:
build:
name: Build Docker image and push to ECR
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: '17'
- name: Build with Gradle
run: ./gradlew build -x test
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2
- name: Log in to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
run: |
REGION="ap-northeast-2"
ECR_REPOSITORY="rednotice-ecr"
IMAGE_TAG="latest"
docker build -t $ECR_REPOSITORY:$IMAGE_TAG .
docker tag $ECR_REPOSITORY:$IMAGE_TAG ${{ steps.login-ecr.outputs.registry }}/$ECR_REPOSITORY:$IMAGE_TAG
docker push ${{ steps.login-ecr.outputs.registry }}/$ECR_REPOSITORY:$IMAGE_TAG
actions/checkout@v2
을 사용해 코드 체크아웃 (프로젝트 코드를 깃액션으로 가져옴을 의미한다)setup-java
로 JDK 17 설치 후 ./gradlew build -x test
로 Gradle 빌드 진행aws-actions/configure-aws-credentials
로 AWS 자격 증명 설정 후 ECR에 로그인 및 이미지 푸시EC2에 SSH로 접속해 Docker 이미지를 pull하고 컨테이너를 실행.
deploy:
name: Deploy to EC2
runs-on: ubuntu-latest
needs: build
steps:
- name: Execute remote SSH commands on EC2
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
port: 22
script: |
REGION="ap-northeast-2"
ECR_REPOSITORY="rednotice-ecr"
IMAGE_TAG="latest"
AWS_ACCOUNT_ID=${{ secrets.AWS_ACCOUNT_ID }}
docker stop REDnotice || true
docker rm REDnotice || true
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com
docker pull $AWS_ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$ECR_REPOSITORY:$IMAGE_TAG
docker run -d --name REDnotice -p 8080:8080 \
-e SPRING_PROFILES_ACTIVE=prod \
-e SLACK_INCOMING_HOOK_URL=${{ secrets.SLACK_INCOMING_HOOK_URL }} \
-e JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }} \
-e S3_ACCESS_KEY=${{ secrets.S3_ACCESS_KEY }} \
-e S3_SECRET_KEY=${{ secrets.S3_SECRET_KEY }} \
-e RDS_PASSWORD=${{ secrets.RDS_PASSWORD }} \
$AWS_ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$ECR_REPOSITORY:$IMAGE_TAG
이 단계에서는 EC2에 SSH로 접속해 기존 컨테이너를 중지 및 삭제 후, ECR에서 최신 이미지를 pull하여 Docker 컨테이너로 실행한다.
FROM openjdk:17-jdk-alpine
WORKDIR /app
COPY build/libs/*.jar REDnotice.jar
# 컨테이너 시작 시 실행할 명령어
ENTRYPOINT ["java", "-jar", "REDnotice.jar"]
GitHub Repository에서 Settings
-> Secrets
-> Actions
에서 시크릿 키를 추가한다. 예시로 AWS_ACCESS_KEY_ID
, AWS_SECRET_ACCESS_KEY
, EC2_HOST
등을 설정.
시크릿 키는 다음과 같이 사용.
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
이제 모든 설정이 완료되면, main 브랜치에 push하는 것만으로도 자동으로 빌드 및 배포가 진행된다.