CICD/Jenkins

Jenkins CI/CD 구축

Red_Horse 2025. 10. 17. 00:43

이 가이드는 Ubuntu 22.04 환경에서 Jenkins를 설치하고, .NET 프로젝트의 CI/CD 파이프라인을 구축하는 전 과정을 다룹니다. 

 

1. 환경 준비 및 기본 설정

1.1 시스템 업데이트

sudo apt update && sudo apt upgrade -y

 

1.2 SSH 서버 설정 (원격 접속용)

# SSH 서버 설치
sudo apt install openssh-server -y

# SSH 서비스 시작 및 자동 시작 설정
sudo systemctl start ssh
sudo systemctl enable ssh

# SSH 서비스 상태 확인
sudo systemctl status ssh

 

1.3 방화벽 설정

# UFW 방화벽 활성화
sudo ufw enable

# SSH 포트 허용 (기본 22번 포트)
sudo ufw allow 22/tcp

# Jenkins 웹 포트 허용 (8080)
sudo ufw allow 8080/tcp

# 애플리케이션 포트 허용 (예: 5117)
sudo ufw allow 5117/tcp

# 방화벽 상태 확인
sudo ufw status

⋇iptime에서 지원하는 DDNS 기능을 사용할 경우 포트포워딩을 별도로 설정해 주어야합니다.

 

2. Jenkins 설치 및 초기 설정

2.1 Java 설치 (Jenkins 필수 요구사항)

# OpenJDK 17 설치
sudo apt install openjdk-17-jdk -y

# Java 버전 확인
java -version

# JAVA_HOME 환경변수 설정
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' >> ~/.bashrc
echo 'export PATH=$PATH:$JAVA_HOME/bin' >> ~/.bashrc
source ~/.bashrc

 

2.2 Jenkins 저장소 추가 및 설치

 

단계 1: Jenkins GPG 키 다운로드 및 추가

# Jenkins 공식 보안 키를 다운로드하여 시스템에 추가
curl -fsSL https://pkg.jenkins.io/debian/jenkins.io-2023.key | sudo tee /usr/share/keyrings/jenkins-keyring.asc > /dev/null

GPG 키? 패키지가 진짜 Jenkins에서 만든 것인지 확인하는 디지털 서명입니다. 가짜 패키지 설치를 방지하기 위함.

 

명령어 설명:

  • curl -fsSL: Jenkins 웹사이트에서 보안 키 파일을 다운로드
  • sudo tee: 다운로드한 키를 시스템 보안 키 저장소에 저장
  • /usr/share/keyrings/: Ubuntu에서 패키지 보안 키를 저장하는 표준 위치

단계 2: Jenkins 저장소를 시스템에 추가

# Jenkins 패키지 저장소를 APT 소스 목록에 추가
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian binary/" | sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null

 

단계 3: 패키지 목록 업데이트

# 새로 추가된 Jenkins 저장소를 포함하여 패키지 목록 업데이트
sudo apt update

 

단계 4: Jenkins 설치

# Jenkins 패키지 설치
sudo apt install jenkins -y

 

단계 5: Jenkins 서비스 설정

# Jenkins 서비스 시작
sudo systemctl start jenkins

# 시스템 부팅 시 Jenkins 자동 시작 설정
sudo systemctl enable jenkins

# Jenkins 서비스 상태 확인
sudo systemctl status jenkins

 

설치 성공 확인:

  • sudo systemctl status jenkins 명령어 실행 시 Active: active (running) 상태여야 함
  • 만약 실패했다면 sudo journalctl -u jenkins로 로그 확인

2.3 Jenkins 초기 설정

# Jenkins 초기 관리자 비밀번호 확인
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

 

웹 브라우저에서 http://[서버IP]:8080에 접속하여:

  1. 위에서 확인한 초기 비밀번호 입력
  2. "Install suggested plugins" 선택 (권장)
  3. 관리자 계정 생성
  4. Jenkins URL 설정

 

3. .NET 개발 환경 구축

3.1 .NET SDK 설치

