Jenkins 설치

Jenkins 설치 (Docker)

Jenkins 이미지 받기

docker의 pull 명령을 통해 최신 LTS 버전의 jenkins 이미지를 다운로드 한다

docker pull jenkins/jenkins:lts
docker pull jenkins/jenkins:jdk17

Jenkins 컨테이너 실행

docker run -d --restart always --env JENKINS_OPTS=--httpPort=8080 -v /etc/localtime:/etc/localtime:ro -e TZ=Asia/Seoul -p 8080:8080 -v /jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -v /usr/local/bin/docker-compose:/usr/local/bin/docker-compose --name jenkins -u root jenkins/jenkins:lts
docker run -d --restart always --env JENKINS_OPTS=--httpPort=8080 -v /etc/localtime:/etc/localtime:ro -e TZ=Asia/Seoul -p 8080:8080 -v /jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -v /usr/local/bin/docker-compose:/usr/local/bin/docker-compose --name jenkins -u root jenkins/jenkins:jdk17

Jenkins 종료

docker stop jenkins
docker rm jenkins

정상적으로 컨테이너가 실행되었는지 확인하기 위해, netstat 명령어를 활용하여 포트가 개방되어 있는지 확인한다

netstat -nltp

Jenkins 접속

다음 명령어를 활용하여 컨테이너의 bash 쉘에 접속한다

docker exec -it jenkins /bin/bash

해당하는 디렉토리로 이동한다

cd /var/jenkins_home/secrets

cat 명령어를 이용하여 초기 비밀번호를 확인한다. 이후 exit을 하여 컨테이너의 bash 쉘에서 나가 Host OS의 쉘로 복귀한다. 방금 확인한 관리자 비밀번호를 웹에 입력한다.

cat initialAdminPassword

Jenkins 내부에 Docker 패키지 설치

Jenkins 컨테이너 접속

docker exec -it jenkins /bin/bash

Docker Repository 등록 및 docker-ce 패키지 설치

apt-get update && apt-get -y install apt-transport-https ca-certificates curl gnupg2 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
apt-get update && apt-get -y install apt-transport-https ca-certificates curl gnupg2 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=arm64] <https://download.docker.com/linux/$>(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable" && apt-get update && apt-get -y install docker-ce

Docker Jenkins에서 Host Docker 접근권한 부여

groupadd -f docker
usermod -aG docker jenkins
chown root:docker /var/run/docker.sock

Jenkins 내부에 Docker-Compose 설치

Jenkins 컨테이너 접속

docker exec -it jenkins /bin/bash

Docker Compose 다운로드

curl 명령을 이용하여 docker-compose 패키지를 /usr/local/bin/docker-compose 디렉토리에 다운로드 한다

curl -L "<https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$>(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

/usr/local/bin/docker-compose 권한 변경

chmod를 이용하여 /usr/local/bin/docker-compose 디렉토리에 대해 jenkins 사용자에게 실행 권한을 추가시킨다

chmod +x /usr/local/bin/docker-compose

Jenkins 파이프라인 설정 (공통)

플러그인 설치 목록

# ssh 커맨드 입력에 사용
SSH Agent

# docker 이미지 생성에 사용
Docker
Docker Commons
Docker Pipeline
Docker API

# 웹훅을 통해 브랜치 merge request 이벤트 발생시 Jenkins 자동 빌드에 사용
Generic Webhook Trigger

# 타사 레포지토리 이용시 사용 (GitLab, Github 등)
GitLab
GitLab API
GitLab Authentication
GitHub Authentication

# Node.js 빌드시 사용
NodeJS

Jenkins 파이프라인 설정

Pipeline script 작성 예시

pipeline {
    agent any
    
    environment {
        imageName = "계정/이미지 이름"
        registryCredential = 'Credential 이름'
        dockerImage = ''
        
        releaseServerAccount = 'ubuntu'
        releaseServerUri = '서버 uri'
        releasePort = '포트 번호'
    }

    stages {
        stage('Git Clone') {
            steps {
                git branch: '브랜치 이름',
                    credentialsId: 'Credential 이름',
                    url: '<https://서버 uri>'
            }
        }
        stage('Jar Build') {
            steps {
                dir ('디렉토리 명') {
                    sh 'chmod +x ./gradlew'
                    sh './gradlew clean bootJar'
                    // sh './gradlew build'
                }
            }
        }
        stage('Image Build & DockerHub Push') {
            steps {
                dir('디렉토리 명') {
                    script {
                        docker.withRegistry('', registryCredential) {
                            sh "docker buildx create --use --name mybuilder"
                            sh "docker buildx build --platform linux/amd64,linux/arm64 -t $imageName:$BUILD_NUMBER --push ."
                            sh "docker buildx build --platform linux/amd64,linux/arm64 -t $imageName:latest --push ."
                        }
                    }
                }
            }
        }
        stage('Before Service Stop') {
            steps {
                sshagent(credentials: ['Credential 이름']) {
                    sh '''
                    if test "`ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker ps -aq --filter ancestor=$imageName:latest"`"; then
                    ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker stop $(docker ps -aq --filter ancestor=$imageName:latest)"
                    ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker rm -f $(docker ps -aq --filter ancestor=$imageName:latest)"
                    ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker rmi $imageName:latest"
                    fi
                    '''
                }
            }
        }
        stage('DockerHub Pull') {
            steps {
                sshagent(credentials: ['Credential 이름']) {
                    sh "ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri 'sudo docker pull $imageName:latest'"
                }
            }
        }
        stage('Service Start') {
            steps {
                sshagent(credentials: ['Credential 이름']) {
                    sh '''
                        ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "sudo docker run -i -e TZ=Asia/Seoul -e "SPRING_PROFILES_ACTIVE=prod" --name 컨테이너 명 -p $releasePort:$releasePort -d $imageName:latest"
                    '''
                }
            }
        }
    }
}

Dockerfile 작성예시

FROM docker
COPY --from=docker/buildx-bin:latest /buildx /usr/libexec/docker/cli-plugins/docker-buildx

FROM openjdk:17-jdk
EXPOSE 443
ADD ./build/libs/doha-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]