> Hello World !!!

     

@syaku

spring boot docker jenkins nexus 스프링 부트 자동 테스트 및 배포 환경 구현

스프링 부트 자동 테스트 및 배포 환경 구현

Github: https://github.com/syakuis/syaku-blog

모든글


기술 스팩

macOS (사용중인 운영체제) Gradle 4.x - 그래들 Gitlab (비공개 저장소를 위해 사용) - 깃랩 Jenkins - 젠킨스 CI Nexus Repository - 넥서스 저장소 Docker - 도커

이번 시간은 spring boot 로 개발된 프로그램을 직접 테스트하고 배포하지 않고 주기적으로 테스트와 배포를 자동으로 할 수 있는 환경을 만들 것이다. 전체 배포 흐름은 이렇다.

  • 개발자가 소스를 직접 git 에 올린다 (push)

  • 젠킨스가 이를 주시하고 소스를 테스트하고 빌드한다.

  • 빌드된 소스를 넥서스 저장소에 배포한다. (Maven repository)

  • 젠킨스에서 배포된 패키지를 특정 서버에 ssh 로 접근하여 구동하거나 도커 이미지를 만들어 컨테이너로 프로그램을 구동되게 할 수 있다.

  • 모든 과정이 완료되면 슬랙으로 메세지를 전달한다. 만약 오류가 발생한다면 이 또한 슬랙에 메세지가 전달될 것이다. 슬랙을 통해 개발자는 문제를 즉시 대처할 수 있다.

하지만 도커로 배포하는 과정은 꽤 복잡하고 많은 내용을 다뤄야 하므로 본 포스팅에서 제외한다. 도커용 젠킨스와 넥서스를 설치하고 스프링 부트 프로그램을 테스트 및 빌드하여 넥서스에 배포하는 것까지 설명한다.

웹 개발자라면 다양한 웹서버 환경을 쉽게 구축할 수 있는 도커를 필수로 익혀서 다양한 테스트를 쉽게 할 수 있도록 하는 것이 좋다. 복잡한 기술이 아니라 기본적인 기능만 익히면 충분하고 길게는 일주일만 시간을 들이면 충분하다.

Nexus Repository 구축하기

넥서스 저장소 : https://www.sonatype.com/nexus-repository-oss 도커 : https://www.docker.com 도커 허브 : https://hub.docker.com

Nexus Repository 는 오픈 소스이며 설치형 패키지 저장소 관리자이다. 우리가 흔히 사용하는 https://mvnrepository.com/ 메이븐 저장소를 만들수 있다. 메이븐 저장소 외에도 npm, docker, bower 등 다양한 저장소를 제공한다. 이번 시간에는 스프링 부트 프로그램의 스냅샷을 배포하기 위한 저장소를 만들 것이다.

무료 서비인 https://bintray.com/ 사용할 수 있지만 스냅샷을 지원하지 않아 직접 저장소를 설치해서 사용했다.

도커를 이용해서 저장소를 구축할 것이다. 도커를 설치하고 도커 이미지 허브 사이트에 접속해서 내려받을 이미지를 검색한다.

도커 설치 및 사용법 : http://syaku.tistory.com/367

하지만 이런 작업은 아래의 모두 구성되어 있다.

Docker Compose 를 이용하여 설치하기

https://docs.docker.com/compose/

docker-compose 를 사용하면 docker 의 여러 명령문을 한번에 정의하여 파일로 사용할 수 있어 아주 편리하다.

우선 다른 컨테이너끼리 네트워크를 통할 수 있도록 도커용 네트워크를 생성한다. 생성한 네트워크를 컨테이너에 설정하면 컨테이너 명으로 접근할 수 있게된다.

$ docker network create devops

devops 라는 네트워크를 만들었고 docker-compose 가 실행되고 나서 해당 컨테이너를 실행하고 종료 그리고 실행된 docker-compose 를 아래와 같이 제거할 수 있다.

# 컨테이너 시작과 종료
$ docker-compose start 혹은 stop
# 컨테이너 제거 -v 볼륨 링크 제거
$ docker-componse down -v

이제 넥서스 컨테이너를 생성하는 작업을 시작한다. 넥서스 전용 폴더를 생성한다.

$ mkdir ~/docker
$ mkdir ~/docker/nexus
$ cd ~/docker/nexus
# 넥서스를 구축하기 위한 실행 정의를 작성한다.
$ vi docker-compose.yml

< / > docker-compose.yml

version: '2'

services:
nexus3:
  image: 'sonatype/nexus3:latest'
  container_name: 'nexus3'
  restart: always
  expose:
    - '8081'
  ports:
    - '8081:8081'
  volumes:
    - './nexus-data:/nexus-data'
  environment:
    TZ: "Asia/Seoul"