# Microsoft 패키지 저장소 추가
wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

# .NET SDK 설치
sudo apt update
sudo apt install -y dotnet-sdk-8.0

# 설치 확인
dotnet --version

 

3.2 Git 설정

# Git 설치 (보통 이미 설치되어 있음)
sudo apt install git -y

# Git 사용자 정보 설정 (사용자)
sudo -u jenkins git config --global user.name "사용자 이름"
sudo -u jenkins git config --global user.email "이메일"

 

4. systemd 서비스 설정

4.1 애플리케이션용 systemd 서비스 생성

#.Net 서비스 파일 생성
sudo nano /etc/systemd/system/{프로젝트명}.service

 

서비스 파일 내용

[Unit]
Description="프로젝트명" Service
After=network.target

[Service]
Type=simple
User=jenkins
Group=jenkins
#WorkingDirectory=/var/lib/jenkins/deployments/프로젝트명
WorkingDirectory="프로젝트 빌드파일 위치"

# 환경변수
Environment=ASPNETCORE_ENVIRONMENT=Development
Environment=ASPNETCORE_URLS=http://0.0.0.0:5117

#ExecStart=/usr/bin/dotnet 프로젝트.dll
ExecStart="프로젝트 실행파일(.dll)"

Restart=always
RestartSec=5
KillMode=mixed
KillSignal=SIGINT

[Install]
WantedBy=multi-user.target

 

4.2 환경변수 파일 생성 (민감한 정보 보호)

# 환경변수 디렉토리 생성
sudo mkdir -p /etc/fitness-api

# 환경변수 파일 생성
sudo nano /etc/fitness-api/environment

 

환경변수 파일 내용 예시:

# 데이터베이스 연결 문자열
ConnectionStrings__DefaultConnection=Server=localhost;Database=FitnessDB;User=dbuser;Password=your_secure_password;

# JWT 설정
JwtSettings__SecretKey=your_jwt_secret_key_here
JwtSettings__Issuer=Issuer
JwtSettings__Audience=Audience
JwtSettings__ExpiryMinutes=1440

# API 키들
ExternalApi__GoogleMaps=your_google_maps_api_key
ExternalApi__Payment=your_payment_gateway_key

# 로깅 설정
Serilog__MinimumLevel=Information

 

4.3 서비스 권한 설정 및 등록

# 환경변수 파일 권한 설정 (보안 강화)
sudo chown root:jenkins /etc/프로젝트 경로/environment
sudo chmod 640 /etc/프로젝트 경로/environment

# 배포 디렉토리 생성 및 권한 설정
sudo mkdir -p /var/lib/jenkins/deployments/프로젝트 폴더
sudo chown -R jenkins:jenkins /var/lib/jenkins/deployments

# systemd 서비스 등록
sudo systemctl daemon-reload
sudo systemctl enable 프로젝트명.service

 

5. Jenkins Job 생성 및 배포 스크립트

5.1 Jenkins Job 생성

 

사전 준비: Git 인증 정보 설정

Private repository이거나 Push 권한이 필요한 경우 반드시 인증 정보를 설정해야 합니다.

 

GitHub Personal Access Token 사용 (권장)

  1. GitHub에서 토큰 생성:
    • GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
    • "Generate new token" 클릭
    • 권한 선택: repo (전체 저장소 접근) 체크
    • 토큰 복사 (한 번만 보여줌으로 별도의 메모장에 작성해두고 사용하길 권장합니다.)
  2. Jenkins에 인증 정보 추가:
    • Jenkins 관리 → Manage Credentials → System → Global credentials
    • "Add Credentials" 클릭
    • Kind: "Username with password" 선택
    • Username: GitHub 사용자명
    • Password: 위에서 생성한 Personal Access Token 입력
    • ID: github-credentials (기억하기 쉬운 이름)
    • Description: GitHub Personal Access Token
  1.  

