Jenkins로 GitLab CI/CD 구성하기

오젼·2026년 2월 12일

이번에 Jenkins를 처음 써보면서 구축한 내용을 정리해보려 합니다.

0. Jenkinsfile 작성

Jenkinsfile 구성에 대한 내용은 별도의 글로 정리되어 있습니다.

이 글을 참고해주세요
👉 Jenkinsfile로 구성한 Docker 기반 CI/CD 파이프라인

1. Jenkins 컨테이너 띄우기

먼저 Jenkins 서버를 띄워야 합니다. Jenkins는 보통 Docker 컨테이너 형태로 실행합니다.

Jenkins는 Self-hosted CI/CD 서버이기 때문에, GitHub Actions와 같은 Managed CI/CD 서비스와 달리 별도의 서버(예: EC2)에 직접 설치하여 운영해야 합니다.

설치에 사용한 docker-compose 설정과 Dockerfile 설정입니다.

docker-compose.yml (Jenkins)

jenkins:
    build:
      context: .
      dockerfile: ./jenkins/Dockerfile
    container_name: jenkins
    user: root
    networks:
      - app_net
    environment:
      - TZ=Asia/Seoul
    volumes:
      - jenkins_data:/var/jenkins_home
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped
    
    
 volumes:
  jenkins_data:

Jenkins의 로그 및 빌드 시간을 한국 시간 기준으로 확인하기 위해 타임존을 Asia/Seoul로 설정하였습니다.

또한 Jenkins 파이프라인에서 Docker 이미지를 빌드하고 Docker Hub에 푸시하기 위해, 컨테이너 내부에서 호스트의 Docker 데몬을 사용할 수 있도록 /var/run/docker.sock을 마운트하였습니다.

아울러 Jenkins 컨테이너 재시작 시에도 환경이 유지되도록 jenkins_data 볼륨을 사용하여 설정, 파이프라인, Credential, 플러그인 정보를 영속화하였습니다.

Dockerfile

FROM jenkins/jenkins:lts

USER root

RUN apt-get update \
 && apt-get install -y ca-certificates curl gnupg lsb-release \
 && install -m 0755 -d /etc/apt/keyrings \
 && curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \
 && chmod a+r /etc/apt/keyrings/docker.asc \
 && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" \
    > /etc/apt/sources.list.d/docker.list \
 && apt-get update \
 && apt-get install -y docker-ce-cli \
 && rm -rf /var/lib/apt/lists/*

USER jenkins

Jenkins 파이프라인에서 Docker 이미지를 직접 빌드하고 Docker Hub에 푸시하기 위해, 기본 Jenkins 이미지에 Docker CLI(docker-ce-cli)를 추가로 설치한 커스텀 이미지를 사용했습니다.

Docker 데몬은 컨테이너 내부에 별도로 띄우지 않고, docker.sock 마운트를 통해 호스트의 Docker 데몬을 공유하는 방식을 사용했습니다.

2. Jenkins 초기설정

Jenkins 컨테이너를 띄웠다면 초기 설정이 필요합니다.

먼저 실행 중인 Jenkins 컨테이너에 브라우저로 접속합니다.

Jenkins 초기 화면에서는 관리자 계정 생성을 위해
초기 관리자 비밀번호(Initial Admin Password) 입력을 요구합니다.

초기 관리자 비밀번호는 Jenkins 컨테이너 내부에 생성되며,
docker exec를 통해 컨테이너에 접근한 후 cat 명령어로 확인할 수 있습니다.

비밀번호 입력 후에는 Jenkins에서 권장하는 기본 플러그인(Suggested Plugins)을 설치합니다.

플러그인 설치가 완료되면 Jenkins 관리자 계정 생성 화면이 나타납니다.

관리자 계정 생성이 완료되면, Jenkins URL을 설정하는 화면이 나타납니다.

Jenkins가 외부 시스템과 연동할 때 사용하는 기준 URL로,
이메일 알림, 빌드 결과 링크, Webhook 응답, PR 상태 체크 등에 포함되는 링크에 사용됩니다.

특히 GitLab Branch Source 플러그인을 사용하는 경우,
Jenkins URL이 localhost로 설정되어 있으면 Webhook 자동 등록 과정에서 오류가 발생하므로,
외부에서 접속할 수 있는 도메인으로 바꿔줍니다.

해당 단계에서 값을 잘못 설정하더라도, 이후 Jenkins 설정 화면에서 수정할 수 있습니다.