networks:
default:
  external:
    name: devops

볼륨 nexus-data 폴더만 있으면 언제든지 넥서스의 현재상태를 유지하고 새로운 넥서스를 생성할 수 있다. 작성이 끝났으면 실행한다. -d 옵션은 실행 작업을 백그라운드로 실행하는 명령이다.

$ docker-compose up -d

Nexus 컨테이너가 설치되고 구동될 것이다. http://localhost:8081 로 접근하면 된다. 기본 계정은 admin/ admin123 이다.

Jenkins CI 구축하기

https://jenkins.io/

Docker 허브에서 이미지를 검색하여 사용하면 된다. 젠킨스 공식 저장소인 jenkins 는 더 이상 업데이트되지 않으니 jenkins/jenkins 를 사용해야 한다.

볼륨에 사용될 폴더를 생성하고 권한 오류가 발생할 경우 아래와 같이 폴더 권한을 변경한다.

$ cd ~/docker
$ mkdir jenkins
$ cd jenkins
$ mkdir jenkins_home
$ chmod 777 jenkins_home
$ vi docker-compose.yml

< / > docker-compose.yml

version: '2'

services:
jenkins:
  image: 'jenkins/jenkins:latest'
  container_name: 'jenkins'
  restart: always
  ports:
    - '8100:8080'
    - '50100:50000'
  expose:
    - '8080'
    - '50000'
  volumes:
    - './jenkins_home:/var/jenkins_home'
  environment:
    TZ: "Asia/Seoul"
networks:
default:
  external:
    name: devops

젠킨스 기본 포트는 8080 이지만 추후 사용될 포트와 충돌이 생길수 있어서 8100 로 사용했다. 테스트로 스프링 부트 프로그램을 작업으로 설정하기 때문에 외부에서 접속할 수 있도록 8101 포트와 스프링 부투 프로그램 구동 포트를 8101 포트로 설정했다.

젠킨스에는 기본적으로 openjdk 1.8 이 포함되어 있다.

이제 브라우저에서 http://localhost:8082 로 접속할 수 있다.

젠킨스 관리자 암호를 알려면 도커 컨테이너 젠킨스에 접근하여 해당 파일 (/var/jenkins_home/secrets/initialAdminPassword)을 열어봐야 한다.

$ docker exec -it jenkins /bin/bash
$ cat /var/jenkins_home/secrets/initialAdminPassword

다음 화면 Customize Jenkins 에서 Select plugins to install 을 선택해서 원하는 플러그인을 선택하고 미리 설치되도록 한다.

Gitlab 연동하기

ssh 키를 이용하면 해당 컴퓨터에서 gitlab 을 이용할 수 있도록 인증된다. 특정 사이트에 인증을 허가받을 때 계정과 암호를 사용하는 것은 좋은 방법은 아니다. 중요한 정보이니 그대로 노출되면 문제가 될 수 있으니 ssh 키를 만들어 사용하는 것이 좋다.

# 도커 컨테이너에 접근한다.
$ docker exec -it jenkins /bin/bash

# ssh 키 만들기
$ ssh-keygen -o -t rsa -C "주로 사용하는 메일주소" -b 4096

# 엔터를 눌러 기본 파일명을 사용한다.
Enter file in which to save the key (/var/jenkins_home/.ssh/id_rsa):

# passphrase 를 입력하라는 건데 엔터를 눌러 넘겨도 된다.
# 난 이걸 입력해 놓고 ssh 비공개 키를 등록할때 입력하지 않아 한참 해맷다. 나란놈은 ... 빙의신이지~
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

# 공개키 열기
$ cat id_rsa.pub

ssh-rsa ....... == 메일주소로끝

이제 생성한 ssh 키를 등록한다. 꼭 gitlab 서비스에만 해당하는 방법이 아니라 어느 저장소든 어느 서비스든 이런 방식으로 사용할 수 있다.

gitlab 사이트에 들어가서 로그인 후 https://gitlab.com/profile 접속한다. 왼쪽 메뉴에 SSH 키 메뉴를 클릭하고 Key 항목에 있는 textarea 에 공개키 ssh-rsa ....... == 메일주로로끝 를 복사해서 붙여넣는 다.

다시 도커로 가서 테스트한다. 아래와 같이 환영 메세지가 출력되면 성공한 것이다.

$ ssh -T git@gitlab.com
Welcome to GitLab, @syaku!

# 비공개키 열기
$ cat id_rsa

-----BEGIN OPENSSH PRIVATE KEY-----
... skip ...
-----END OPENSSH PRIVATE KEY-----

