SpringBoot & Docker & DockerHub & EC2 & GitHub & JenkinsCI/CD

devty·2023년 6월 8일
0

DevOps

목록 보기
4/11
post-thumbnail

Architecture

대략적인 과정

  1. Local에서 Github에 푸시한다.
  2. Github의 webhook을 이용하여 jenkins에 전송한다.
  3. jenkins에서 Github의 코드를 받고 빌드, 테스트를 진행한다.
  4. 받은 코드 중 Dockerfile을 이용하여 이미지를 빌드하고 Docker hub에 푸시한다.
  5. 또한 받은 코드 중 deploy.sh 파일을 jenkins에 설정한 운영용 EC2 서버로 전송하고 실행을 한다.
  6. deploy.sh 파일에는 가동중인 docker를 중지 및 삭제를 하고 Docker hub에 올려져 있는 docker image를 받아옵니다.
  7. 받아온 이미지를 docker run 시켜 SpringBoot 프로젝트를 띄운다.

SpringBoot Code

SampleController : 간단한 테스트를 하기 위한 컨트롤러

Dockerfile : 도커파일

deploy.sh : 배포용 스크립트

  • 패키지 구조

  • deploy.sh → scripts 디렉토리 안에 둔다.
  • Dockerfile → 프로젝트에 root 부분에 둔다.
  • SampleController → src 디렉토리 안에 둔다.

HealthController

@RestController
public class SampleController {

    @RequestMapping("/sample")
    public String sample() {
        return "checkcheck";
    }
}

Dockerfile

# Amazon JDK11 사용
FROM amazoncorretto:11

