git repository에 있는 react project를 Jenkins를 사용해

 

자동으로 개발서버에 빌드 및 도커 컨테이너로 배포하려 한다.

 

젠킨스 > Jenkins 관리 > 플러그인 관리

docker를 사용하여 컨테이너를 띄울 예정이니 docker 관련 플러그인을 설치해주자.

 

Jenkins에서 파이프라인을 만들어보자

Jenkins > 새로운 Item

새로운 Item을 생성한다.

 

Jenkins > 새로운 Item

'Pipeline', 배관 아이템을 선택한다. 아이템 이름은 필수값이다.

 

Jenkins > 새로운 Item > Pipeline

SCM을 Git으로 선택 후, GitHub의 Repository를 선택해준다.

Credentials에서는 여기서 생성한 Credential을 넣으면 된다.

 

Branches to build에는 master브랜치를 입력해준다.

개발 branch를 따로 지정해주고 싶다면 그렇게 해도 된다.

 

Script Path에는 레파지토리에 사전 작성할 파이프라인 스크립트의 파일명을 입력해주면 된다.

그리고 레파지토리에 Script Path에 해당하는 경로에 Script파일을 작성하면 된다.

나는 다음과 같이 작성했다.

pipeline {
    agent none
    //기본적으로 체크아웃을 하지 않는 옵션
    options { skipDefaultCheckout(true) }
    stages {
        stage('Checkout repository') {
            agent any
            steps {
                checkout scm
            }
        }
        stage('Build') {
            agent {
                docker {
                    image 'node:14.15.2-alpine'
                }
            }
            steps {
                sh 'npm install'
                sh 'npm run build'
            }
        }
        stage('Docker build') {
            agent any
            steps {
                sh 'docker build -t {image_name}:latest .'
            }
        }
        stage('Docker run') {
            agent any
            steps {
                sh 'docker ps -f name=raor_dev -q | xargs --no-run-if-empty docker container stop'
                sh 'docker container ls -a -fname=raor_dev -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 {container_name} -p 80:80 {image_name}:latest'
            }
        }
    }
}

Checkout repository에서 레파지토리 내용을 checkout받고 

Build에서 node를 docker agent로 실행해 소스를 build한다.

Docker build에서 도커 이미지를 빌드하고

Docker run에서 기존 컨테이너와 이미지를 지우고 새로운 컨테이너를 실행한다.

 

도커 build stage에서 사용할 Dockerfile은 다음과 같이 작성했다.

FROM nginx:latest
VOLUME /raor_dev_volume
RUN rm -rf /etc/nginx/conf.d/default.conf
ADD ./nginx/default.conf /etc/nginx/conf.d/default.conf
ADD ./build /usr/share/nginx/html

혹시 nginx 컨테이너와 파일 교환이 필요할 때 사용할 volume을 마운트해주고

build stage에서 빌드해놓은 ./build 디렉토리를 컨테이너의 nginx/html로 복사해주면 된다.

 

nginx의 기본 설정 파일의 경로는 /etc/nginx/conf.d/default.conf 이며

레파지토리에 nginx의 설정 파일을 작성해놓고 사용하려 한다. 기존 이미지에 있는 conf 파일은 삭제해준다.

사용자에게 api서버를 노출하지 않고 nginx가 제공하는 reverse proxy를 사용하려면 필수이다.

 

물론 nginx 컨테이너를 사용하지 않고 node 컨테이너를 사용하여 npm serve를 사용해 빌드된 리액트 애플리케이션을 실행 할 수 있다.

위와 같은 방법은 최신버전에서 보안도 많이 개선되었다고 한다. 하지만 nginx는 잘 알려진 훌륭한 웹서버이며 node컨테이너를 웹서버화하여 이미지로 만들어야 하는 번거로움도 없다.

 

이제 젠킨스에서 PIPELINE 실행을 통해 GitHub 레파지토리의 파일을 체크아웃받아 node로 빌드를 하고 nginx 이미지를 통해 빌드된 React application을 웹서버 컨테이너로 실행 할 수 있다.

 

 

 

작성 참조 링크

www.jenkins.io/doc/tutorials/build-a-node-js-and-react-app-with-npm/

twofootdog.github.io/Docker-Docker%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EB%A1%9C-jenkins-%EC%8B%A4%ED%96%89-%ED%9B%84-%EC%86%8C%EC%8A%A4-push-%EC%8B%9C-%EC%9E%90%EB%8F%99-%EB%B9%8C%EB%93%9C%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0(Springboot)/

