본문 바로가기
프로젝트/낙낙(KnockKnock)

배포 자동화를 해보자-3(Github Actions) (완료)

by 티코딩 2023. 9. 12.

다음편을 바로 썼어야했는데 해결에 너무 급급해 블로깅을 제대로 못했다.

이제 몰아서 다시 써보려고한다.

배포 자동화를 해보자1에 이어서 배포 그룹을 만드는것부터 정리해보려한다.

 

ㅇ 배포그룹 만들기

중요한건 배포 설정에 저걸로 설정하고,

완성되면 저렇게 나온다.

 

저렇게 배포 그룹이 생성되면 git push 를하면 github actions에서

저기내가 설정해둔 단계중 Code Deploy 단계에서 배포그룹으로 배포가 실행된다.

 

이렇게 배포가 실행되고 완료되면

appspec.yml 파일에 설정해둔 작업들이 해당 scripts에 따라 진행된다.

나의 appspec.yml 파일을 파헤쳐보자.

version: 0.0
os: linux
files:
  - source:  /
    destination: /home/ubuntu/action
    overwrite: yes

permissions:
  - object: /
    pattern: "**"
    owner: ubuntu
    group: ubuntu

hooks:
#  ApplicationStop:
#    - location: scripts/empty_script.sh
#      timeout: 3000
#      runas: root
#  DownloadBundle:
#    - location: scripts/empty_script.sh
#      timeout: 3000
#      runas: root
  BeforeInstall:
    - location: scripts/server_clear.sh
      timeout: 3000
      runas: root
#  Install:
#    - location: scripts/empty_script.sh
#      timeout: 3000
#      runas: root
  AfterInstall:
    - location: scripts/initialize.sh
      timeout: 3000
      runas: root
  ApplicationStart:
    - location: scripts/deploy.sh
      timeout: 3000
      runas: root
#  ValidateService:
#    - location: scripts/empty_script.sh
#      timeout: 3000
#      runas: root

주석처리해둔 부분은 넣어도되고 안넣어도 된다. 어차피 location 의 empty_script.sh는 아무것도 없는 빈 스크립트이다.

files의 destination부분을 잘 확인하고 항상 경로를 잘 확인해야한다. 내가 경로설정을 잘못해서 며칠을 날렸다.

그리고 여기서 사용되는 스크립트 파일들을 보자.

스크립트 파일들은 저렇게 예쁘게 모아놨다.

 

ㅇ server_clear.sh

#!/bin/bash

# 이전 배포에서 생성된 파일들을 삭제합니다.
if [ -d "/home/ubuntu/action" ]; then
    rm -rf /home/ubuntu/action
fi
# 이전 배포에서 생성된 도커 컨테이너를 이미지 이름으로 찾아 중지하고 삭제합니다.
CONTAINER_NAME="kkcon"  # 여기에 해당하는 도커 컨테이너이름을 입력하세요.
IMAGE_NAME="kki"
# 도커 컨테이너 중지
if docker ps -a | grep -q $CONTAINER_NAME; then
    docker stop $CONTAINER_NAME
    docker rm $CONTAINER_NAME
    echo "Container $CONTAINER_NAME removed"
else
    echo "Container $CONTAINER_NAME not found, skipping removal"
fi
# 도커 이미지 삭제
if docker images | grep -q $IMAGE_NAME; then
    docker rmi $IMAGE_NAME
    echo "Image $IMAGE_NAME removed"
else
    echo "Image $IMAGE_NAME not found, skipping removal"
fi

Before Install 단계에선 이전에 생성했던 서버를 삭제하고 새롭게 업데이트된 서버를 받아들일 준비를 해야한다.

그래서 컨테이너를 중지시키고, 삭제하고 이미지를 삭제하는 로직을 넣어놨다.

 

ㅇ initialize.sh

#!/bin/bash