# JAR_FILE 변수에 값을 저장
ARG JAR_FILE=build/libs/*.jar

# 변수에 저장된 것을 컨테이너 실행시 이름을 app.jar파일로 변경하여 컨테이너에 저장
COPY ${JAR_FILE} app.jar

# 빌드된 이미지가 run될 때 실행할 명령어
ENTRYPOINT ["java","-jar","/app.jar"]

deploy.sh

# docker를 시작하기 위함
sudo systemctl start docker

# 가동중인 mkc 도커 중단 및 삭제
docker ps -a -q --filter "name=mkc" | grep -q . && docker stop mkc && docker rm mkc | true

# 기존 이미지 삭제
docker rmi taeyun1215/mkc

# 도커허브 이미지 pull
docker pull taeyun1215/mkc

# 도커 run
docker run -d -p 8080:8080 --name mkc taeyun1215/mkc

# 사용하지 않는 불필요한 이미지 삭제 -> 현재 컨테이너가 물고 있는 이미지는 삭제되지 않습니다.
docker rmi -f $(docker images -f "dangling=true" -q) || true

운영용 EC2 만들기

  1. EC2 만들기는 밑에 페이지에 시작부분을 참고하여 만들면 된다.

    AWS EC2

  2. 나는 이름 및 태그를 study-cicd-docker로 두었다.

Jenkins용 EC2 만들기

  1. 마찬가지로 위 링크를 참고하되 이름 및 태그를 study-cicd-jenkins로 두었다.
  2. 키 페어는 운영용 EC2 만들 때 사용한 키 페어를 사용하면 된다.
  3. 보안 그룹도 새로 만들되 기존 보안 그룹 규칙 1, 2, 3은 그대로 사용하고 보안 그룹 규칙 4번은 사용자 지정 TCP로 두고 포트는 8085으로 소스 유형은 내 IP만 허락하면 된다.
    • 위와 같이 하는 이유는 Jenkins는 다른 사람이 접속하면 안되기 때문이다.

EC2에 탄력적 IP 할당하기

  1. 탄력적 IP를 할당하는 이유는?

    • 인스턴스는 생성 시 및 중지했다가 다시 시작하는 경우 새로운 IP주소를 할당하게 된다.
    • 따라서 그런 번거로움을 줄이고자 탄력적 IP를 사용하면 고정된 IP가 만들어져 해당 인스턴스들에게 연결만 시켜주면 된다.
  2. EC2 메인페이지에 왼쪽 탭에 네트워크 및 보안 → 탄력적 IP → 탄력적 IP 주소 할당을 클릭한다.

    • 할당을 눌러주면 탄력적 IP가 생성된다.
  3. 우리는 운영 EC2, jenkins EC2 두개 이므로 탄력적 IP를 두개 생성해준다.

  1. 탄력적 IP를 기존에 만들어 두었던 두개 EC2에 연결하면 된다. → 탄력적 IP 주소 연결을 클릭한다.

  1. 탄력적 IP 1개는 운영용 EC2, 나머지 탄력적 IP는 jenkins EC2로 매칭해서 연결한다.

  2. 연결된 탄력적 IP는 EC2 메인페이지에서 확인이 가능하다.

EC2 서버 접속 방법

  • EC2 접속방법은 밑 페이지중 EC2 접속방법이라는 머릿말을 찾으면 된다. EC2 접속방법

운영용 EC2 세팅하기

  • 운영용 EC2에 도커를 설치한다.
    # 운영 EC2 접속
    ssh 호스트명
    
    # 패키지 업데이트
    sudo yum -y upgrade
    
    # 도커 설치
    sudo yum -y install docker
    
    # 도커 설치 작업이 잘 되었는지 버전 확인
    docker -v
    
    # 도커 시작
    sudo service docker start
    
    # 도커 그룹에 사용자 추가 -> docker가 그룹명, ec2-user가 사용자명
    sudo usermod -aG docker ec2-user

jenkins EC2 세팅하기

jenkins EC2 세팅하기 전 시나리오를 알고 있어야한다.

  • 도커를 이용하여 jenkins를 띄운다.
  • 띄운 jenkins에서 docker hub에 docker image를 push 해야한다.
  • 즉, 도커로 연 jenkins에서 다시 docker 명령어를 쓸 수 있게 해야한다.
    • 도커 위에서 도커를 사용해야한다.
  • 이러한 방법에는 2가지 방식이 있다.
    • DinD(Docker in Docker)방식
    • DooD(Docker Out of Docker)방식
  • Docker 측에서는 도커 안에 도커를 띄우는 것을 권장하진 않지만 그나마 DooD방식을 권장하고 있다.
  • 결론적으로 DooD 방식으로 도커위에 도커를 띄우기 위해서는 -v 옵션으로 호스트의 docker socket을 빌려서 사용하면 된다.
  1. Jenkins EC2에 도커를 설치한다.

    # 운영 EC2 접속
    ssh 호스트명
    
    # 패키지 업데이트
    sudo yum -y upgrade
    
    # 도커 설치
    sudo yum -y install docker
    
    # 도커 설치 작업이 잘 되었는지 버전 확인
    docker -v
    
    # 도커 시작
    sudo service docker start
    
    # 도커 그룹에 사용자 추가 -> docker가 그룹명, ec2-user가 사용자명
    sudo usermod -aG docker ec2-user
  2. Dockerfile 생성 및 코드 작성

    # Dockerfile 생성
    sudo vim Dockerfile
    
    # Dockerfile 작성 시작
    FROM jenkins/jenkins:jdk11
    
    # 도커를 실행하기 위한 root 계정으로 전환
    USER root
    
    # 도커 설치
    COPY docker_install.sh /docker_install.sh
    RUN chmod +x /docker_install.sh
    RUN /docker_install.sh
    
    # 도커 그룹에 사용자 추가
    RUN usermod -aG docker jenkins
    USER jenkins
  3. docker_install 생성 및 코드 작성

    # docker_install.sh 파일 생성
    sudo vim docker_install.sh
    
    # docker_install.sh 파일 작성 시작
    # !/bin/sh
    apt-get update && \
    apt-get -y install apt-transport-https \
      ca-certificates \
      curl \
      gnupg2 \
      zip \
      unzip \
      software-properties-common && \
    curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && \
    add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
    $(lsb_release -cs) \
    stable" && \
    apt-get update && \
    apt-get -y install docker-ce
  4. 2, 3번 파일인 Dockerfile, docker_install은 동일한 디렉토리에 두고 빌드해야하며 docker.sock 권한을 변경해줘야한다.

    sudo chmod 666 /var/run/docker.sock
  5. Dockerfile을 빌드하여 이미지 생성한다.

    docker build -t jenkins .
  6. 해당 폴더를 만드는 이유는 아직 잘 모르겠다..todo

    # jenkins 폴더 만들기
    mkdir jenkins
    
    # 해당 폴더에 대해 권한 부여하기
    sudo chown -R 1000 ./jenkins
  7. 이제 jenkins 컨테이너를 띄운다.

    sudo docker run -d --name jenkins \
    -v /home/ec2-user/jenkins:/var/jenkins_home \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -p 8085:8080 \
    -e TZ=Asia/Seoul \
    jenkins
    • d : 벡그라운드로 띄우기
    • v : 볼륨 마운트
    • p : 포트 설정
    • e : 환경변수 설정 옵션으로 한국시간으로 설정하는 옵션을 주었습니다.

jenkins 세팅

  1. EC2에서 설정해준 탄력적 IP가 필요하다.

  2. 접속을 하면 비밀번호를 입력하라는 페이지가 나온다.

  3. jenkins에 접속을 했다면 jenkins 관리 → System Configuration → ****플러그인 관리 → install plugins에 플러그인을 검색하여 설치해준다.

    • gradle → spring boot의 gradle을 사용하기 위한 플러그인
    • github integration → github의 webhook을 사용하기 위한 플러그인
    • post build task → 빌드 로그를 판단하여’ script 혹은 shell을 실행할 수 있게 하는 플러그인
    • publish over ssh → 다른 EC2에 접속하여 작업을 가능하게 해주는 플러그인
  4. jenkins 관리 → Security -> Manage Credentials를 클릭하여 jenkins에서 사용할 계정 정보들을 등록한다. 지금 하고 있는 Architecture에서는 Github와 Docker의 계정 등록이 필요하다.

    • global을 클릭하고 Add Credentials를 클릭하여 계정 정보를 등록한다.
    • Github
      • Kind → Username with password 입력 (고정)
      • Scope → Global (Jenkins, nodes, items, all child items, etc)를 입력 (고정)
      • Username → Github ID
      • Password → Github Password
      • Description → Github으로 입력하면 식별하기 편하다.
    • Docker
      • 위와 동일하게 작성하되 Username, Password, Description은 자기 도커 계정이 맞춰서 작성하면 된다.

Github Webhook & jenkins 연동

  1. Github → Setting → Developer setting → Personal access tokens으로 들어가서 Generate new token을 클릭후 token을 생성해준다. 밑은 권한 설정이다.

    • repository의 권한
    • org의 권한
    • hook의 권한
    • 생성하게 되면 token_key가 나온다. ghp로 시작하는 걸 적어두자.
  2. Jenkins와 Web hook으로 연결하고 싶은 프로젝트로 들어가서 오른쪽에 Settings를 클릭합니다.

  3. 왼쪽 탭에 Webhooks를 클릭한다.

  4. jenkins(main page) → jenkins 관리 → 시스템 설정을 클릭한다.

  5. Github 관련 세팅을 한다.

    • Name → 사용자가 원하는 이름을 입력
    • API URL → https://api.github.com (고정)
    • Credentials → Add를 클릭해서 밑에서 진행한다.
  6. Add를 클릭해서 나온 Add credential 페이지를 작성하면 된다.

    • Kind → Secret text로 변경.
    • Scope → Global (Jenkins, nodes, items, all child items, etc)를 입력 (고정)
    • Password → 발급 받은 토큰 값(ghp로시작하는 토큰 값) ****입력
    • ID → Jenkins 파이프라인에서 해당 credencial을 가져올때 사용할 이름, 사용자가 식별할 수 있는 ID값을 입력 (생략 가능)
  7. Test connection을 하면 연결이 됐는지 확인이 된다.

  • Credentials verified for user taeyun1215, rate limit: 4998라고 나오면 연결이 된 것이다.

SSH Servers 세팅

  • 이 접근 과정은 Jenkins EC2가 ssh키(pem키)를 가지고 운영용 EC2에 접근하는 과정이다.
  • 운영용 EC2의 보안 그룹에서는 Jenkins의 ssh 접근을 허용해줘야 한다. → 보안그룹 설정해야함. 다음 목차에서 하겠음.
  1. 방금 페이지에서 제일 아래로 내리면 SSH Servers를 설정할 수 있는 부분이 나올 것이다.

    • Name : Job에 표시될 이름
    • Hostname : 운영 EC2의 탄력적 IP를 입력함.
    • Username : ssh 접근 계정 (ec2-user) 거의 고정임.
    • Remote Directory : 업로드될 디렉토리 (생략 가능)
  2. 고급을 클릭하여 들어가면 key 값을 입력해야하는데 이것은 앞전에 받아온 pem 키값이다.

    • local에서 진행해야한다.

  • cat ~/.ssh/pem키 파일 명 → 키에 대한 private key의 값이 나올 것이다.
  • 출력된 key를 복사해서 붙여넣어준다.

Jenkins EC2에서 운영 EC2 열기 위한 보안 권한 추가

  1. Jenkins EC2에서 운영 EC2를 접속하는 것이기에 운영 EC2에 Jenkins EC2 보안 권한을 추가해줘야한다.

  2. AWS EC2 메인페이제에서 운영 EC2에 클릭하고 보안 탭을 클릭한다.

  3. 보안 → 보안 그룹에 존재한 그룹 클릭 → 인바운드 규칙 → 인바운드 규칙 편집을 클릭한다.

  4. 규칙 추가 → SSH, IP(jenkins EC2 탄력적 IP)로 등록한다.

Github의 web hook에서 Jenkins EC2 보안 권한 추가

  • Github의 web hook IP 허용 작업을 해야한다. 이 작업은 Jenkins EC2 보안 그룹을 수정해야한다.
  1. 위 운영 EC2와 똑같은 작업으로 Jenkins EC2 → 보안그룹 → 인바운드 규칙 편집을 클릭힌다.

  2. 사용자 지정 TCP, 8080, 해당 IP는 고정된 IP(web hook IP)이다.

    • 192.30.252.0/22
    • 185.199.108.0/22
    • 140.82.112.0/20
  3. 여기까지 끝났다면 방금전에 작성하던 Jenkins ssh 설정 페이지에서 Test Configuration을 클릭하여 연결을 확인한다.

    • Success가 나오면 연동이 된 것이다.
  4. 하단에 저장버튼클 클릭합니다.

Gradle 세팅

  • jenkins 메인페이지 → jenkins 관리 → Global Tool Configuration

    • name → gradle의 버전을 알아 볼수 있는 이름으로 지정
    • version → gradle의 version 세팅

프로젝트 생성

  • 이제 기본적인 세팅은 끝났고 jenkins에서 빌드 및 배포하는 작업을 수행해야함.
  1. jenkins 메인페이지 → 새로운 item → awstest (프로젝트 명) → Freestyle project으로 생성.

  2. GitHub project를 선택하고 project url에 본인의 프로젝트 주소를 입력한다.

  3. Git을 선택하고 밑과 같이 작성한다.

    • Repository URL → 위에서 작성한 깃허브 링크에 .git만 붙여준다.
    • Credentials → 전에 Github 계정 정보를 만들어 두었던 Credentials를 선택한다.
    • Branch Specifier → Push했을 때 web hook이 반응하는 브런치이다.
  4. 빌드 유발은 GitHub hook trigger for GITScm polling만 체크한다.

  5. 빌드 환경에서 Use secret text or file을 선택하고 Bindings의 Add 드롭박스를 클릭하고 Username and password (separated)를 선택한다.

  6. 각각 Variable에 Username으로 사용할 변수명, Password로 사용할 변수명을 지정해주고 Credentials에 specific credentials을 선택하고 전에 만들어놓았던 Dockerhub 계정을 선택합니다.

    • 주의할 점
      • 나와 같은 경우에는 USERNAME, PASSWORD로 두었는데 그렇게 되면 밑에 빌드 진행한 후 동작할 명령어도 똑같이 입력해줘야함.
      • USERNAME → Docker hub ID가 들어가고
      • PASSWORD → Docker hub PASSWORD가 들어간다.
      • Credentials → Specific credentials를 선택후 이전에 만들어둔 docke hub 계정을 선택한다.
  7. Build에서 Invoke Gradle script를 선택한다.

    • 이전에 만들어둔 Gradle로 세팅을 하고 Tasks에는 빌드 명령어인 clean build를 적어준다.
  8. Add build step에서 Execute shell을 선택합니다.

    • Execute shell Command에는 빌드를 진행한 후 실행할 명령어를 입력한다.
      # 도커파일 이미지를 빌드합니다.
      docker build --build-arg DEPENDENCY=build/dependency -t taeyun1215/mkc --platform linux/amd64 .
      
      # 도커 로그인을 시도합니다. $변수명 을 이용하면 위에서 작성한 변수명으로 값을 사용할 수 있습니다.
      echo $PASSWORD | docker login -u $USERNAME --password-stdin
      
      # 도커허브에 빌드된 이미지를 푸시합니다.
      docker push taeyun1215/mkc
      
      # 푸시한 이미지를 삭제합니다.
      docker rmi taeyun1215/mkc
      
      # 참고
      # taeyun1215/mkc -> 도커 계정 ID/도커 레파지토리 명으로 두면 된다.
      # 위 부분은 처음에 작성한 script/depoly.sh에서 사용할 명이니 참고해야한다.
  9. 여기까지가 코드를 빌드, 테스트하고 이미지를 빌드하여 도커허브에 푸시하는 작업이다.

  10. 이 밑 부터는 Jenkins EC2에서 운영용 EC2로 접속하는 작업이다.

  11. 빌드 후 조치를 선택하고 send build artifacts over SSH를 선택합니다.

    • send build artifacts over SSH → 운영용 EC2로 접속하기 위함.
  12. send build artifacts over SSH에 운영용 EC2를 설정하면 된다.

    • Name : 전에 세팅했던 ssh 서버를 선택합니다.
    • Source files : 운영용 EC2로 보낼 파일의 위치를 작성합니다.
    • Remove prefix : 파일 앞부분의 경로를 적어줍니다.
      • scripts/deploy.sh 파일의 scripts/를 제거하고 deploy.sh만 복사시켜 줍니다.
    • Exec command : 실행할 명령어를 작성합니다.
      # 운영용 EC2에서 도커에 로그인을 합니다.
      echo $PASSWORD | docker login -u $USERNAME --password-stdin
      
      # deploy.sh 파일을 실행합니다.
      sh deploy.sh
  13. 최종적으로 작업이 끝난 후 workspace를 비우도록 합니다.

    업로드중..

  14. 맨 아래 저장버튼을 클릭한다. 그럼 이제 Github에 지정한 브랜치에 푸시하면 자동으로 빌드 및 배포까지 가능하게 된다.

profile
지나가는 개발자

0개의 댓글