3. Jenkins 파이프라인 생성

설정이 완료되면 다음과 같은 화면이 나옵니다.

사진으로만 뵀던 신사분이 보입니다.

그 아래 + 새로운 Item을 클릭하면 다음과 같은 화면이 나옵니다.

Pipeline, Freestyle project, Multibranch Pipeline
Jenkins에서 제공하는 다양한 Job 타입 중 하나를 선택할 수 있습니다.

세세한 타입 설명은 넘어가도록 하고, PipelineMultibranch Pipeline에 대해 설명하도록 하겠습니다.


1. Pipeline

Pipeline은 Jenkins에서 가장 기본적인 파이프라인 타입으로,
Jenkinsfile을 기반으로 빌드, 테스트, 배포 과정을 코드로 정의할 수 있습니다.

일반적으로 단일 브랜치를 기준으로 CI/CD를 구성할 때 사용하며,
특정 브랜치(main, develop 등)에 대해서만 파이프라인을 실행하도록 설정하는 경우에 적합합니다.

즉, 하나의 브랜치에 대해 하나의 파이프라인을 구성하는 구조입니다.

2. Multibranch Pipeline

Multibranch Pipeline은 하나의 Git 저장소 내 여러 브랜치를 자동으로 감지하여,
브랜치별로 독립적인 Pipeline을 생성하는 타입입니다.

저장소를 스캔하여 각 브랜치의 Jenkinsfile을 읽고,
브랜치마다 개별 Job을 생성해 자동으로 빌드를 수행합니다.

특히 다음과 같은 구조에서 유용합니다.

  • Merge Request(또는 Pull Request) 단위 CI 수행
  • develop/main 브랜치 기준 CD 수행
  • 브랜치별 독립적인 빌드 이력 관리

이번 프로젝트에서는
Merge Request 단계에서는 소스 브랜치 기준으로 CI를 수행하고,
merge 이후에는 develop 브랜치 기준으로 CI/CD를 수행하기 위해
Multibranch Pipeline을 선택하였습니다.

4. GitLab 연결을 위한 Jenkins 설정

4-1. GitLab Branch Source 플러그인 설치

파이프라인 소스(Branch Source)를 설정해야 하는데,
기본 상태에서는 Git, GitHub, Single repository & branch만 선택할 수 있습니다.

GitLab 저장소를 Multibranch Pipeline과 연동하기 위해서는
추가 플러그인 설치가 필요합니다.

관리(우측 상단 ⚙️)Plugins를 클릭하고 GitLab Branch Source 플러그인을 설치해줍니다.

4-2. GitLab Branch Source 활성화 확인

설치 후 돌아오면 Branch Source 목록에 GitLab 항목이 추가되어 있습니다.

그런데 기본적으론 gitlab.com을 가리키는 Default 서버만 등록되어 있습니다.
회사나 조직에서 자체 GitLab 서버를 사용하는 경우에는 해당 GitLab 도메인을 추가로 등록해야 합니다.

4-3. GitLab 서버 추가 (Configure System)

관리(우측 상단 ⚙️)SystemGitLab에 들어가 새로운 깃랩 서버를 추가해줍니다. 이때 해당 깃랩에 접근할 수 있는 access token이 필요합니다.

4-4. GitLab Access Token 발급

저의 경우 Group access token을 발급해줬습니다.

4-5. GitLab 서버 연결 테스트 및 Webhook 설정

토큰을 적용하고 Test connection을 해보면 잘 되는 것을 확인할 수 있습니다.

또한 GitLab에서 이벤트가 발생할 때 Jenkins가 자동으로 파이프라인을 실행할 수 있도록
Manage Web Hooks 옵션을 활성화한 뒤 Apply를 눌러 설정을 저장합니다.

5. Multibranch Pipeline 설정

5-1. Multibranch Pipeline에 GitLab 프로젝트 연결

다시 파이프라인 설정 화면에 돌아와보면, 추가한 서버를 목록에서 선택할 수 있게 됩니다.

이제 Owner를 입력하고 프로젝트를 선택합니다. Owner에는 GitLab 사용자명 또는 Group 경로를 입력합니다.

저의 경우 프로젝트가 Group 단위로 관리되고 있었기 때문에 Group 이름을 입력했습니다.

이후 나머지 설정은 기본값에서 바꿀 게 없습니다. 그래도 이해를 위해 각 항목을 간단히 정리하겠습니다.

