GO SIWOO!

AWS EC2를 통한 Spring Boot 프로젝트 배포 자동화, Docker, Nginx Proxy Manager, Jenkins, Github webhook 사용 본문

Develop/Mat.ZIP 배포

AWS EC2를 통한 Spring Boot 프로젝트 배포 자동화, Docker, Nginx Proxy Manager, Jenkins, Github webhook 사용

gosiwoo 2023. 11. 8. 04:05

들어가며

백엔드 개발자 4명이서 힘들게 개발한 맛집 소셜 웹 서비스를 팀원이 배포 하였지만 결제 문제로 인해 배포가 중단되었습니다. 하지만 배포를 담당한 팀원이 다른 일로 인해 배포를 할 수 없는 상황에 있었고, 그런 이유로 제가 해당 프로젝트를 다시 배포해야 하는 상황에 놓였습니다.

 

프로젝트의 Github 주소는 다음과 같고 배포 사이트 접속 주소와 시연 영상은 readme에 있습니다.

LikeLion-team10/Mat-ZIP (github.com)

 

GitHub - LikeLion-team10/Mat-ZIP

Contribute to LikeLion-team10/Mat-ZIP development by creating an account on GitHub.

github.com

AWS EC2

배포 환경은 AWS EC2 프리티어를 사용했습니다. 배포를 위해서는 DB, Nginx, Jenkins를 서버에 띄워야 합니다. DB 서버는 AWS RDS 사용해도 무방하지만 배포만이 목적이었던 저로서는 EC2에 MariaDB Docker 이미지를 가져와 컨테이너를 띄우기로 했습니다.

EC2 인스턴스 유형

프리티어에서 사용할 수 있는 t2.micro 인스턴스를 사용했습니다. 1GB의 적은 메모리 때문에 여러 문제가 발생할 수 있고 해결 방법은 아래에 링크로 첨부해 두었습니다.

스토리지 구성입니다. 프리티어는 최대 30GB의 스토리지를 할당받을 수 있기에 최대한으로 설정했습니다.

보안 그룹은 인바운드 규칙만을 설정해 주었으며 Nginx Proxy Manager, Jenkins, Spring Boot 프로젝트, HTTP, HTTPS등을 위해 인바운드 규칙을 설정해 주었으며 ssh 접속을 하기 위한 포트와 MariaDB를 위한 포트는 제 local IP만을 허용했습니다. 추가로 AWS의 탄력적 IP를 발급받아 IP주소를 고정해 주었습니다.

 

서버 접속은 putty를 사용해 Auth 개인 ppk 키를 발급받고 넣어 접속했습니다.

EC2 서버 접속 후

EC2 서버 접속 후 해야 할 일의 순서는 다음과 같습니다.

  1. yum 또는 apt(apt-get) 업데이트, 도커 설치, MariaDB 설치(컨테이너), git 설치(컨테이너)
  2. 프로젝트에 알맞은 Java 버전 다운 및 JAVA_HOME, PATH 변수 설정
  3. 프로젝트 git clone, DB 설정과 생성
  4. 프로젝트 빌드 테스트
  5. 프로젝트 Docker 이미지 생성 및 실행
  6. 도메인 구매 및 적용
  7. Nginx Proxy Manager 설치
  8. Jenkins 설치
  9. Github webhook설정

1. yum 또는 apt(apt-get) 업데이트, 도커 설치, MariaDB 설치, git 설치

많이 단축하기는 했지만 위처럼 많은 과정을 거쳐 배포를 완료하였습니다. 

 

1-1.  yum 패키지 업데이트

  • centOS는 yum, ubuntu는 apt(apt-get)을 사용하면 됩니다.
$ yum install epel-release -y
$ yum update -y

1-2.  Docker, 도커 설치

# 혹시 모르니 기존의 오래된 도커를 삭제하는 명령을 수행
$ yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine

# Set up the repository
$ yum install -y yum-utils

$ yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
    
# Install Docker Engine
$ yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 도커 시작
$ systemctl start docker

# 도커 활성화
$ systemctl enable docker

# 도커 작동 테스트
$ docker run hello-world