728x90
반응형

젠킨스 > Jenkins 관리 > 플러그인 관리

젠킨스에서 플러그인 관리 화면으로 진입한다.

 

젠킨스 > Jenkins 관리 > 플러그인 관리

git과 github관련 플러그인의 설치를 확인한다. 설치되어 있지 않다면 설치해야 한다.

 

 

GitHub 계정별 연동

github으로 가자.

 

github > Settings

github > Settings > Developer setting

Developer setting 항목을 찾는다.

 

github > Settings > Developer settings > Personal access tokens

Personal acceess tokens 항목에서 계정의 토큰을 생성 할 수 있다.

Generate new token 버튼으로 토큰을 생성한다.

위 캡쳐에서처럼 admin:org(레파지토리 읽기/쓰기), admin:repo_hook(레파지토리 훅 권한) -깃헙에 push가 일어나면 자동으로 빌드되어 컨테이너를 실행할 수 있도록-, repo(레파지토리 접근) 스콥으로 진행하겠다.

 

젠킨스 > Jenkins 관리 > 환경설정

이후 Jenkins 환경설정에서 Add GitHub Server를 눌러주자.

젠킨스 > Jenkins 관리 > 환경설정

Add버튼으로 Credentials를 등록한다.

GitHub > GitHub Server > Add Credentials

Kind - Secret text

Secret - 토큰

을 입력해주면 된다.

Jenkins > Jenkins 관리 > 환경설정

Test connection버튼으로 연결을 확인하고 환경설정 가장 아래의 저장 또는 Apply버튼으로 세팅을 저장한다.

(사실 Public Repository로 진행한다면 이 과정은 필요없다)

 

 

SSH KEY연동방식

젠킨스와 gitHub 연동시 계정을 통째로 인증하는 방식은 보안상 위험 할 수 있다.

 

따라서 SSH 연동방식또한 소개한다.

 

간단하게, 더 귀찮고 더 보안이 좋은 방식이다.

 

cd /var/jenkins_home
mkdir .ssh
ssh-keygen -t rsa -f /var/jenkins_home/.ssh/github_rsa_ssh_key

먼저 SSH 키를 생성한다.

키의 이름은 github_rsa_ssh_key 으로 하겠다.

 

 

GitHub > Repository > Settings > Deploy keys > Add deploy key

깃헙 레파지토리에서 Setting > Deploy keys > Add deploy key항목을 찾아낸다.

 

GitHub > Repository > Settings > Deploy keys > Add deploy key

방금 생성한 ssh key 중 확장자가 .pub으로 되어있는 public key를 등록해준다.

 

SCM: Git > Repositories > Credentials

이후 Credentials를 등록하는 화면에서 위와 같이 입력한다.

Private Key는 위에서 생성한 SSH키 중 private key를 입력하면 된다.

 

SCM: Git > Repositories

Repository URL은 위와 같이 SSH방식으로 적어야 한다

 

이상 GitHub과 Jenkins를 연동하는 두가지 방법이다.

728x90
반응형

git repository에 있는 spring boot project를 Jenkins를 사용해

 

자동으로 개발서버에 빌드 및 도커 컨테이너로 배포하는 일기다.

 

젠킨스 > Jenkins 관리 > 플러그인 관리

docker를 사용하여 컨테이너를 띄울 예정이니 docker 관련 플러그인을 설치해주자.

 

Jenkins에서 파이프라인을 만들어보자

Jenkins > 새로운 Item

새로운 Item을 생성한다.

 

Jenkins > 새로운 Item

'Pipeline', 배관 아이템을 선택한다. 아이템 이름은 필수값이다.

 

Jenkins > 새로운 Item > Pipeline

SCM을 Git으로 선택 후, GitHub의 Repository를 선택해준다.

Credentials에서는 여기서 생성한 Credential을 넣으면 된다.

 

Branches to build에는 master브랜치를 입력해준다.

개발 branch를 따로 지정해주고 싶다면 그렇게 해도 된다.

 

Script Path에는 레파지토리에 사전 작성할 파이프라인 스크립트의 파일명을 입력해주면 된다.

그리고 레파지토레에 Script Path에 해당하는 경로에 Script파일을 작성하면 된다.