5-2. Branch / Merge Request 감지(Discover) 설정 = 대상 선정 (WHAT)

Behaviours는 Multibranch Pipeline이 어떤 브랜치와 Merge Request를 빌드 대상으로 삼을지 설정하는 영역입니다.

1) Discover branches

  • Only branches that are not also filed as MRs
    • 이미 MR로 올라간 브랜치는 “브랜치 빌드” 대상에서 제외하고,
    • MR 빌드로만 관리하도록 설정합니다.
    • 즉, 동일한 커밋에 대해 브랜치 빌드와 MR 빌드가 중복 실행되는 것을 방지할 수 있습니다.

2) Discover merge requests from origin

  • Merging the merge request with the current target branch revision
    • MR 소스 브랜치만 빌드하는 것이 아니라,
    • 대상 브랜치(예: develop)의 최신 커밋과 merge된 결과를 기준으로 빌드합니다.
    • 실제 merge 시점에서 발생할 수 있는 충돌/빌드 실패를 미리 검증할 수 있습니다.

3) Discover merge requests from forks

  • Merging the merge request with the current target branch revision
    • fork 저장소에서 올라오는 MR도 동일한 방식으로 빌드하도록 설정합니다.
    • (팀 내부 프로젝트에서 fork를 사용하지 않는다면 이 옵션은 생략해도 됩니다.)

4) Trust 설정

  • Trusted Members
    • 신뢰할 수 있는 멤버(Developer/Maintainer/Owner 등)가 생성한 MR에 대해서만 빌드를 수행하도록 제한합니다.
    • 외부 기여자의 MR로 인해 Jenkins에서 임의 코드가 실행되는 위험을 줄일 수 있습니다.

5-3. Merge Request 이벤트 기반 빌드 트리거 설정 = 실행 시점 (WHEN)

Multibranch Pipeline에서 GitLab Webhook 이벤트에 따라
언제 빌드를 실행할지 세부 조건을 설정합니다.

  • Always build pipeline on Open MR webhook

    • Merge Request가 처음 생성될 때마다 파이프라인을 실행합니다.
    • 새로운 MR에 대해 즉시 CI를 수행하기 위한 설정입니다.
  • Always build pipeline on Re-Open MR webhook

    • 닫혔던 Merge Request가 다시 열릴 경우에도 파이프라인을 실행합니다.
    • 수정 후 다시 검증이 필요한 상황을 고려한 설정입니다.

5-4. Build Configuration 설정

Jenkinsfile이 위치한 저장소 경로를 지정합니다.
젠킨스에서 해당 경로를 기준으로 Jenkinsfile을 탐색해 빌드를 수행합니다.

6. 깃랩 webhook 설정

깃랩에서 발생한 이벤트를 자동으로 감지하기 위해선 webhook 설정이 필요합니다.

깃랩 프로젝트 settings -> webhooks에서 https://젠킨스 도메인/gitlab-webhook/post
를 추가해줍니다.

필요한 권한을 알맞게 설정해줍니다.

7. 추가 플러그인 설치

설정을 적용하면 멀티브랜치 파이프라인이 자동으로 실행됩니다.

하지만 빌드 과정에서 오류가 발생합니다. 로그를 보니 Jenkins가 docker agent 문법을 인식하지 못했습니다.

이는 Jenkins에 Docker Pipeline 플러그인이 설치되어 있지 않아
파이프라인에서 Docker agent를 사용할 수 없기 때문입니다.

다시 Docker Pipeline 플러그인을 설치합니다.

SSH Agent 플러그인도 필요해서 설치해줍니다.

8. Credentials 설정

필요한 Credentials도 설정해줍니다.

9. 마무리

모두 잘 됩니다.

이렇게
Merge Request 단위 CI와 develop 브랜치 기준 CI/CD가 자동으로 동작하는
Jenkins 기반 파이프라인을 구성해봤습니다.

Jenkins 설정 과정은 항목이 많고 복잡해 보일 수 있습니다.
하지만 한 번 구조를 잡아두면,
여러 프로젝트와 브랜치의 CI/CD 흐름을 한 곳에서 관리할 수 있다는 장점이 있습니다.

이번 경험을 통해
Self-hosted CI/CD 환경의 구성 방식과
Jenkins Multibranch Pipeline의 동작 흐름을 정리할 수 있었습니다.

0개의 댓글