1-3. MariaDB 설치

  • 보안 설정까지 완료 후 마스터 계정을 생성 및 DB를 생성합니다.(필수)
  • 마스터 계정은 계정의 아이디와 비밀번호만 안다면 접속이 가능하도록 권한을 줍니다.
  • DB를 생성하지 않으면 프로젝트의 빌드가 실패합니다.
# 컨테이너 실행
docker run \
  --name '컨테이너 이름'\ #컨테이너 이름 부여
  -d \ #백그라운드 실행
  --restart unless-stopped \ #컨테이너 중단시 자동 시작
  -e MARIADB_ROOT_PASSWORD='패스워드' \ #MariaDB의 root_password 설정
  -e TZ=Asia/Seoul \ #컨테이너 타임존 설정
  -p 3306:3306 \ #호스트포트:컨테이너포트 매핑 (변경 가능)
  -v /docker_projects/mariadb_1/conf.d:/etc/mysql/conf.d \ #MariaDB 설정파일 서버에 마운트
  -v /docker_projects/mariadb_1/mysql:/var/lib/mysql \ #MariaDB 데이터 서버에 마운트
  -v /docker_projects/mariadb_1/run/mysqld:/run/mysqld/ \ #MariaDB 실행파일, 소켓 파일 마운트
  mariadb:latest #실행할 컨테이너 이미지(최신 버전)
  
# 보안 설정
docker exec -it mariadb_1 /usr/bin/mariadb-secure-installation
##Enter current password for root (enter for none):
##root 계정 패스워드 입력
##Switch to unix_socket authentication [Y/n] n
##Change the root password? [Y/n] n
##나머지 Y

1-4. git을 설치

$ yum install git -y

2. 프로젝트에 알맞은 Java 버전 다운 및 JAVA_HOME, PATH 변수 설정

해당 프로젝트는 Spring boot 3.0버전을 사용함에 따라 Java 17버전을 사용하였으므로 다음과 같이 Java 17을 설치하고 환경변수 설정을 해주어야 합니다.

2-1. /tmp 디렉터리로 이동해 jdk-17을 다운로드

$ cd /tmp
# EC2의 상태에 따라
## Linux 64-bit
$ wget https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-x64_bin.tar.gz
## Linux ARM64
$ wget https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-aarch64_bin.tar.gz

2-2. 다운받은 jdk-17을 tar 명령어를 통해 압축을 풀고 이동

$ tar -xvf openjdk-17.0.2_linux-x64_bin.tar.gz
$ mv jdk-17.0.2/ /opt/jdk-17/

2-3. 프로파일에 JAVA_HOME 변수와 PATH를 설정

$ vi ~/.bashrc

#파일 내
export JAVA_HOME=/opt/jdk-17 # 추가
export PATH=$JAVA_HOME/bin:$PATH # 추가

2-4. 수정된 프로파일을 시스템에 반영 및 jdk 설치 확인

  • Java의 버전이 올바르게 출력된다면 성공입니다.
$ source ~/.bashrc
$ java -version

3. 프로젝트 git clone

git을 통해 관리되고 있는 프로젝트를 가져오는 단계입니다. 해당 단계에서는 git clone을 직접하여 서버 내에서 성공적으로 프로젝트가 실행되는지 확인만을 하는 단계입니다. 빌드 과정에서의 에러, 프로젝트 설정등을 테스트하는 과정이라고 보시면 될 듯 합니다.

3-1. 프로젝트가 관리 될 폴더 생성 및 이동

  • 다른 폴더구조를 가져가고 싶다면 변경이 가능합니다.
$ mkdir -p /docker_projects/'프로젝트 이름'/project
$ cd /docker_projects/'프로젝트 이름'/project

3-2. git clone 명령어로 프로젝트 가져오기

  • 명령어 끝의 .을 빠뜨리지 않아야 현재 디렉토리에서 작업을 진행할 수 있습니다.
$ git clone 'clone할 github 주소' .

3-3. 배포를 원하는 브랜치로 이동

$ git checkout '배포할 브랜치'