Jenkins Job 생성 단계:

  1. Jenkins 대시보드 → "새 항목"
  2. 항목 이름: FitnessPT_API_Deploy
  3. "Freestyle project" 선택
  4. "소스 코드 관리" → Git 선택
    • Repository URL:
      • HTTPS 방식: 깃 레포주소
    • Credentials: 위에서 생성한 인증 정보 선택
    • Branch: */main

연결 테스트:

  • Repository URL과 Credentials 설정 후 "Test Connection" 버튼 클릭
  • 성공 시: "Credentials verified for user [username], repository [repo-name]"
  • 실패 시: 인증 정보나 URL 확인 필요

5.2 배포 스크립트 생성

Jenkins Execute Shell에 입력할 스크립트

#!/bin/bash

echo "🚀 자동배포를 시작합니다..."

# ================================================================
# 🎯 프로젝트 설정
# ================================================================
PROJECT_NAME="프로젝트명"
SERVICE_NAME=".Service 이름"
APP_PORT="5117"
BUILD_CONFIG="Release"
DEPLOY_PATH="/var/lib/jenkins/deployments/$PROJECT_NAME"

# 색상 정의 (가독성 향상)
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m'

# ================================================================
# 🛠️ 배포 프로세스
# ================================================================

echo -e "${YELLOW}📋 배포 설정:${NC}"
echo "  • 프로젝트: $PROJECT_NAME"
echo "  • 서비스명: $SERVICE_NAME"
echo "  • 포트: $APP_PORT"
echo "  • 빌드 구성: $BUILD_CONFIG"
echo "  • 배포 경로: $DEPLOY_PATH"
echo ""

# 1. 기존 서비스 중지
echo -e "${YELLOW}🛑 기존 서비스 중지 중...${NC}"
sudo systemctl stop $SERVICE_NAME || echo "서비스가 실행 중이 아닙니다."

# 2. 이전 배포 파일 백업 (선택사항)
if [ -d "$DEPLOY_PATH" ]; then
    echo -e "${YELLOW}📦 이전 배포 파일 백업 중...${NC}"
    sudo cp -r $DEPLOY_PATH ${DEPLOY_PATH}_backup_$(date +%Y%m%d_%H%M%S) || true
fi

