Jenkins, Docker, gitLab Webhook을 이용한 자동 배포_2편

dgh03207·2022년 5월 17일
2

배포

목록 보기
2/4
post-thumbnail
post-custom-banner

Jenkins+Docker 자동배포

SpringBoot 백엔드 와 Next.js 프론트를 Jenkins를 이용해서 gitlab에 업로드 될때마다 자동빌드 및 배포를 할 수 있도록 프로그래밍한 내용을 담고 있다.
Nginx로 리버스 프록시와 페이지 리다이렉션을 진행했고, https 세팅까지 진행했다.
삽질끝에 얻은 정보들을 이 배포 시리즈에 최대한 담아봤는데, 많은사람들에게 도움이 되면 좋겠다.😆😍

프로젝트를 Dockerize 하기

프로젝트 내에 Dockerfile 을 생성하자

SpringBoot (백엔드) Dockerfile

Spring 공식문서에서 Dockerfile 문서를 가져왔다.

  • Java11Gradle 을 사용하였기때문에, jar 파일이 생성되는 경로가 build/libs/ 아래이므로, COPY 커맨드를 아래와같이 써주었다.
  • Maven 을 사용하는 경우 target/ 아래에 jar 파일이 생성되므로, 그렇게 작성해주면 된다.
  • EXPOSE 로 8081 포트를 지정해주었다.

Dockerfile은 컨테이너에 설치해야하는 패키지, 소스코드, 명령어, 환경변수 설정등을 기록한 하나의 파일로 애플리케이션 빌드 및 배포를 자동화하기위해 존재하는 것이다.