3-4. Spring boot의 경우 설정 파일의 수정

    • 로컬 개발 환경과 배포 환경은 다르기에 application.yml 또는 application.properties 수정합니다.
    • 또는 배포되지 않은 .gitignore 파일에 들어있는 민감한 정보의 파일을 추가합니다.
    • 저는 application-prod.yml 파일 사전에 정보를 만들어 두고 민감한 정보는 Jenkins 파이프라인을 통해 생성해 주었습니다.

4. 프로젝트 빌드 테스트

git clone 명령어를 통해 받은 프로젝트를 빌드하는 단계입니다. 배포를 처음하시는 분들은 처음하는 해당 단계에서 로컬 개발 환경과의 차이 때문에 많은 문제가 발생할 거라 생각됩니다. 제가 그랬습니다...

제가 마주한 문제는 DB 접근 권한 문제, 설정 파일DB 접근 문제(Docker로 인한 문제), AWS EC2 프리티어의 메모리 부족 이었습니다. 아래 링크는 제가 프리티어 메모리 부족 문제를 스왑 메모리로 해결했던 방법입니다.

AWS EC2 프리티어, 메모리 부족 문제 (tistory.com)

 

AWS EC2 프리티어, 메모리 부족 문제

메모리 부족 AWS 프리티어를 사용해 배포를 하던 중 문제가 발생했습니다. 처절한 ctrl + c의 흔적들... 위와 같이 Spring boot 기반의 프로젝트를 Clone한 뒤 jar 파일 생성 과정에서 실패를 한 것을 보실

gosiwoo.tistory.com

4-1. gradlew 권한 설정

  • 프로젝트 필드에 필요한 명령 gradlew를 소유자가 실행 가능한 상태로 변경하는 과정입니다.
$ cd /docker_projects/'프로젝트 이름'/project
$ ls -alh | fgrep gradlew
$ chmod 744 gradlew
$ ls -alh | fgrep gradlew

4-2. 프로젝트 빌드

  • ssh 접속한 계정이 root가 아닐경우 gradlew은 744로 설정되었기에 sudo 를 붙여줘야 합니다.
  • 추가로 sudo를 설정할 경우 -E라는 옵션을 주어 JAVA_HOME, PATH 환경변수를 그대로 사용하여야 합니다.
$ ./gradlew clean build
$ sudo -E ./gradlew clean build #ssh 로그인 계정이 root 계정이 아닐 경우

4-3. 프로젝트 실행

  • active를 prod로 나누지 않았다면 기존 local로 실행하시면 됩니다.
  • 하지만 개발 환경과 배포 환경을 나누어 주는 것을 권장드립니다.
$ java -jar -Dspring.profiles.active=prod build/libs/'프로젝트 build jar 파일'

4-4. 프로젝트 접속

  • 시작한 프로젝트의 port 번호와 EC2 탄력적 IP를 기반으로 프로젝트에 접속합니다. (ex. IP:PORT)
  • local 개발 환경과 같이 작동에 문제가 없다면 다음으로 넘어가시면 됩니다 :)

5. 프로젝트 Docker 이미지 생성 및 실행

프로젝트가 EC2 서버에서 원활한 실행이 완료되었으면 도커파일을 생성해 이미지를 만들고 실행하면 완료됩니다.

저의 경우에는 프로젝트 내부에 Dockerfile을 만든 후 push하여 git clone 후 추가적인 작업을 하지 않도록 하였습니다.

후에 멀티 스테이지 빌드 과정을 수행했기에 Dockerfile의 정보가 바뀔 예정입니다.

 

5-1. Dockerfile 생성