jenkins 로 접속해서 Credentials > System > Global credentials (unrestricted) > Add Credentials 들어가서 아래와 같이 입력하고 저장한다.

이어서 gitlab 액세스 토큰을 만들어서 등록한다. 액세스 토큰은 외부에서 gitlab 서비스에 접근을 허용할때 사용할 수 있는 인증방식이다.

gitlab 사이트에 들어가서 로그인 후 https://gitlab.com/profile 접속한다. 왼쪽 메뉴에 액세스 토큰을 클릭하고 적당한 Name 을 입력하고 생성한다. 그럼 상단에 토큰 값이 출력된다 이것을 복사한다. 새로고침하거나 다시 해당 페이지로 돌아올 경우 토큰 값은 사라진다. 다시 볼 수 없으니 주의한다. 하지만 지우고 다시 만들면 된다.

jenkins 로 접속해서 Credentials > System > Global credentials (unrestricted) > Add Credentials 들어가서 아래와 같이 입력하고 저장한다.

그리고Jenkins 관리 > 시스템 설정 > Gitlab 항목에 아래와 같이 설정하고 저장한다.

입력 후 테스트를 실행해서 성공 메세지가 출력되는 지 확인한다.

참고

젠킨스 작업 만들기

스프링 부트로 개발한 프로그램을 테스트하고 빌드하고 배포하고 이런 작업들을 젠킨스에 등록하여 자동으로 주기적으로 작업을 처리하도록 설정한다.

젠킨스 > 왼쪽메뉴 에서 새로운 item 선택하고 아이템 명을 입력 후 Freestyle project 선택한다.

  • GitLab Connection : 이전에 생성한 액세스 토큰 인증을 선택

  • 소크 코드 관리 : git 을 선택

  • Repositories

    • Repository URL : gitlab 에서 프로젝트 ssh 저장소 주소를 복사하여 넣어준다. 대충 이런 경로이다. git@gitlab.com:syakuis/spring-blog.git

    • Credentials : 이전에 생성한 ssh 키를 등록한 값을 선택한다.

  • Branches to build : 어떤 git 브랜치를 젠킨스가 주시할 건지 설정한다. 나는 */develop 를 설정했다. 쉼표로 여러개 입력할 수 있다.

  • Build : Add build step > Execute shell > Command 아래와 같이 입력한다.

    ./gradlew clean build

Gradle 배포 설정 추가

이제 gradle 에 배포 설정을 추가해주면 된다. 하지만 배포 설정은 민감한 부분이 있으니 비공개적으로 기록하기 위해 공용 설정에 하거나 설정된 계정 정보가 공개되지 않도록 주의한다.

나는 공용 설정에 배포 설정을 추가했다. ~/.gradle/init.gradle 파일을 열거나 만든다.

allprojects {
 apply plugin: 'maven-publish'
 
 publishing {
   publications {
       mavenJava(MavenPublication) {
           from components.java
      }
  }
   repositories {
   maven {
 url 'http://localhost:8081/repository/maven-snapshots/'
 credentials {
           username "$username"
           password "$password"
      }
}
  }
}
}

변수 값은 ~/.gradle/gradle.properties 파일을 열거나 만든다.

username=admin
password=admin123

이렇게 하고 gradle task 에서 Tasks > publishing > publishMavenJavaPublicationToMavenRepository 를 실행하면 된다.

이젠 Jenkins 에서 빌드된 패키지 Nexus 에 배포되도록 설정한다.

이전에 했던 젠킨스 작업 만들기에서 빌드 부분에 추가하면 된다. ./gradlew clean build publish

매터모스트 메신저 연동

작업 진행상태를 받기위해 메신저와 연동한다. 슬랙은 인터넷을 찾으면 많은 것 같아 생략했다.

설치 채팅 솔루션 매터 모스트에 연동한다. 매터모스트 관리에서 아래와 같이 설정한다.

먼저 알림을 따로 관리할려면 알림용 채널을 생성한다.

메뉴를 클릭한다.

통합 기능을 클릭한다.

Incoming Webhook 를 선택한다.

적당한 이름으로 작성한다. 저장하면 url 정보가 출력되는 데 복사한다.

다시 젠킨스로 와서 Jenkins > Plugin Manager 에서 Mattermost Notification Plugin 을 설치한다.

그리고 젠킨스 관리 > 시스템 설정 > Global Mattermost Notifier Settings 에서 각각 입력한다.

Endpoint 에 복사했던 url 정보를 넣는 다.

Channel 은 매터모스트의 채널을 입력한다. #devops

Build Server URL 는 젠킨스 url 을 입력한다.

아래의 테스트 버튼을 눌러 테스트하고 저장한다.