# 3. 배포 디렉토리 생성/정리
echo -e "${YELLOW}📁 배포 디렉토리 준비 중...${NC}"
sudo mkdir -p $DEPLOY_PATH
sudo rm -rf $DEPLOY_PATH/*

# 4. .NET 프로젝트 빌드
echo -e "${YELLOW}🔨 .NET 프로젝트 빌드 중...${NC}"
dotnet clean
dotnet restore
dotnet publish -c $BUILD_CONFIG -o $DEPLOY_PATH --no-restore

if [ $? -ne 0 ]; then
    echo -e "${RED}❌ 빌드 실패!${NC}"
    exit 1
fi

# 5. 파일 권한 설정
echo -e "${YELLOW}🔐 파일 권한 설정 중...${NC}"
sudo chown -R jenkins:jenkins $DEPLOY_PATH
sudo chmod +x $DEPLOY_PATH/$PROJECT_NAME

# 6. 서비스 시작
echo -e "${YELLOW}🚀 서비스 시작 중...${NC}"
sudo systemctl start $SERVICE_NAME

# 7. 서비스 상태 확인
sleep 5
SERVICE_STATUS=$(sudo systemctl is-active $SERVICE_NAME)

if [ "$SERVICE_STATUS" = "active" ]; then
    echo -e "${GREEN}✅ 서비스가 성공적으로 시작되었습니다!${NC}"
    
    # 헬스체크
    echo -e "${YELLOW}🔍 헬스체크 진행 중...${NC}"
    sleep 10
    
    if curl -f http://localhost:$APP_PORT/health > /dev/null 2>&1; then
        echo -e "${GREEN}✅ 헬스체크 성공!${NC}"
    else
        echo -e "${YELLOW}⚠️  헬스체크 실패 (서비스는 실행 중)${NC}"
    fi
    
    # 최종 결과 출력
    echo ""
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo -e "${GREEN}🎉 배포 완료!${NC}"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "프로젝트: $PROJECT_NAME"
    echo "포트: $APP_PORT"
    echo "URL: http://localhost:$APP_PORT"
    echo "배포 위치: $DEPLOY_PATH"
    echo "로그 확인: sudo journalctl -u $SERVICE_NAME -f"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
    
    # 실행 중인 프로세스 정보
    echo "실행 중인 프로세스:"
    ps aux | grep "$PROJECT_NAME" | grep -v grep || echo "프로세스 정보 조회 실패"
    
else
    echo -e "${RED}❌ 서비스 시작 실패!${NC}"
    echo "서비스 로그 확인:"
    sudo journalctl -u $SERVICE_NAME --no-pager -l
    exit 1
fi

echo -e "${GREEN}✅ 모든 작업 완료!${NC}"

 


빌드 스크립트의 경우 프로젝트의 설정마다 일부 차이가 있을 수 있습니다.
기본적인 .NET 프로젝트 기준으로 작성된 스크립트로서 빌드 오류가 발생시 프로젝트에 맞추어 수정이 필요할 수 있습니다.

 

6. 보안 설정 및 환경변수 관리

6.1 Jenkins 사용자 sudo 권한 설정

# Jenkins 사용자에게 특정 명령어만 sudo 권한 부여
sudo visudo

 

다음 내용 추가

# Jenkins가 서비스 관리만 할 수 있도록 제한
jenkins ALL=(ALL) NOPASSWD: /bin/systemctl start 프로젝트명, /bin/systemctl stop 프로젝트명, /bin/systemctl restart 프로젝트명, /bin/systemctl status 프로젝트명, /bin/journalctl -u 프로젝트명*

 

6.2 환경변수 보안 관리

# 환경변수 파일 암호화 (선택사항)
sudo apt install gpg -y

# 환경변수 파일 백업
sudo cp /etc/프로젝트명/environment /etc/프로젝트명/environment.backup

# 권한 재확인
sudo ls -la /etc/프로젝트명/

 

7. 트러블슈팅 및 모니터링

7.1 로그 모니터링

# Jenkins 로그 확인
sudo journalctl -u jenkins -f

# 애플리케이션 로그 확인
sudo journalctl -u 프로젝트명 -f

# 시스템 로그 확인
sudo tail -f /var/log/syslog

 

7.2 포트 및 프로세스 확인

# 포트 사용 현황 확인
sudo netstat -tulpn | grep :5117

# 실행 중인 프로세스 확인
ps aux | grep 프로젝트명

# 서비스 상태 확인
sudo systemctl status 프로젝트명

 

7.3 일반적인 문제 해결

문제 1: 빌드 실패

# .NET SDK 버전 확인
dotnet --version

# 프로젝트 의존성 복원
dotnet restore --force

# 캐시 정리
dotnet clean

 

문제 2: 서비스 시작 실패

# 서비스 로그 상세 확인
sudo journalctl -u 프로젝트명 -n 50

# 환경변수 파일 문법 검사
sudo systemd-analyze verify /etc/systemd/system/프로젝트명.service

# 권한 문제 해결
sudo chown -R jenkins:jenkins /var/lib/jenkins/deployments

 

문제 3: 포트 충돌

# 포트를 사용하는 프로세스 찾기
sudo lsof -i :{프로젝트 내부 포트}

# 해당 프로세스 종료
sudo kill -9 [PID]

 

마무리 및 추가 개선사항

완성된 CI/CD 파이프라인의 특징

  • 자동화: Git 푸시 → 자동 빌드 → 자동 배포
  • 보안: 환경변수로 민감 정보 보호
  • 안정성: systemd 서비스로 프로세스 관리
  • 모니터링: 상세한 로깅 및 헬스체크
  • 확장성: 다른 프로젝트에도 쉽게 적용 가능

 

세팅 이후 내용을 정리한 가이드로서 진행중 이슈가 있을 수 있습니다.

도움이 필요한 부분은 댓글을 남겨주시면 내용 수정 및 추가 가이드 안내 드리겠습니다.