FROM openjdk:17-jdk-alpine
ARG JAR_FILE=build/libs/'프로젝트 build jar 파일'
COPY ${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/app.jar"]

Dockerfile입니다. 해당 파일은 프로젝트의 루트 경로에 위치하여 Dockerfile이라는 이름으로 저장해야 합니다.

각 항목을 설명드리면 다음과 같습니다.

  • FROM openjdk:17-jdk-alpine 
    • 베이스 이미지로 사용할 Docker 이미지를 지정합니다.
    • 여기서는 OpenJDK 기반의 Alpine Linux 이미지를 사용합니다.
    • Alpine 버전은 20MB의 가벼운 버전입니다.
  • ARG JAR_FILE=build/libs/'프로젝트 build jar 파일'
    • Docker 빌드 중 사용할 빌드 아티팩트 jar 파일의 경로를 지정합니다.
  • COPY ${JAR_FILE} app.jar
    • 빌드된 JAR 파일을 Docker 이미지 내부로 복사해 Docker 컨테이너 내에서 app.jar라는 이름으로 실행됩니다.
  • EXPOSE 8080
    • 실행되고 있는 Docker 컨테이너가 외부에 노출할 포트 번호를 설정합니다.
  • ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/app.jar"]
    • 컨테이너가 시작될 때 실행할 명령을 정의합니다.
    • 앞서 Docker 없이 하는 빌드 테스트에서 실행하는 명령어와 같습니다, 바뀐 부분은 app.jar입니다.

5-2. 기존의 이미지 제거 후 이미지 생성

  • 혹시 모를 기존의 이미지를 제거하고 다시 생성합니다.
# 기존 컨테이너 중지 & 삭제, 이미지 삭제
$ docker stop prject_1 # 컨테이너 중지
$ docker rm -f project_1 # 컨테이너 삭제
$ docker rmi -f project # 이미지 삭제

# 이미지 생성
$ docker build -t project .

5-3. 프로젝트 이미지 실행

  • 각 옵션들의 설명은 주석에 있습니다 :)
$ docker run \ # Docker 컨테이너 실행 위한 명령
  	--name=project_1 \ # 해당 컨테이너에 project_1이라는 이름 지정
  	--restart unless-stopped \ # 중지시 사용자의 개입없이 재시작
  	-p 80:8080 \ # 호스트 80 포트로 들어올 시 컨테이너 8080에 매핑
  	-e TZ=Asia/Seoul \ # 컨테이너의 환경변수 TZ를 설정합니다 (시간대 설정)
 	 -d \ # 컨테이너 백그라운드 실행
 	 project # 실행할 Docker의 이미지의 이름 또는 ID

5-4. 프로젝트 접속

  • EC2 보안그룹의 80포트 설정이 접근 가능하다면 탄력적 IP만으로 컨테이너에 올라간 프로젝트에 접속이 가능합니다.

현재 접속 요청 흐름

현재의 접속 요청 흐름은 위와 같습니다.

아직 해야 할 사항이 많습니다. 도메인 주소 설정, Nginx Proxy Manager, Jenkins 등등 많이 남아 있습니다.

6. 도메인 구매 및 적용

도메인은 iwantmyname에서 구매를 하고 dnszi에 관리 관한을 위임해서 사용했습니다. 가비아 등등 여러가지 도메인 관리 서비스를 하는 업체로 변경해서 위임하셔도 무관합니다.

위임하는 방법은 구매한 도메인의 네임 서버를 바꾸면 관리가 위임됩니다.

# iwantmyname
1차 네임서버 : ns1.iwantmyname.com
	      123.12.123.12
               
# dnszi
1차 네임서버 : ns1.dnszi.com
	      123.12.123.12

위처럼 총 5개의 네임서버를 바꾸어 주면 됩니다. 사용할 도메인은 matzip.site 입니다.

 

또한 dnszi에서 도메인에 IP를 부여하는 과정이 필요합니다.

도메인이 어디의 IP를 가르키도록 하는지 설정하는 과정입니다.

호스트 IP관리(A레코드)

dnszi의 A레코드로 들어가서 

사용할 도메인의 A레코드를 추가해주면 마무리 됩니다.

도메인 A레코드 적용은 10분정도 기다려야 합니다. nslookup 명령을 통해 적용을 확인하시면 됩니다.

7. Nginx Proxy Manager 설치

Nginx Proxy Manager는 자동으로 무료 SSL 인증서를 갱신해 줍니다. 또한 Nginx 에서 사용이 가능한 기능을 GUI로 손쉽게 웹 서버를 운영하게 도와줍니다.

 

