Jenkins/Docker를 이용하여 AWS EC2 서버에 Gradle로 빌드한 jar 파일을 배포할 것이다.
이는 Spring Boot로 작성한 프로젝트를 Jenkins와 Docker를 활용하여 이미지를 생성하고 그 이미지를 기반으로 ssh로 연결된 EC2에 자동 배포하는 것이다.
jenkins를 이용한 시스템 구성도
는 아래와 같다.
# 사용할 AMI 버전
Springbot 2.6.3
gradle 7.4
AWS EC2 이미지 : Ubuntu 20.04
먼저 만든 SpringBoot 프로젝트를 Docker image로 생성해야 한다.
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
return "jenkins_test";
}
}
앞서 그 이미지를 사용하기 위한 Dockerfile
을 먼저 생성한다.
Dockerfile (위치: 프로젝트 루트)
FROM openjdk:11-jdk
LABEL maintainer="mooh2jj@naver.com"
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
💥주의
gradle jar 파일 생성이 springboot 2.5버전부터는 java 명령어를 통해 jar 파일이 2개가 생성된다고 한다. 그래서 별도의 설정
을 해야JAR_FILE=build/libs/*.jar
에 error가 안나온다!
build.gradle
의 별도 설정(plain jar 파일 제거)
jar {
enabled = false
}
이제, 로컬에서 별도로 잘되는지 확인하고 Dockerfile을 이용해서 이미지를 만든다.
sudo docker build -t mooh2jj/docker-jenkins-github-test .
그 다음 도커 이미지가 제대로 되있는 확인한다.
sudo docker images
이제 빌드한 네임대로 docker image를 dockerhub
레포지토리에 등록할 것이다.
이 허브에 image를 등록해서 배포할 때 pull
을 하기 위함이다.
dockerhub
레포지토리는 이렇게 만들어주자.
그다음 로컬에서 docker 이미지를 저 만든 레포지토리에 push한다.
sudo docker push mooh2jj/docker-jenkins-github-test
이제부터 배포할 서버(worker-instacne)는 이 레포지터리에 등록된 이미지를 pull 받아서 사용할 것입니다.
서버설치는 전에 만든 걸 적은 블로그를 참조해두었다.
서버의 종류는 jenkins 인스턴스
, 그리고 배포할 서버인 worker 인스턴스
2개이다.
EC2 서버에는 docker> jenkins 를 설치한다.
설치하는 방법은 이 블로그 참조.
jenkins 설치
: https://velog.io/@mooh2jj/Jenkins-AWS-EC2-설치
그리고 worker 인스턴스에는 docker 를 설치해주자.
docker 설치
: https://velog.io/@mooh2jj/AWS-EC2-Docker-설치
Jenkins SSH 서버 등록
: https://velog.io/@mooh2jj/젠킨스-자동배포하기
1) Jenkins 인스턴스
개인키&공개키
생성
2) 공개키 - SSH서버(worker 인스턴스)에 등록
3) 개인키 - Jenkinspublish-over-ssh
페이지에 Key에 등록
이 순서로 하면 된다.
밑에 Test Configuraion이 Success
가 뜨면 젠킨스가 배포할 서버인 SSH 인스턴스 접속이 성공한 것이다.
Item
> Free Style
등록
먼저 이름은 아무렇게 지어도 좋다.
그 다음 프로젝트에 들어가서 구성
으로 들어간다.
소스 코드 관리
> Git
Repository URL 에 본인이 만든 프로젝트 Git주소를 적어준다.
프로젝트가 public
으로 되어 있다면 Credentials
는 따로 처리할 필요가 없다.
만약 private
라면 이 블로그를 참조해주기를 바란다.
https://velog.io/@mooh2jj/Jenkins-Git-webhook-설정
Build
> Invoke Grade script
> Use Gradle Wrapper
Invoke Gradle을 선택할 경우 Jenkins에 Global Toll Configuration에서 Gradle 패키지를 설치해야 사용할 수 있다.
여기서는 Use Gradle Wrapper
을 사용하자.
그리고 Make gradlew executable
까지 체크해준다.
이는 jar 파일 자체를 빌드를 해주는 것으로 gradlew 권한(chmod
) 문제로 실행이 안 되는 상황을 막아 주는 것이다.
그리고 Tasks
안에 clean build
를 넣어준다.
그리고
Build
> Execute shell
docker login -u [도커허브ID] -p [도커허브Password]
docker build -t [도커허브ID]/[도커허브 레포지토리 이름] .
docker push [도커허브ID]/[도커허브 레포지토리 이름]
를 적어준다.
그러면 Jenkins 내부 /var/jenkins_home/workspace/
안에 git 레포지토리로 등록한 프로젝트가 jenkins-docker-test
가 들어가고 그 프로젝트 안에 /gradlew clean build
가 실행되는 것이다.
# jenkins 내부 확인
docker exec -it [jenkins 컨테이너 ID] /bin/bash
root~ > cd /var/jenkins_home/workspace/
💥[도커허브Password]
같은 경우 보안 기밀 상 유출 위험이 있어 DockerHub 내에서 Token
을 생성해 기입할 수 있다.
DockerHub > Account Setting
> Security
> New Access Token
그다음 생성한 암호화된 Token을 [도커허브Password]
자리에 대체하면 된다.
💥 docker push가 정상적으로 동작되지 않을 때
=> docker login 이 안되서 !
denied: requested access to the resource is denied
Build step 'Execute shell' marked build as failure
SSH: Current build result is [FAILURE], not going to run.
Finished: FAILUREdocker-compose
💢 참고로, Invoke Gradle script
> Execute shell
이 순서로 진행해주어야 한다. docker 이미지에서 빌드하고 처리하기 때문에 docker push 전에 해야되기 때문이다.
빌드 후 조치
> Send build artifacts over SSH
jenkins 인스턴스 Freestyle Project 내 구성
에 다시들어가서, 빌드 후 조치로 SSH 인스턴스가 해주어야 명령어를 적어주어야 한다.
다음 2가지를 적어주면 된다.
1) Name
2) Exec command
Name은 알아서 Publish Over
를 통해 등록했으면 리스트로 나온 걸 선택해주면 된다.
SSH 원격 서버(worker instance)에 보낼 명령어를 적어주자.
Transfer Set에 Excute shell
만 적어주면 된다.
# 처음 컨테이너 돌시에
# sudo docker rm -f $(docker ps -aq)
# sudo docker rmi -f mooh2jj/docker-jenkins-github-test
sudo nohup docker run -p 8080:8080 mooh2jj/docker-jenkins-github-test > /dev/null 2>&1 &
웹 브라우저에서 잘 확인이 된다.
웹 URL : [등록한 SSH 서버 퍼블릭IP주소]:8080/test
이젠 Jenkins를 통해 Github에 push한 내용이 바로 빌드/배포 하는 과정이 자동화되어진 것이다.
Git + Jenkins + Docker 를 활용해 CI/CD 시스템을 만들면 개발하는 데 정말 편하다는 것을 알 수 있다.
Jenkins에서는 Schedule를 짜서 자동으로 배포하는 시스템이 마련되어 있다. 그중 하나가 build periodically
기능이다.
말그대로 주기성
을 가지고 빌드/배포한다는 것이다.
# Build every 5 minutes:
H/5 ****
출처 : https://www.baeldung.com/ops/jenkins-job-schedule
Mysql 도커로 설치및 실행
: 이 블로그 - Mysql 만들기 참조
https://velog.io/@mooh2jj/도커Docker-이미지로-Apache-및-PHP-개발환경-구축하기
추가로 해야할 일
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://{mysql-instacne IP}:9876/post
username: root
password: 1234
jpa:
open-in-view: true
hibernate:
ddl-auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
use-new-id-generator-mappings: false
show-sql: true
properties:
hibernate.format_sql: true
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
logging:
level:
root: info
com.example: debug
org.hibernate.SQL: debug
@RequiredArgsConstructor
@RestController
public class PostController {
public final PostRepositroy postRepositroy;
@PostMapping
public Post createPost(@RequestBody Post post) {
return postRepositroy.save(post);
}
@GetMapping("/posts")
public List<Post> getPostList() {
return postRepositroy.findAll();
}
}
@Getter
@Setter
@ToString
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String content;
}
public interface PostRepositroy extends JpaRepository<Post, Long> {
}