나는 다음과 같이 작성했다.

pipeline {
    agent none
    //기본적으로 체크아웃을 하지 않는 옵션
    options { skipDefaultCheckout(true) }
    stages {
        stage('Checkout repository') {
            agent any
            steps {
                checkout scm
            }
        }
        stage('Build and test') {
            agent {
                docker {
                    image 'gradle:6.6.1-jdk11-openj9'
                    args '-v /root/.m2:/root/.m2'
                }
            }
            steps {
                sh 'gradle clean build -x test'
            }
        }
        stage('Docker build') {
            agent any
            steps {
                sh 'docker build -t {container_name}:latest .'
            }
        }
        stage('Docker run') {
            agent any
            steps {
                sh 'docker ps -f name={container_name} -q | xargs --no-run-if-empty docker container stop'
                sh 'docker container ls -a -fname=sbor_dev -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 {container_name} -p 8080:8080 {container_name}:latest'
            }
        }
    }
}

Checkout repository에서 레파지토리 내용을 checkout받고 

Build and test에서 gradle을 docker agent로 실행해 소스를 build한다.

Docker build에서 도커 이미지를 빌드하고

Docker run에서 기존 컨테이너와 이미지를 지우고 새로운 컨테이너를 실행한다.

 

도커 build stage에서 사용할 Dockerfile은 다음과 같이 작성했다.

FROM openjdk:11
ADD {your_application_file} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

open jdk 이미지의 정보는 https://hub.docker.com/_/openjdk 여기서 확인할 수 있으며 컨테이너와 파일교환을 위해 volume을 따로 설정해줘도 좋다.

 

이제 젠킨스에서 PIPELINE 실행을 통해 GitHub 레파지토리의 파일을 체크아웃받아 gradle로 빌드를 하고 OpenJDK11버전 이미지를 통해 SpringBoot Application을 컨테이너로 실행 할 수 있다.

 

 

[Trouble Shooting]

Jenkins

Invalid agent type "docker" specified.

Jenkins에서 docker 관련 플러그인이 없을 경우. 관련 플러그인 설치로 해결.

 

 

container 내부 docker 설치

/var/jenkins_home/workspace/{depends on you}/script.sh: docker: not found

컨테이너 내부에 docker가 설치되어있지 않음을 간과한경우.

도커가 설치되어 있는 컨테이너를 사용해야 한다.

curl -fsSL https://get.docker.com/ | sudo sh

 

 

Jenkins docker container

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/amd64/gradle:6.6.1-jdk11-openj9/json: dial unix /var/run/docker.sock: connect: permission denied

컨테이너에서 docker.sock에 대한 실행권한이 없다. 컨테이너에서 구동되는 jenkins는 jenkins라는 user권한을 사용하기 때문에 docker그룹에 추가해주자.

컨테이너의 root권한 bash를 열어준 뒤 그룹에 추가하면 된다.

이후 도커 데몬을 재기동 해주자.

usermod -aG docker jenkins
service docker restart


docker rmi

docker: "rmi" requires a minimum of 1 argument.

docker rmi 명령어가 삭제할 이미지가 없는 경우다.

docker rmi $(docker images --filter "dangling=true" -q --no-trunc)

위와 같이 잉여 이미지를 정리하는 명령어를 사용 할 때, 이미지가 하나도 없는 깨끗한 상태라면 바로 에러를 뿜게 된다.

따라서 다음과 같이 --no-run-if-empty를 사용하자

docker images --no-trunc --all --quiet --filter="dangling=true" | xargs --no-run-if-empty docker rmi

참조: stackoverflow.com/questions/35416962/error-while-cleaning-images-from-docker

 

 

 

작성 참조 링크

twofootdog.github.io/Docker-Docker%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EB%A1%9C-jenkins-%EC%8B%A4%ED%96%89-%ED%9B%84-%EC%86%8C%EC%8A%A4-push-%EC%8B%9C-%EC%9E%90%EB%8F%99-%EB%B9%8C%EB%93%9C%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0(Springboot)/

tomgregory.com/building-a-spring-boot-application-in-docker-and-jenkins/

 

728x90
반응형

Ubuntu 18.04.5 LTS에서 Docker를 사용해 Jenkins를 띄우려 한다.

 

준비물은 dockerhub 계정.

 

1. 패키지 정보 업데이트

sudo apt-get update

 