제가 Nginx Proxy Manager를 사용한 이유는 HTTP(80 포트) 요청을 강제로 HTTPS(443 포트)로 리다이렉트, 무료 SSL 인증서, 도메인 라우팅을 손쉽게 하기 위해서 사용했습니다. 한마디로 외부에서 오는 모든 요청을 Nginx에서 처리하기 위해 사용했습니다. (프록시 기능)

 

다음은 설치 및 적용 과정입니다.

 

7-1. 기존 프로젝트 Docker 컨테이너를 삭제

  • 기존 프로젝트가 서버의 80 포트를 선점하고 있기에 컨테이너를 삭제합니다.
$ docker rm -f project_1

7-2. Nginx Proxy Manager Docker 이미지를 관리할 디렉터리를 생성

$ mkdir -p /docker_projects/nginx_proxy_manager_1
$ cd /docker_projects/nginx_proxy_manager_1

7-3. 해당 디렉터리에서 docker-compose.yml을 생성

version: "3"
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80' # Public HTTP Port
      - '443:443' # Public HTTPS Port
      - '81:81' # Admin Web Port
    environment:
      TZ: "Asia/Seoul"
      DB_MYSQL_HOST: "172.17.0.1"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: 'DB username'
      DB_MYSQL_PASSWORD: "DB password"
      DB_MYSQL_NAME: "Nginx용 DB"
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

7-4. MariaDB의 'Nginx용 DB' 생성

$ docker exec -it mariadb_1 mariadb -u root -p'password'
$ CREATE DATABASE 'Nginx용 DB';
$ exit

7-5. docker-compose.yml을 통해 실행

$ docker compose up -d

7-6. '도메인:81'로 가서 Nginx Proxy Manager 확인

Nginx Proxy Manager

Nginx Proxy Manager 초기 화면입니다.

처음 제공되는 admin Email과 Password는 다음과 같습니다. 반드시 초기 접속 후 바꿔주시면 좋겠습니다 :)

  • Email: admin@example.com
  • Password: changeme

우측 상단의 Edit DetailsChange Password를 통해 변경해주시면 되겠습니다.

 

7-7. Proxy Hosts에서 도메인으로 오는 요청을 Docker 컨테이너 게이트웨이로 라우팅

 

Docker 게이트웨이로 라우팅

172.17.0.1은 Docker 컨테이너 내부에서 사용되는 가상 네트워크의 게이트웨이 주소입니다.

모든 서비스가 Docker 컨테이너로 띄워져 있는 상태이기에 게이트웨이로 보내면 요청 포트 번호에 따라 MariaDB는 172.17.0.2, Spring Boot 프로젝트는 172.17.0.3으로 게이트웨이가 보내줍니다.

 

7-8. SSL 인증서 추가

SSL 인증서

SSL 인증서를 추가해 443 포트 요청, HTTPS 요청을 처리할 수 있도록 합니다.

추가한 SSL 인증서는 SSL Certificates 탭에서 만료시간을 확인하여 갱신 해주셔야 합니다. 갱신주기는 90일이며 만료 30일 전부터 갱신 가능합니다.

 

갱신을 만료일 전까지 해주지 않으면 DB를 날려먹거나 여러가지 문제가 발생할 수 있기에 미리미리 해주셔야 하지만 crontab 명령어를 통해 주기적으로 자동 갱신하는 방법 또한 있습니다.

 

7-9. 기존 Docker 이미지 제거 및 8080:8080으로 재실행

# 기존 프로젝트 이미지 제거
$ docker rm -f project_1
$ docker rmi -f project

# gradlew를 소유자 실행 가능한 상태로 변경 (이전에 했던 작업)
$ cd /docker_projects/'프로젝트 이름'/project
$ ls -alh | fgrep gradlew
$ chmod 744 gradlew
$ ls -alh | fgrep gradlew

# 빌드 (둘 중 하나 선택)
$ ./gradlew clean build
$ sudo -E ./gradlew clean build

# project 이미지 생성
$ cd /docker_projects/'프로젝트 이름'/project
$ docker build -t project .

