목차
과정
1. Github main 브랜치에 Push
2. Github Actions에서 AWS S3에 빌드 파일 및 Dockerfile, deploy.sh 등 업로드
3. Github Actions이 AWS CodeDeploy에 배포 요청
4. CodeDeploy가 배포 실행
5. 도커 빌드 및 실행
위와 같은 과정으로 자동 배포화가 진행됩니다.
Github Actions -> S3 빌드 및 업로드
- S3 버킷 생성
IAM 사용자를 통해 S3 저장소에 접근 할 것이기 때문에 모든 퍼블릭 액세스를 차단합니다.
아래와 같이 버킷이 생성된 것을 확인 할 수 있습니다.
IAM 설정
IAM > 사용자 > 사용자 추가
- 정책 추가
GitHub Actions 워크플로우에서 AWS 리소스를 사용하기 위해
AmazonS3FullAccess와 AWSCodeDeployFullAccess 정책을 추가한다.
- Access Key 생성
보안 자격 증명 -> 액세스 키 만들기
위와 같이 설정 해줍니다.
생성된 액세스 키는 csv 파일로 저장해둡니다. 이후에 Github Actions에서 secreats 를 설정해줘야 합니다.
- 역할생성
IAM -> 역할 -> 역할 만들기
1. EC2 역할 생성
CodeDeploy 서비스를 사용하여 EC2 인스턴스에 애플리케이션을 배포하기 위해 AmazonEC2RoleforCodeDeploy 역할을 추가한다.
2. CodeDeploy 역할 생성
자동으로 권한이 추가된다.
- EC2 IAM 역할 수정
사용중인 EC2 인스턴스 접속 후에 작업 -> 보안 -> IAM 역할 수정을 해준다.
설정한 role-ec2-codedeploy로 역할을 수정해준다. (이후에 인스턴스 재부팅 한 번 해야한다.)
CodeDeploy 설정
CodeDeploy-> 배포 -> 애플리케이션 -> 애플리케이션 생성
- 배포그룹 생성
환경 구성의 키 값은 사용중인 인스턴스 값을 사용한다.
Github 설정
- Secrets
github -> settings -> secrets and variables -> Actions
위에 IAM 설정에서 가져온 액세스 키의 정보들을 AWS_ACCESS_KEY_ID 와 AWS_SECRET_ACCESS_KEY에 저장하고, APPLICATION에는 spring boot 프로젝트 내의 application.yml 파일 내용을 넣습니다.
- Github Actions Workflow
Actions에서 새로운 Wokrflow를 생성해준다.
main-deploy.yml
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
name: Deploy to Production
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@master
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Gradle Caching
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Make application.yml
run: |
cd ./src/main
mkdir resources
cd ./resources
touch ./application.yml
echo "${{ secrets.APPLICATION }}" > ./application.yml
shell: bash
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Make zip file
run: |
mkdir deploy
cp ./appspec.yml ./deploy/
cp ./Dockerfile ./deploy/
cp ./scripts/*.sh ./deploy/
cp ./build/libs/*.jar ./deploy/
zip -r -qq -j ./spring-build.zip ./deploy
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
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: Upload to S3
run: |
aws s3 cp \
--region ap-northeast-2 \
./spring-build.zip s3://jeonsg2-bucket
- name: Code Deploy
run: aws deploy create-deployment --application-name spring-deploy
--deployment-config-name CodeDeployDefault.OneAtATime
--deployment-group-name spring-deploy-group
--s3-location bucket=jeonsg2-bucket,bundleType=zip,key=spring-build.zip
EC2 설정
S3에 있는 파일을 담을 app 폴더를 생성한다.
mkdir ~/app
Docker 설치
sudo apt update //우분투 패키지 인덱스 업데이트
sudo apt install docker.io -y //도커 설치
sudo service docker start //도커 시작
sudo systemctl status docker.service //확인
프로젝트 파일 설정
Dockerfile (프로젝트 루트 디렉토리에 넣어주면 된다.)
FROM openjdk:11
WORKDIR /Toy-project
COPY Toy_project-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","app.jar"]
scripts/depoly.sh
#!/bin/bash
echo "> 현재 실행 중인 Docker 컨테이너 pid 확인" >> /home/ubuntu/deploy.log
CURRENT_PID=$(sudo docker container ls -q)
if [ -z $CURRENT_PID ]
then
echo "> 현재 구동중인 Docker 컨테이너가 없으므로 종료하지 않습니다." >> /home/ubuntu/deploy.log
else
echo "> sudo docker stop $CURRENT_PID" # 현재 구동중인 Docker 컨테이너가 있다면 모두 중지
sudo docker stop $CURRENT_PID
sleep 5
fi
cd /home/ubuntu/app
sudo docker build -t imagee:v1.0 .
sudo docker run -d -p 8080:8080 imagee:v1.0
appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/app
overwrite: yes
permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu
hooks:
ApplicationStart:
- location: deploy.sh
timeout: 60
runas: ubuntu
배포 자동화 결과
1. Spring boot 프로젝트에서 GitHub로 push를 하게 되면 GitHub Actions는 push event를 감지하여 자동으로 시작된다.
2. Actions는 빌드 도구 Gradle를 사용하여 Spring boot 애플리케이션을 빌드한다.
3. 빌드가 성공하면 빌드 된 애플리케이션 아티팩트 JAR를 생성한다.
4. Actions는 해당 JAR파일을 S3 버킷에 업로드한다.
5. CodeDeploy는 S3 버킷에서 애플리케이션 아티팩트를 가져와 EC2 인스턴스에 배포한다.
6. 배포가 성공하면 최신 버전의 애플리케이션 EC2 인스턴스에서 실행된다.
위의 순서와 같이 자동 배포화가 이루어집니다.