2. 도커 설치

curl -fsSL https://get.docker.com/ | sudo sh

Ubuntu의 경우 Docker에서 제공해주는 스크립트로 편하게 설치 할 수 있다.

 

3. 사용자 계정을 docker 그룹에 추가

sudo usermod -aG docker ${계정}

 

 

4. dockerhub에 로그인

docker login [URL]

URL을 생략하게 된다면 기본적으로 dockerhub에 로그인하게 된다.

계정이 준비되어있지 않다면 hub.docker.com 에서 계정을 생성하자.

 

 

이상으로 docker 설치가 완료되었다. docker -v 등의 명령어로 도커가 설치되었나 확인해보자.

 

5. Jenkins 이미지 다운로드

원래 docker pull 명령어를 실행했을때 local에 image가 없으면 docker pull로 가져온다.

하지만 docker 20.10.1, Ubuntu 18.04.5 버전에서 manifest unknown에러가 발생하기 때문에 수동으로 젠킨스 이미지를 받아야 했다.

hub.docker.com/_/jenkins?tab=tags&page=1&ordering=last_updated

 

jenkins Tags - Docker Hub

 

hub.docker.com

위 링크에서 Docker Hub Repository에 있는 최신 도커 이미지를 확인 할 수 있다.

docker pull jenkins:2.60.3

 

6. Host와 컨테이너간 파일 공유를 위한 디렉토리를 생성해야 한다.

mkdir jenkins
mkdir jenkins/jenkins_home

 

7. jenkins 컨테이너를 실행한다.

docker run -d -p 8080:8080 -p 50000:50000 -v $PWD/jenkins/jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock --name jenkins jenkins/jenkins

포트정보와 jenkins setting이 저장될 볼륨은 원하는대로 세팅해도 좋다.

jenkins 컨테이너가 docker 컨테이너를 띄우게 해야 함으로 docker.sock파일도 볼륨으로 지정해준다.

 

-d
Detached Mode. 컨테이너가 백그라운드로 실행된다.

--name ["이름"]
컨테이너의 이름을 설정한다.

-v
데이터 볼륨을 설정한다. host와 공유할 디렉토리를 설정하여 파일을 컨테이너에 저장하지 않고 호스트에 바로 저장한다.

 

-p

컨테이너의 포트를 호스트의 특정 포트와 연결한다. [호스트포트]:[컨테이너포트]

컨테이너 포트만 입력하면 호스트의 포트가 무작위로 연결된다.

 

Jenkins의 Initial Password를 확인해야 한다.

jenkins_home의 공유디렉토리를 설정해주었으니 ./jenkins/jenkins_home/secrets/initialAdminPassword 파일을 통해 확인 할 수 있다.

 

7-1. KST 시간대 설정

dockerhub에서 제공하는 jenkins는 기본적으로 UST 시간대로 설정이 되어 있기 때문에 이것을 KST로 바꿔줬다.

docker exec -itu 0 jenkins /bin/bash
ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

컨테이너 내에서 'sudo'를 지원하지 않음으로 root유저(0)로 바쉘을 실행한다.

이후 시간대의 링크를 바꿔준 후 date 명령어로 시간대를 확인하면 바뀐것을 알 수 있다.

 

 

8. jenkins 버전 업데이트

애석하게도 dockerhub에서 제공해준 최신 이미지 2.60.3버전에서는 젠킨스 플러그인을 멀쩡하게 사용 할 수 없다.

2.164.3 버전 이상을 요구하니 jenkins를 업데이트해야 한다.

 

mirrors.jenkins-ci.org/

 

Jenkins mirrors

 

mirrors.jenkins-ci.org

위 Jenkins mirrors 페이지에서 최신 jenkins버전을 확인 할 수 있다.

그 중 war-stable의 최신버전인 2.263.1버전으로 해야겠다.

 

root 권한을 이용해 bash을 열자

wget http://updates.jenkins-ci.org/download/war/2.263.1/jenkins.war
mv ./jenkins.war /usr/share/jenkins/
chown jenkins:jenkins /usr/share/jenkins/jenkins.war

 

이후 컨테이너를 restart한다.

 

8. 젠킨스 설정

드디어 docker 컨테이너가 running중인 서버 8081포트로 접속하여 7번과정에서 확인한 initialPassword로 진행하면 된다.

728x90
반응형

+ Recent posts