FROM adoptopenjdk/openjdk11:alpine
COPY build/libs/*.jar app.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/app.jar"]

Next.JS (프론트) Dockerfile

  • NextJSyarn 을 사용하였다.
  • yarn 명령어를 돌리기 위해, package.jsonyarn.lockCOPY 명령어를 통해 나의 디렉토리에 가져온다.
    • yarn 명령어는 프로젝트를 돌리기위해 필요한 패키지들을 다운받는 명령어다.
  • COPY . . dockerfile이 있는 장소에서의 모든것을 copy하는 명령어인데, yarn build 를 하기위하여 뭐가 필요할지모르니 그냥 다 받아왔다.
  • CMDENTRYPOINT 와 같은 명령어이지만, 컨테이너 시작시 실행 명령에 대한 Default 지정 여부가 가장 큰 차이다.
    • 이 블로그 에서 해당 부분을 잘 설명하고 있다.
    • 내용을 간단히 정리해보면
      CMD 로 전달한 인자값은 명령어를 실행시키는 사용자에 의해 추가 및 변경이 가능하고, ENTRYPOINT 로 전달한 인자값은 사용자에의해 변경이나 추가가 불가능하다.
FROM node:alpine

COPY package*.json ./
COPY yarn.lock ./

RUN yarn

COPY . .

RUN yarn build

EXPOSE 3000

CMD ["yarn","start"]

Jenkinsfile 작성

Dockerfile와 같은 위치에 Jenkinsfile도 생성해주자.

  • 파이프라인 정의를 위한 pipeline 을 최상위 레벨에 정의
  • agent 에 대한 자세한 정의는 공식문서를 참조하면 좋다. → 공식문서
    • 말그대로 파이프라인에서 사용할 에이전트를 정의하는 것인데,
    • any 를 사용하면, 에이전트로 사용할 수 있는 어떤것이든 사용하겠다 라는 말이다. 보통 많이 쓰는 것 같다.
  • stages 는 는 stage 들을 돌릴 블록이라고 생각하면 된다. → 공식문서

각각의 동작들을 통해 프로젝트 build와 run이 가능하고, 이 동작들에서 오류가 나면, 어떤 곳에서 에러가 나는지 Jenkins status를 통해 쉽게 파악이 가능하다.

SpringBoot (백엔드) Jenkinsfile

stage 에 들어가는 이름은 자유롭게 정하면 된다. 나중에 status에서 어떤 부분에서 에러가 났는지 확인하기 편하게 짓도록 하자.

도커 컨테이너 이름을 dockerhi 라고 치자.

  • Build stage에서는 SpringBoot 프로젝트를 build 해준다.
  • docker build 를 통해서 build가 완료된 실행파일로 dockerhi 라는 이름의 도커 컨테이너 를 생성해준다.
  • docker run 을 통해 이 컨테이너를 run 시켜준다.
    • docker run 쉘 명령어중
      • -d : Detached 모드로, 데몬 모드라고도 불리며, 백그라운드로 컨테이너를 실행시킴
      • --name : 컨테이너 이름을 설정함
      • -p : 포트번호를 지정하는데 외부포트:내부포트
      • -net : MySQL 을 도커위에서 돌리는데, 같은 네트워크내에서 돌아가도록 설정해주기위해서 해당 옵션을 사용했다. 필요없으면 빼도된다.
      • 옵션을 확인하고 잘 작성하자
pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'chmod +x ./gradlew'
                sh './gradlew bootJar'
            }
        }
        stage('docker build'){
            steps{
                script{
                    docker.build('dockerhi')
                }
            }
        }

        stage('docker run'){
            steps{
                sh 'docker ps -f name=dockerhi -q | xargs --no-run-if-empty docker container stop'
                sh 'docker container ls -a -f name=dockerhi -q | xargs -r docker container rm'
                sh 'docker images --no-trunc --all --quiet --filter="dangling=true" | xargs --no-run-if-empty docker rmi'
                sh 'docker run -d --name dockerhi --net {네트워크명} -p 8081:8081 dockerhi:latest'

            }
        }

    }
}

NextJS(프론트) Jenkinsfile

pipeline {
    agent any
    stages {

        stage('docker build'){
            steps{
                script{
                    docker.build('dockerhi')
                }
            }
        }

        stage('docker run'){
            steps{
                sh 'docker ps -f name=dockerhi -q | xargs --no-run-if-empty docker container stop'
                sh 'docker container ls -a -f name=dockerhi -q | xargs -r docker container rm'
                sh 'docker images --no-trunc --all --quiet --filter="dangling=true" | xargs --no-run-if-empty docker rmi'
                sh 'docker run -d --name dockerhi -p 3000:3000 dockerhi:latest'

            }
        }
        
    }
}
  • docker ps 명령어를 통해 현재 실행중인 컨테이너 확인이 가능하다.
  • docker ps -a 명령어를 통해 존재하는 모든 컨테이너 를 확인할 수 있다.
  • docker run 부분에서 에러가 나면 보통은 같은 이미지를 빌드하는 컨테이너가 있다는 에러가 뜰것이니, 필요없는 컨테이너들을 삭제해주도록 하자. docker rm [컨테이너ID]
  • docker logs [컨테이너명] 을 통해서 어느 부분에서 에러가 났는지 확인할 수 있다.

Docker위에 MySQL 올리기

docker-compose.yml

version: '3.8'

services:
  db:
    container_name: my_db
    image: mysql
    restart: always
    env_file:
      - .env
    environment:
      TZ: Asia/Seoul
    volumes:
      - ./db_volumes/conf.d:/etc/mysql/conf.d
      - ./db_volumes/data:/var/lib/mysql
      - ./db_volumes/initdb.d:/docker-entrypoint-initdb.d
    ports:
      - '3307:3307'
    networks:
      - my_network
networks:
  my_network:

docker-compose up -d 명령어를 통해 쉽게 mysql을 도커에 다운받을 수 있다.

.env 파일을 생성하여 민감한 정보들을 담아둘 수 있다.

MYSQL_HOST=
MYSQL_PORT=
MYSQL_ROOT_PASSWORD=
MYSQL_DATABASE=[db이름]
MYSQL_USER=[user]
MYSQL_PASSWORD=[pwd]
profile
같이 공부하자!
post-custom-banner

4개의 댓글

comment-user-thumbnail
2022년 5월 18일

잘봤습니다~

1개의 답글
comment-user-thumbnail
2022년 5월 18일

잘 봤어요!! 다음 글 기대되네요ㅎㅎ

1개의 답글