아키텍처 구조
본 글에서는 SpringBoot와 Vue3 사용한 '날숨' 프로젝트의 자동 빌드, 배포하는 과정을 설명한다. 아래는 필자가 진행한 '날숨' 프로젝트의 아키텍처 구조이다.
Docker를 사용하며, Docker를 개념적으로 두 개의 영역으로 구분했다. 왼쪽은 배포한 웹 애플리케이션이 동작하는 영역이며, 클라이언트 요청에 대해 응답한다. 오른쪽은 그 외 컨테이너들이 있는 영역이다. 각 컨테이너의 역할은 아래와 같다.
- Nginx: Nginx 웹 서버가 동작하는 컨테이너. 리버스 프록시 역할을 수행한다. 빌드된 Vue3의 파일들을 갖고 있어 정적 파일 요청(HTML, JS, CSS)을 처리하며 백엔드 요청을 Spring Boot 컨테이너로 프록시한다.
- Spring Boot : jdk 21이 설치된 컨테이너. 톰캣 서버가 동작하며 백엔드 요청을 처리한다.
- mysql : Mysql 서버가 동작하는 컨테이너
- Jenkins : 젠킨스 서버가 동작하는 컨테이너. 젠킨스를 통해 빌드와 배포를 자동화한다. 빌드 과정 중에 정적 분석 서버인 Sonar Cude에 요청을 넣는다.
- Sonar Cude : 소나 큐브 서버가 동작하는 컨테이너. 소나 큐브는 정적 분석 툴이다. 코드를 보고 코드 버그, 취약점, 코드 스멜 등을 식별한다.
- Portainer : 포테이너가 동작하는 컨테이너. 포테이너는 도커 컨테이너를 관리해주는 툴이다. 도커 환경을 시작적으로 모니터링 할 수 있으며 도커 컨테이너의 쉘에 바로 접근할 수 있다. 매우 편리하기에 사용을 추천한다.
Docker Compose 설치
EC2는 Ubuntu 22.04 (LTS) 버전이며 이미 Docker가 설치되어 있다고 가정한다. 아래는 Docker 설치에 관한 공식 문서이다.
https://docs.docker.com/engine/install/ubuntu/
여러개의 컨테이너를 한번에 생성하기 위해 docker compose를 사용한다. docker compose를 통해 한 번에 여러 개의 컨테이너를 생성, 실행, 폐기할 수 있다. 아래는 docker compose 설치에 관한 공식 문서이다.
https://docs.docker.com/compose/install/linux/
apt 패키지 설치 도구로 docker compose 플러그인을 간편하게 설치할 수 있다. 아래 명령어를 입력한다.
sudo apt-get update
sudo apt-get install docker-compose-plugin
버전을 출력해 docker compose가 잘 설치되었는지 확인한다.
Docker Compose version vN.N.N(N에는 버전 정보가 들어감)
Docker Copose up 수행
우선 필자는 편의를 위해 아래와 같이 EC2의 디렉터리 구조를 만들었다. 홈 디렉터리에서 아래 명령어를 실행했다.
mkdir docker-compose
mkdir docker-compose/volumns
mkdir deploy
mkdir deploy/backend
mkdir deploy/frontend
그리고 아래 docker-compose.yml을 docker-compose 디렉터리에 넣었다. (docker-compose.yml를 자신의 환경에 맟춰서 수정하자)
version: '3.0'
services:
nginx:
networks:
- appnet
ports:
- '80:80'
- '443:443'
image: nginx
springboot:
networks:
- appnet
command: sh -c 'if [ -e /app.jar ]; then java -jar /app.jar --spring.profiles.active=production; else echo "app.jar not found, skipping execution"; fi'
image: openjdk:21
mysql:
ports:
- '3306:3306'
volumes:
- mysql_data:/var/lib/mysql
networks:
- appnet
environment:
MYSQL_ROOT_PASSWORD: adminPassword
MYSQL_DATABASE: databaseName
MYSQL_USER: userName
MYSQL_PASSWORD: userPassword
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
image: mysql:8.0.34
jenkins:
ports:
- '8080:8080'
user: root
networks:
- jenkinsnet
image: jenkins/jenkins:jdk21
sonarqube:
ports:
- '9000:9000'
networks:
- jenkinsnet
image: sonarqube
portainer:
ports:
- '9443:9443'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
image: portainer/portainer-ce:latest
volumes:
mysql_data: {}
portainer_data: {}
networks:
jenkinsnet: {}
appnet: {}
이 후 docker-compose 디렉터리로 이동하여 아래의 명령어를 실행한다. docker-compose.yml에 정의된 컨테이너, 볼륨, 네트워크가 생성된다.
sudo docker compose up -d
또한 아래의 명령어로 생성시킨 컨테이너, 네트워크를 삭제시킬 수 있다. 단 볼륨은 삭제되지 않는다.
sudo docker compose down
배포 쉘 스크립트 생성
젠킨스가 배포 과정 사용할 쉘 스크립트 파일을 생성하자. 젠킨스 컨테이너에 있는 빌드 결과물을 운영 또는 개발 서버가 동작하는 컨테이너로 옮기기 위해 필요하다. 아래의 deploy.sh 파일을 만들어 /deploy/backend 디렉터리에 넣는다.
docker cp docker-compose-jenkins-1:/var/jenkins_home/workspace/pipeline/backend/target/jenkins-0.0.1-SNAPSHOT.jar /home/ubuntu/deploy/backend/app.jar
docker cp /home/ubuntu/deploy/backend/app.jar docker-compose-springboot-1:/
docker restart docker-compose-springboot-1
내용은 간단하다. 젠킨스 컨테이너에 있는 spring boot 앱 빌드 결과물인 jar 파일을 ec2(호스트)로 옮기고, 다시 ec2에서 springboot 컨테이너로 옮긴 후 springboot 컨테이너를 재실행한다.
또, 아래의 deploy.sh 파일을 만들어 /deploy/frontend 디렉터리에 넣는다.
rm -rf /home/ubuntu/deploy/frontend/dist
docker cp docker-compose-jenkins-1:/var/jenkins_home/workspace/pipeline/frontend/dist /home/ubuntu/deploy/frontend/dist
docker exec -it docker-compose-nginx-1 rm -rf /usr/share/nginx/html
docker cp /home/ubuntu/deploy/frontend/dist docker-compose-nginx-1:/usr/share/nginx/html
docker restart docker-compose-nginx-1
이것도 위와 비슷하다. 젠킨스 컨테이너에 있는 vue3 빌드 결과물인 dist 디렉터리를 ec2로 옮기고 다시 ec2에서 nginx 컨테이너로 옮긴 후 nginx 컨테이너를 재실행한다.
'Infra > CI&CD' 카테고리의 다른 글
SpringBoot, Vue3 프로젝트 CI/CD (2) (0) | 2024.01.27 |
---|---|
Django Channels 배포 (0) | 2022.09.12 |