# 이미지 실행 
$ docker run \
  --name=project_1 \
  --restart unless-stopped \
  -p 8080:8080 \ # Nginx로8080 라우팅을 해주었기에 80:8080에서 변경됨
  -e TZ=Asia/Seoul \
  -d \
  project

7-10. 프로젝트 실행 확인 (도메인 만으로 접속)

도메인으로 접속이 완료되었고 자물쇠 SSL 인증서까지 확인까지 할 수 있습니다.

추가적으로 하시면 좋은 작업은 Nginx Proxy Manager를 포트 번호, 81로 접근하는게 아닌 도메인 라우팅 하는 작업도 해주시면 좋습니다.

8. Jenkins 설치

거의 다 왔습니다. 현재 배포 상황은 git clone을 통해 받아온 프로젝트를 docker에 띄으고 nginx를 통해 80 포트로 라우팅을 시켰으며 SSL 인증서, 도메인 등등을 모두 완료했습니다. 현재 배포된 프로젝트는 배포하는 브랜치에 변경이 있을 경우 clone을 다시 하고 Spring Boot 프로젝트의 이미지를 다시 만들고 컨테이너에 올려야 합니다. 남은 작업은 배포 자동화 입니다. 배포 자동화는 Jenkins와 Github webhook를 통해 진행되며 Jenkins 또한 같은 EC2 서버에 Docker로 띄울 예정입니다.

 

8-1. 젠킨스 설치

  • 앞서 Docker run 작업과 같이 이미 Jenkins가 띄워져 있다면 제거해 주시면 되겠습니다 :)
  • '-v /var/run/docker.sock:/var/run/docker.sock'는 Docker in Docker를 Docker 바깥에서 작업할 수 있도록 합니다.
$ docker run \
  --name jenkins_1 \
  -p 8081:8080 \
  -e TZ=Asia/Seoul \
  -v /docker_projects/jenkins_1/var/jenkins_home:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /docker_projects/jenkins_1/data:/data \
  -u root \
  -d \
  --restart unless-stopped \
  jenkins/jenkins:jdk17

8-2. Nginx Proxy Manger로 Jenkins, proxy 처리

  • 7-10 끝에 Nginx Proxy Manager도 도메인을 통해 들어갈 수 있게 라우팅을 해줬듯이 Jenkins도 해줍니다.

8-3. Jenkins 초기 비밀번호 확인 후 로그인

$ docker exec jenkins_1 cat /var/jenkins_home/secrets/initialAdminPassword

Jenkins 시작 가이드 (ncloud-docs.com)

 

Jenkins 시작 가이드

 

guide.ncloud-docs.com

Jenkins GUI에 들어간 후 초기 계정 설정은 위의 NCP 가이드를 따라주시면 됩니다.

주의 할 점은 instance Configuration 설정에 Jenkins URL 부분을 Nginx에서 proxy 처리한 jenkins 접속 도메인으로 설정해 주시면 됩니다.

 

8-4. 로그인 완료 후 화면

  • 8-3의 모든 설정이 끝나면 위와 같은 GUI를 보실 수 있습니다.
  • 새로운 프로젝트를 만들고 싶다면 위 이미지의 새로운 Item -> Pipeline을 선택 후 파이프라인 프로젝트를 생성하시면 됩니다.

Jenkins 메인화면

 

8-5. Pipeline 테스트

  • 간단한 Pipeline 테스트입니다. 안하고 넘어가셔도 무방합니다.
pipeline {
    agent any

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url: 'Github Repository 주소'
            }
        }
    }

8-6. 배포 자동화 Pipeline 작성

  • 실제 배포 환경에 사용할 Pipeline입니다.

Pipeline (1)

좌측 메뉴의 구성 부분으로 들어가신 후 하단의 Pipeline을 작성하시면 됩니다.

Pipeline(2)

해당 파이프 라인에서 Spring Boot 프로젝트의 민감한

설정 정보또한 입력이 가능합니다.

Pipeline (3)

9. Github webhook설정

마지막입니다!!!

Github 에서 배포 repository의 모든 Event(trigger), 즉 push가 발생할 경우 해당 URL로 요청을 보냅니다.

 

