캡스톤 디자인을 진행하는 와중에 배포 주기를 짧게 만들어 제품을 쌓아 올리는게 좋을것 같다는 의견이 나와 배포 파이프라인을 미리 구축한 후 진행하게 되었습니다.
따라서 초반에 만든 유저 까지의 스프링 서버를 aws ec2에 자동 배포를 하도록 설정 하였습니다.
배포 자동화 구축시 고민
배포 자동화 구축을 하는데에 있어 우선 무엇을 사용할지 고민을 하였는데 우선 CI tool 에서 jenkins, github action, travis ci 에서 고민 하였습니다.
이때 github action을 채택하였는데, 이유는 우선 github에서 제공하기에 다루기에 편리했고 jenkins의 경우 서버를 하나 더 올려야 했기 때문에 금액적으로도 생각을 하여 github action을 채택하였습니다.
배포 아키택쳐의 경우에는 두가지를 고민하였습니다.
1.
2.
이에 2번째 방법을 택하였는데, 그 이유는 첫번쨰 방법은 aws 에 종속되기 때문에 혹시 나중에 다른데에 배포하게 되면 다시만들어야 할지도 모른다는 두려움이 있었고,
2번째의 경우에 docker 를 사용하면 환경 설정의 문제를 쉽게 해결 할 수 있을거라고 생각했기 때문입니다.
이에 맞춰 github action을 위한 workflow 파일을 작성하였습니다.
배포 과정
1. ec2 생성, docker 설치
2. github action 작성
3. 배포 테스팅
1의 ec2 생성과 docker 설치는 따로 정리하지 않겠습니다.
하지만 주의할점
1. ec2 생성후 인바운드 규칙에서 8080 포트와 22 포트를 열어주어야 합니다.
- 8080의 경우는 spring project 에서 사용하고
- 22 포트의 경우는 ssh 접속시 22로 접속하기 때문
2. github action 작성
name: Code deploy
on:
pull_request:
branches: [ "main" ]
types: [ closed ]
jobs:
build:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: make application-oauth.yml
run: |
cd ./src/main/resources
touch ./application-prod.yml
echo "${{ secrets.APPLICATION_PROD }}" > ./application-prod.yml
- name: Setup Gradle
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
- name: Build with Gradle Wrapper
run: ./gradlew build -x test
- name: Docker build
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t app .
docker tag app ${{ secrets.DOCKER_USERNAME }}/maru:latest
docker push ${{ secrets.DOCKER_USERNAME }}/maru:latest
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.AWS_HOST }} # EC2 인스턴스 퍼블릭 DNS
username: ubuntu
key: ${{ secrets.AWS_ACCESS_SECRET_KEY }} # pem 키
# 도커 작업
script: |
docker pull ${{ secrets.DOCKER_USERNAME }}/maru:latest
CONTAINERS=$(docker ps -q)
for CONTAINER in $CONTAINERS; do
docker stop $CONTAINER
done
docker rm $(docker ps -aq)
docker run -d --log-driver=syslog -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod ${{ secrets.DOCKER_USERNAME }}/maru:latest
docker image prune -a -f
하나씩 살펴보자
1.
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- jdk set up
2.
- name: make application-oauth.yml
run: |
cd ./src/main/resources
touch ./application-prod.yml
echo "${{ secrets.APPLICATION_PROD }}" > ./application-prod.yml
.yml 파일 생성이다.
이는 프로젝트에 oauth 설정이 들어가있으므로 이를 .gitignore 에서 빼주고 관리하기 때문에 배포시에 추가해서 배포해야한다.
따라서 git secret 에 application-oauth.yml 파일을 넣어 놓고 그 값을 파일을 만들어 넣어서 넘깁니다.
3.
- name: Docker build
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t app .
docker tag app ${{ secrets.DOCKER_USERNAME }}/maru:latest
docker push ${{ secrets.DOCKER_USERNAME }}/maru:latest
docker hub에 login 한 후 docker image 를 넘깁니다.
4.
- name: Deploy
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.AWS_HOST }} # EC2 인스턴스 퍼블릭 DNS
username: ubuntu
key: ${{ secrets.AWS_ACCESS_SECRET_KEY }} # pem 키
# 도커 작업
script: |
docker pull ${{ secrets.DOCKER_USERNAME }}/maru:latest
CONTAINERS=$(docker ps -q)
for CONTAINER in $CONTAINERS; do
docker stop $CONTAINER
done
docker rm $(docker ps -aq)
docker run -d --log-driver=syslog -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod ${{ secrets.DOCKER_USERNAME }}/maru:latest
docker image prune -a -f
docker hub에서 이미지를 받은 후 이를 실행하는 스크립트를 실행합니다.
위처럼 github action을 작성한 후 main branch에 pull request 를 보낸후 합쳐지면 github action 이 실행되고 배포가 됩니다.
on:
pull_request:
branches: [ "main" ]
types: [ closed ]
이 코드가 pull request가 닫혔을떄 실행하는 의미이다.
뒤의 2편에서는 trouble shooting을 다루겠습니다.
'aws' 카테고리의 다른 글
AWS RDS 접속 (0) | 2024.03.29 |
---|---|
spring boot, github action, docker 를 이용한 배포 자동화 (2) (3) | 2024.03.20 |
aws 리전 (0) | 2022.09.18 |