# 배포된 파일들에 대해 실행 권한을 추가합니다.
chmod +x /home/ubuntu/action/**

IMAGE_NAME="kki"
# 새로운 이미지를 빌드합니다.
docker build -t $IMAGE_NAME /home/ubuntu/action

이번 단계에선 새로운 이미지를 빌드해야한다.

이전에 이미지 빌드단계가 너무 오래걸렸는데, 빌드가 원래 오래걸리긴하지만 정도를 넘어설 정도로 오래걸렸었는데, 지원님께서 왜그런지 잡아주셨다. 너무 오래걸려서 이미지빌드를 스킵하고 컨테이너만 새롭게 만들고 했었다.

문제의 dockerfile을 보자.

#FROM gradle:7.4-jdk11-alpine as builder
#WORKDIR /build

# 그래들 파일이 변경되었을 때만 새롭게 의존패키지 다운로드 받게함.
#COPY build.gradle settings.gradle /build/
#RUN gradle build -x test --parallel --continue > /dev/null 2>&1 || true

## 빌더 이미지에서 애플리케이션 빌드
#COPY . /build
#RUN gradle build -x test --parallel
#
## 여기서 Gradle 클린 빌드를 추가
#RUN gradle clean build -x test --parallel

# APP
FROM openjdk:11-jdk
WORKDIR /app

# 빌더 이미지에서 jar 파일만 복사
COPY /build/libs/KnockKnock-0.0.1-SNAPSHOT.jar app.jar

EXPOSE 8080

# root 대신 nobody 권한으로 실행
USER nobody
ENTRYPOINT [ \
   "java", \
   "-Dspring.profiles.active=dev",\
   "-Djava.security.egd=file:/dev/./urandom", \
   "-Dsun.net.inetaddr.ttl=0", \
   "-jar", \
   "app.jar" \
]

저기서 빌드를 계속해서 배포가될때마다 쌓였던것같다. 그래서 싹다 주석처리하고 이렇게만 하니 잘 된다.

 

ㅇ Deploy.sh

Application Start 단계에 필요한 스크립트다. 이 파일도 정말 우여곡절이 많았지만, 정말 미니멀하게 바뀌었다. 전에 코드들은 다 주석처리 되어있다.

#!/bin/bash

# 빌드 파일의 이름이 콘텐츠와 다르다면 다음 줄의 .jar 파일 이름을 수정하시기 바랍니다.
#BUILD_JAR=$(ls /home/ubuntu/action/back/KnockKnock/build/libs/KnockKnock-0.0.1-SNAPSHOT.jar)
#JAR_NAME=$(basename $BUILD_JAR)
#LOG_FILE="/home/ubuntu/action/scripts/deploy.log"
#
#echo "> 현재 시간: $(date)" >> "$LOG_FILE"
#echo "> build 파일명: $JAR_NAME" >> "$LOG_FILE"
#
#echo "> build 파일 복사" >> "$LOG_FILE"
#DEPLOY_PATH="/home/ubuntu/action"
#cp $BUILD_JAR $DEPLOY_PATH
#
#echo "> 현재 실행중인 애플리케이션 컨테이너 확인" >> "$LOG_FILE"
#CONTAINER_ID=$(docker ps -q -f name="kkcon")  # Docker 컨테이너 이름을 여기에 입력하세요.
#
#if [ -z "$CONTAINER_ID" ]
#then
# echo "> 현재 실행중인 애플리케이션 컨테이너가 없으므로 종료하지 않습니다."
#else
#  echo "> 컨테이너를 중지시킵니다."
#  docker stop "$CONTAINER_ID"
#  docker rm "$CONTAINER_ID"
#fi

#IMAGE_NAME="kki"
#echo "> DEPLOY_JAR 배포" >> "$LOG_FILE"


docker run -d -p 8080:8080 --env-file /home/ubuntu/app.env --name kkcon kki

남은 코드는 단 두줄뿐이다. 그냥 사실 기본적으로 이미지를 빌드했으니 여기선 컨테이너를 실행만 시켜주면 되는것이었다.

 

이렇게 설정하고 나면 배포가 아주 잘된다. 배포그룹에가서 github actions가 만든 deployment를 보자. 배포아이디를 보고 들어가서 배포 수명 주기 이벤트를 보자.

맨밑에 이벤트에 View events를 눌러보면 내가 설정한 스크립트가 각 단계에 적용되어 명령어가 잘 실행되는걸 볼 수 있다.

처음에 스크립트 문제로 안되서 고생좀 했다..

이걸보는분들은 스크립트를 잘짜야한다. 근데 가끔 오류코드가 Unknown이나오는데 그건 인스턴스 연결해서 codedeploy agent log를 잘 살펴봐야한다. 다들 화이팅!