[UMC 3기] Vibecap

프론트엔드 팀의 요청으로 E2E 테스트를 위해 서버 애플리케이션을 배포했다.
새로운 기능이 추가될때마다 애플리케이션을 업데이트해 프론트엔드에서 API를 호출할수 있게 만들어야 했다. 그래야 프론트와 백엔드의 개발 속도를 맞출 수 있기 때문이다.
내가 맡은 기능도 구현해야 하는데 이런 기계적 반복은 최소화 하고 싶었다.

Before

자동화하기 전에는 배포를 위해 다음과 같은 과정을 밟았다.

  • 로컬에서
    1. 팀원이 push한 코드를 로컬 코드 포인트에 통합
    2. 애플리케이션 빌드
    3. 도커 이미지 생성, 도커 허브에 업로드
  • EC2에서
    1. 실행중이던 도커 컨테이너 중지
    2. 기존의 도커 컨테이너, 이미지 삭제
    3. 도커 허브에서 이미지 다운로드
    4. 도커 컨테이너 생성, 실행

spring profilelocal이나 test로 설정하고 위의 과정을 진행해버렸다면 처음부터 다시 진행해야 했는데 굉장히 짜증났다. 😅

After

완전히 자동화 하지는 못했다. 빌드, 배포 과정을 각각 스크립트로 실행하도록 구현했다.

스크립트를 작성한 이후 빌드&배포 과정은 다음과 같다. 빌드 배포 과정

  • 로컬에서
    1. $ git pull origin dev
    2. $ integrate.py
  • EC2에서
    1. $ deploy.sh

생각해보니 코드를 pull과정을 스크립트에 포함하지 않았는데 이름을 integrate라고 한 건 이상하다.🤔

평가

CI&CD를 구축하면 일반적으로 source control 툴과 연동해서 코드를 push하면 서버 인스턴스에서 지정된 스크립트에 정의된대로 push된 코드가 통합->테스트 실행->결과 통보->빌드->애플리케이션 실행 과정이 진행된다고 한다.
하지만 이번 프로젝트에서 사용한 ec2 인스턴스의 메모리는 1GB이기 때문에 애플리케이션을 빌드하는 것조차 힘들었다. 그래서 로컬에서 빌드하고 서버에서는 도커 컨테이너를 실행하는 방법이 맞는것 같다.

배포 스크립트

integrate.py

#! /usr/bin/env python3
# only for building production application

import subprocess
import os
import sys

# dockerfile path
CONTAINER_DIR = "/Users/mingeun/containers/Vibecap/api-server"
# .jar file
JAR = "Vibecap_Back-0.0.1-SNAPSHOT.jar"
JAR_DIR = "/Users/mingeun/Vibecap/Vibecap_Back/build/libs"

def _Call(cmd, silent=False):
    # return subprocess.call(cmd + " > /dev/null", shell=True)
    return subprocess.call(cmd, shell=True)

def update_app():
    if os.getcwd() != CONTAINER_DIR:
        os.chdir(CONTAINER_DIR)
    if _Call("rm %s" % JAR) < 0:
        pass
    _Call("cp %s/%s ./" % (JAR_DIR, JAR))
    _Call("mytree")

def Main(argv):
    _Call("gradle clean")
    _Call("gradle build -x test")

    os.chdir(CONTAINER_DIR)
    print("current directory : " + os.getcwd())
    update_app()

    _Call("docker image build --no-cache --build-arg BUILDPLATFORM=amd64 -t mingeun2154/vibecap-server:0.0.0 .")

    _Call("docker image push mingeun2154/vibecap-server:0.0.0")

if __name__ == "__main__":
    sys.exit(Main(sys.argv))

deploy.sh

#! /bin/sh

echo "stop and remove docker container..."
docker stop vibecap-server
if [ $? < 0 ]
then
     echo "no container exist"
else
     docker rm vibecap-server
fi

echo "remove dangling images..."
docker image prune

echo "pull docker image from docker hub..."
docker image pull mingeun2154/vibecap-server:0.0.0

docker container run -v /home/ec2-user/vibecap/logs:/app/logs -d --name vibecap-server -p 8080:8080 mingeun2154/vibecap-server:0.0.0

Comments