Jenkins로 Spring Boot 2 + Vue 3 프로젝트를 리눅스 서버에 배포하기 (1)
시작하기에 앞서...
이 글은 내가 만든 도서 관리 앱을 AWS Lightsail에 Jenkins로 자동 배포하는 과정을 정리한 글임을 먼저 밝힌다.
이 글을 정독하기 전에, 먼저 아래의 글을 읽고 AWS Lightsail 인스턴스를 생성하고 PuTTY 사용법에 대해서 알아보는 것을 권장한다. 만약 본인이 이미 VPS를 통해 인스턴스를 생성하고 PuTTY로 원격 접속하는 방법에 대해 알고 있다면 다음 최소사양을 만족하는 가상 서버를 직접 생성하도록 하자.
서버 최소사양
- CPU: 1 Core
- Memory: 512MB
- Disk: 20GB
참고로 이 사양은, AWS Lightsail 에서 제공하는 인스턴스의 최소 사양이다.
배포 과정
나의 프로젝트 배포 과정은 다음과 같다.
- Github에 소스코드를 push 한다.
- Jenkins에서 일정 시간마다 Github 리포지토리를 복제하고 빌드 한다.
- 빌드 된 결과물을 리눅스 서버에 배포한다.
서버 세팅하기
서버 세팅 과정은 다음과 같다.
- 서버 최신화
- Docker 설치
- Nginx 컨테이너 생성
- Postgresql DB 컨테이너 생성
- OpenJDK 설치
서버 최신화
우선 서버의 상태를 최신 상태로 만들어야 한다. 아래의 명령어를 입력해 최신 상태로 갱신하자.
처음 업그레이드 명령어를 사용한다면 아래와 같은 화면이 뜰 수 있는데, 기본으로 선택되어 있는 'keep the local version currently installed'를 선택하자.
Docker 설치
다음은 Docker를 설치하도록 하겠다. 아래의 글을 참조해 Docker를 설치하도록 하자.
Docker 설치가 완료되면 사용자 계정을 docker 그룹에 추가해야 한다. docker 그룹에 추가하지 않더라도 크게 상관은 없지만, docker 명령어를 사용할 때 마다 sudo 명령어를 앞에 붙여줘야 하므로 편의를 위해 그룹에 추가해 주는 것이 좋다. docker 그룹에 계정을 추가하는 방법은 아래의 글을 참고하도록 하자.
Nginx 컨테이너 생성하기
Docker가 설치 되었으니 이제 Vue 3 프로젝트를 배포할 Nginx 컨테이너를 생성해 보겠다.
Nginx 컨테이너를 실행 후, 해당 인스턴스의 공개 IP를 웹 브라우저 주소창에 입력해보자. 아래와 같이 403 Forbidden HTTP Status가 뜨면서 nginx/1.xx.x 가 표시되면 정상적으로 컨테이너가 생성 된 것이다.
이제 Nginx 설정을 변경하겠다. 다음 명령어를 입력하자.
$ docker exec -it webserver /bin/bash
이 명령어를 입력하고 나면 유저 권한이 root로 변경되는데, 해당 컨테이너의 root 권한으로 접속 된 것이다. 설정을 변경하기 위해서는 에디터가 필요하다. 나는 nano 에디터를 사용하기 때문에 nano 패키지를 설치하려고 한다. 본인이 vi나 vim이 더 편하다면 그쪽을 설치해도 무관하다. nginx 기본 이미지는 debian 리눅스를 기반으로 하기 때문에 apt 패키지 관리자를 사용하면 된다.
# apt update
# apt install nano -y
에디터를 설치 했다면 설정 파일을 열도록 하자.
# nano etc/nginx/conf.d/default.conf
파일을 열면 기본적으로 설정되어 있는 내용이 있을 것이다. 모든 내용을 지운 다음 아래의 내용으로 변경하자. <호스트 IP 혹은 도메인>은 해당하는 서버를 가리키는 주소를 적으면 된다. <요청URI>는 Vue 3 프론트엔드에서 Spring Boot 2 백엔드에 API 요청을 할 때 사용하는 URI를 입력해주면 된다. 나 같은 경우에는 백엔드에 요청하는 API URI가 /api이기 때문에 proxy_pass 뒤에 http://apiserver/api로 적어주었다.
# Spring Boot 2로 만든 API Server 업스트림
upstream apiserver {
server 172.17.0.1:8080;
keepalive 100;
}
server {
listen 80;
listen [::]:80;
server_name <호스트 IP 혹은 도메인>;
charset utf-8;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://apiserver/<요청URI>;
}
}
Docker는 호스트의 커널은 공유하지만 네트워크 환경은 공유하지 않는 격리된 환경이다. 그렇기 때문에 127.0.0.1이나 localhost를 호출하면 호스트를 호출하는 게 아니라 컨테이너 자기 자신을 호출하게 된다. Docker는 기본적으로 172.17.0.X IP 대역으로 네트워크를 관리하는데, 이 중 172.17.0.1이 호스트에 부여되는 IP다. 따라서 호스트에서 서비스가 돌아가는 백엔드에 요청을 보내기 위해서는 172.17.0.1을 호출해야 한다.
Postgresql 컨테이너 생성하기
내 Spring Boot 2 프로젝트는 Postgresql 데이터베이스를 사용하기 때문에, Postgresql 컨테이너도 생성할 것이다.
Postgresql 14 이미지를 정상적으로 내려 받았다면 다음의 명령줄을 입력해 Postgresql 컨테이너를 생성한다. 여기서 -e 옵션을 이용해 초기 데이터베이스 사용자 아이디와 패스워드를 지정해 줄 수 있다. USER_NAME과 USER_PASSWORD는 각각 Spring Boot 2 프로젝트에서 datasource를 연결할 때 사용하는 아이디/패스워드 값을 입력해주면 된다.
OpenJDK 설치
Spring Boot 2 프로젝트를 실행하려면 당연히 JRE나 JDK가 필수다. 리눅스 서버에서 지원하는 OpenJDK 버전을 먼저 찾아보도록 하자.
$ apt-cache search openjdk
apt 기본 리포지토리 에서는 많은 버전의 OpenJDK를 지원한다. 이 중에서 나는 openjdk-17-jre를 설치할 것이다.
정리하며
프로젝트 배포를 위해 Docker, OpenJDK를 설치했다. 그리고 Docker로는 프로젝트에서 사용할 Nginx 서버 컨테이너와 Postgresql DB 서버 컨테이너를 생성했다. 다음 글에서는 Jenkins를 이용해 Nginx 서버 컨테이너에 Vue 3 프로젝트를 배포하고 인스턴스에는 직접 Spring Boot 2 프로젝트를 배포하고 자동 실행하는 방법에 대해 다루도록 하겠다.