9-1. Github webhook 설정

Github WebHooks (1)
Github WebHooks (2)

Payload URL에 https://'Jenkins Nginx 라우팅 주소'/github-webhook'/ 을 입력합니다. 아래의 trigger가 발생하면 해당 주소로 Event 발생을 알립니다. 저는 push 상태에서만 Event를 실행시킬 예정이므로 기본값인 just the push event.를 선택하고 Add webhook 버튼으로 마무리 했습니다.

 

9-2. Jenkins, Github hook trigger 설정

Jenkins trigger 설정

Pipeline을 작성한 곳 바로 위 Gtihub hook trigger for GITScm poling 버튼을 눌러 활성화 해 줍니다.

 

9-3. jenkins_1 도커 환경에서 도커를 설치, HOST OS의 도커 명령어 사용 가능하도록 하기 위해 설치

  • jenkins_1 안에서의 Docker와 HOST OS 에서의 Docker가 동기화되어 같은 Docker 환경을 공유합니다.
  • 해당 작업을 하는 이유는 jenkins 내에서 Docker 호스트의 다른  컨테이너에 접근을 해야하기 때문입니다.
  • 예로 Spring Boot 컨테이너를 중지/삭제하고 다시 시작하기 위해서는 HOST OS상의 Docker에서 작업이 가능하기 때문입니다.
  • 8-1 작업에서 Docker 소켓 설정을 HOST OS의 도커 소켓을 가르키고 있기에 가능한 것입니다.
# 젠킨스(jenkins_1) 접속
$ docker exec -it jenkins_1 bash

# jnkins_1 내 도커 설치
$ apt-get update -y
$ apt-get install -y ca-certificates curl gnupg lsb-release
$ mkdir -p /etc/apt/keyrings
$ rm /etc/apt/keyrings/docker.gpg
$ curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
	(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
$ apt-get update
$ apt-get install -y docker-ce docker-ce-cli docker-compose-plugin
$ exit

# apt-get update -y: 패키지 목록을 업데이트합니다.
# apt-get install -y ca-certificates curl gnupg lsb-release: 필요한 패키지들을 설치합니다.
# mkdir -p /etc/apt/keyrings: Docker의 GPG 키를 저장할 디렉토리를 생성합니다.
# rm /etc/apt/keyrings/docker.gpg: 기존의 Docker GPG 키를 제거합니다.
# curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg: Docker의 GPG 키를 다운로드하고 /etc/apt/keyrings/docker.gpg 파일에 저장합니다.
# echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian (lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null: Docker 패키지 저장소 정보를 /etc/apt/sources.list.d/docker.list 파일에 추가합니다.
# apt-get update: 패키지 목록을 다시 업데이트합니다.
# apt-get install -y docker-ce docker-ce-cli docker-compose-plugin: Docker와 관련 도구들을 설치합니다.
# exit: 현재의 쉘 세션을 종료합니다.

 

9-4. jenkins_1 내 도커 설치 확인

$ docker exec -it jenkins_1 bash
$ docker
$ docker compose

# 도커 관련 명령어들이 도커 호스트 기준에서 실행되는지 확인 
$ docker images

# 도커 관련 명령어들이 도커 호스트 기준에서 실행되는지 확인 
$ docker ps

$ exit

 

마치며

배포 자동화가 끝났습니다. 해당 포스팅에 적지 못한 과정이 있는데 Docker Multi-Stage 빌드로 바꾸었습니다. 해당 Dockerfile은 처음 포스팅의 Github Repository의 Dockerfile에 있습니다. Multi-Stage 빌드는 간단하게 따로 포스팅을 진행하도록 하겠습니다. 그리고 추가적으로 할 수 있는 작업으로는 Github Actions와 SonarQube로 수행하는 정적 분석을 Jenkins Pipeline 과정에 추가하면 좋을 듯 합니다. (저는 부족해서 거기까지는 아직 안 될 듯 합니다. 해당 과정중에 빠진 정보나 궁금한 것은 질문주시면 제가 아는 한에선 언제든 답해드리겠습니다. 감사합니다 :)