최근에 개발부터 배포까지의 과정이 너무 귀찮고 버전 관리가 원활하게 이루어지지 않아 CI/CD 과정을 간단하게 구현하였다.
구현하면서 구현 방법이나 간단하게나마 CI/CD가 이루어지는 과정에 대해 이야기해보려고 한다.
Environment
OS 운영체제 | Ubuntu 18.04.6 LTS |
Docker | 20.10.12 |
Docker API | 1.41 |
Docker Compose | 1.26.2 |
Docker Compose Python | 3.7.7 |
Jenkins | 2.332.3 |
필자가 구현한 CI/CD 과정을 간단하게 설명하자면 아래와 같다.
환경 : 우분투 서버 / Docker / Bitbucket(git과 동일하다.) / SpringBoot ( Gradle )
CI/CD Process
사전 작업
- Jenkins 서버 설치
- Jenkins 서버를 Docker를 이용해 간단하게 서버에 올린다.
- docker-compose를 이용해 Jenkins이미지를 가져와서 간단하게 컨테이너를 올린다.
- ssh-keygen Tool를 이용해 RSA알고리즘 SSH Key ( public, private ) 2가지를 생성한다.
- Bitbucket에서 Jenkins 쪽으로 Webhook 요청을 할 수 있도록 AccessKey ( ssh PublicKey )를 설정해준다.
- Bitbucket -> Jenkins SSH protocol Webhook 설정
- Bitbucket (Git)에서 특정 브런치로 Push Event가 발생하게 되면 Jenkins 서버로 SSH Protocol를 이용해 새로운 Push가 있다고 알리는 Webhook을 설정한다.
- Jenkins 서버에서 Git 소스를 가져와 Gradlew 툴로 재 빌드 작업.
- Jenkins 서버에서 Docker.sock을 이용해 빌드된 Jar 파일을 image화 시키고 Run 부팅시키기.
위의 순서는 사전작업이면서 CI/CD를 구성하는 전체 순서이기도 한다. 1~6까지 천천히 설명하고자 한다.
진행 절차
- Jenkins Server
- SSH Keygen
- WebHook
- Jenkins Gradle Build
- Dockerfile, Docker Compose
Jenkins Server
젠킨스 서버를 Docker Container로 올려서 사용하고자 한다.
Docker run 명령어로 젠킨스 이미지를 실행할 수 있지만 Docker Compose를 이용해 실행하고자 한다.
Docker Compose가 설치되어있지 않다면 아래의 명령어로 설치해준다.
[root@0f157633fbbc ~ ] apt-get update
[root@0f157633fbbc ~ ] apt-get install docker-compose
docker-compose.yml은 아래와 같다.
version: '3.1' # Docker Compose 버전
services: # service 정의
dike-jenkins: # dike-jenkins 서비스
image: jenkins/jenkins:lts # 사용할 이미지
container_name: dike-jenkins # 컨테이너 이름
ports:
- "12345:8080" # 외부 포트와 내부 포트 EXPOSE는 내부에 노출할 포트
privileged: true # privileged 설정
volumes:
- /var/run/docker.sock:/var/run/docker.sock # dike-jenkins 컨테이너에서 Host Docker 사용
- /dike-jenkins:/var/jenkins_home # 볼륨 마운트
user: root # 사용자 계정 root 사용
environment:
- TZ="Asia/Seoul" # 타임 존 설정
networks:
- dike # docker 네트워크 설정
networks:
dike:
driver: bridge # 브릿지 네트워크 정의
docker-compose.yml이 있는 경로에서 아래의 명령어로 jenkins서버를 실행한다.
[root@0f157633fbbc ~ ] docker-compose up -d
jenkins install 설치법은 따로 설명하지 않는다.
SSH Keygen
jenkins 서버 안에서 ssh-keygen을 이용해 SSH키를 생성한다.
[root@0f157633fbbc ~ ] ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/redjuns/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/redjuns/.ssh/id_rsa.
Your public key has been saved in /home/redjuns/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:hjbXN0Bbx6t+RWKf/u6fFrupg3gyk3BsXKqKLfHAV1g brandon@mac1
The key's randomart image is:
+---[RSA 2048]----+
| . ... |
| E . o .. |
| o o . |
| . o . o + .|
| . = S + oo +.|
| + o = * ... oo|
| = = o.. ..o|
| .o. . * o...+o|
| ..o. = o+*O|
+----[SHA256]-----+
/home/redjuns/.ssh/ 경로에 'id_rsa.pub', 'id_rsa' 두 개의 key가 생성된다.
pub은 PublicKey이다.
WebHook
GitHub, BigBucket 설정창에 아래의 URL로 Webhook을 설정해준다 WebHook 설정법은 따로 찾아보길 바란다.
http://jenkins-host:12345/bitbucket-hook/
Jenkins Gradle Build
Jenkins 부분은 설정해주어야 하는 것이 많다.
- SSH private Key 설정
- Gradle Version 설정
- Item (파이프라인) 설정
- 소스 코드 관리 Git 설정
- 빌드 Event 설정 (빌드 유발 설정)
- Build 설정
SSH Private Key 설정
Jenkins 대시보드에 접속하여 'Dashboard > Jenkins 관리 > Manage Credentials'에서 SSH private Key를 추가한다.
Gradle Version 설정
Jenkins 대시보드에 접속하여 'Dashboard > Jenkins 관리 > Global Tool Configuration'에서
Item 설정 (파이프라인)
Dashboard에서 새로운 Item을 만들어 준다.
Item 유형은 Freestyle project를 선택한다.
소스 코드 관리
소스 코드 관리 탭에선 git소스 Clone 주소(SSH)를 적어준다.
Credentials는 위에서 추가한 SSH private Key이다.
빌드 유발
빌드 유발은 BitBucket이므로 필자는 "Build when a change is pushed to BitBucket"을 선택하겠다
BitBucket 플러그인을 설치하면 "Build when a change is pushed to BitBucket"이 추가된다.
( ** 플러그인은 "Dashboard > Jenkins 관리 > 플러그인 관리"에서 BitBucket을 검색하고 설치할 수 있다. )
Build
빌드는 Gradle 빌드를 사용할 것이다. build 명령어는 "clean > bootjar"이다.
bootjar로 jar가 생성되면 Shell 명령어로 docker에 올려주어야 한다.
Add build step으로 Execute shell을 추가한다.
Apply 버튼을 눌러서 적용시킨다.
Dockerfile, Docker Compose
Spring boot 프로젝트 구조는 아래와 같다.
프로젝트 최상위 경로에 Dockerfile과 docker-compose.yml이 존재한다.
결국엔 Jenkins에서 빌드 후 Dockerfile과 docker-compose를 통해 컨테이너로 올리게 되는 것이다.
- Dockerfile
## Image 서버 Dockerfile
FROM openjdk:11
LABEL service="dike-api" jdk-ver="11"
RUN mkdir -p /dike
#RUN apk update
## openjdk 8 tz 설정.
RUN groupadd -g 999 dike
RUN useradd -r -u 999 -g dike dike
#변수 생성 bootjar로 생성된 jar를 가르킴.
ARG JAR_FILE=dike-api/build/libs/*.jar
## jenkins workspace jar 파일 이동.
ADD ${JAR_FILE} /dike/dike-api.jar
## CMD, ENTRYPOINT 실행 경로.
WORKDIR /dike
## profiles 설정 버전
## ENTRYPOINT ["javar", "-jar", "-Dspring.profiles.active=dev", "dike-api-0.0.1-SNAPSHOT.jar"]
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=dev","dike-api.jar"]
- docker-compose.yml
version: '3'
services:
dike-api:
image: dike-api:latest
container_name: dike-api
# ports:
# - "48888:8080"
# privileged: true
# volumes:
# - /root/.gradle:/root/.gradle/
user: dike
environment:
- TZ="Asia/Seoul"
networks:
- dike
networks:
dike:
driver: bridge
Execute Shell이 실행되는 디렉터리 경로는
/var/jenkins_home/workspace/develop-build
Jenkins Home / workspace / Item 이름 경로에서 실행된다는 것을 알아야 한다.
'인프라' 카테고리의 다른 글
GitHub 계정 액세스 토큰 발급 받기. (0) | 2023.10.27 |
---|---|
CloudFront + Lambda(Edge) + S3 온디맨드 이미지 서버 만들기 (2) | 2022.11.11 |