2024.10.05 - [데브옵스/CICD] - [Docker] Jenkins와 GitHub 연동하기: 지속적 통합(Continuous Integration, CI)
[Docker] Jenkins와 GitHub 연동하기: 지속적 통합(Continuous Integration, CI)
2024.10.04 - [데브옵스/CICD] - Docker로 Jenkins 설치하기: 단계별 가이드1. 들어가며지속적 통합(Continuous Integration, CI)은 현대 소프트웨어 개발에서 필수적인 프로세스입니다. CI를 통해 개발자들은 코
bigdwarf.blog
1. 들어가며
Jenkins를 활용해 CI/CD 파이프라인을 구축할 때 Docker 이미지 빌드가 필요한 상황이 자주 발생합니다. 일반적인 환경에서는 Jenkins 사용자에게 Docker 권한을 부여하는 것으로 충분하지만, Jenkins를 Docker 컨테이너로 실행하는 경우에는 호스트의 Docker 데몬을 사용해야 하는 특수한 설정이 필요합니다.
이 글에서는 Jenkins 컨테이너 내부에서 Docker를 설치하고, Docker 소켓을 공유하여 호스트의 Docker를 사용하는 방법을 다룹니다. 이는 컨테이너 내부에서 별도로 Docker 데몬을 실행하는 방법보다 안전하고 효율적인 방식입니다.
2. Docker와 Jenkins의 연동 개요
Jenkins와 Docker를 연동하여 CD 파이프라인을 구축하려면 Jenkins가 Docker 명령어를 실행할 수 있어야 합니다. 이를 위한 두 가지 방법이 있습니다.
- Docker 소켓 공유: 호스트의 Docker 소켓을 Jenkins 컨테이너와 공유하여 Jenkins가 Docker 명령을 실행할 수 있게 합니다. (권장)
- 컨테이너 내부에 Docker 설치: Jenkins 컨테이너에 별도로 Docker를 설치하여 자체 데몬을 실행하는 방법 (비권장)
이 글에서는 첫 번째 방법을 다루며, Docker 소켓 공유 설정에 대해 설명합니다.
2.1 Docker 소켓 공유란?
컨테이너는 기본적으로 호스트 시스템의 Docker 데몬에 접근할 수 없습니다. 따라서 Jenkins가 Docker 명령을 실행하려면 호스트의 Docker 소켓을 공유하여 Jenkins 컨테이너가 호스트에서 Docker 명령어를 실행할 수 있게 해야 합니다. 하지만 보안적인 고려가 필요하며, 이를 잘못 설정할 경우 시스템에 위험을 초래할 수 있습니다.
2.2 Docker 소켓 공유 설정
Docker 소켓을 Jenkins 컨테이너에 마운트하려면 아래와 같이 설정합니다.
Docker 소켓을 Jenkins 컨테이너에 마운트하여 Jenkins가 호스트의 Docker 데몬에 접근할 수 있게 합니다. 이를 위해 Jenkins 컨테이너를 실행할 때 아래와 같이 /var/run/docker.sock
파일을 마운트합니다.
- Docker 명령어 방식
docker run -d -p 8080:8080 -p 50000:50000 \
-v /home/junu/docker_data/jenkins:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \ # 소켓 마운트
--name jenkins jenkins/jenkins:lts
- Docker Compose 방식
version: '3.9'
services:
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins # 컨테이너 이름을 명시적으로 표시하기 위해 추가
ports:
- "8080:8080"
- "50000:50000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock # 소켓 마운트
- /home/junu/docker_data/jenkins:/var/jenkins_home
networks: {}
2.3 Docker 소켓 공유 권한 문제
/var/run/docker.sock
의 permission denied 발생했을 경우
/var/run/docker.sock
파일의 권한을 666으로 변경하여 그룹 내 다른 사용자도 접근 가능하게 변경
sudo chmod 666 /var/run/docker.sock
- 또는 chown 으로 docker group 변경
chown root:docker /var/run/docker.sock
3. Docker Engine 설치: Jenkins 컨테이너 내부에서 Docker 설치하기
3.1 Jenkins 컨테이너 내부에 직접 Docker 설치
Docker 컨테이너 내부에 별도로 Docker를 설치하기전 컨테이너 내 리눅스 환경 확인이 필요합니다. 이글에서 설치한 Jenkins 컨테이너는 Debian 계열의 리눅스로 이미지가 만들어져있습니다. 컨테이너 내에 Debian 패키지 관리자를 사용하여 Docker를 설치해야 합니다. Docker 공식 문서에서 제공하는 Install Docker Engine on Debian 가이드를 참고 또는 아래 명령어를 입력해 설치를 진행합니다.
- jenkins 컨테이너 내부 root로 접속
docker exec -it --user root jenkins /bin/bash
- Docker apt저장소를 설정합니다.
# Add Docker's official GPG key:
apt-get update
apt-get install ca-certificates curl
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
# Add the repository to Apt sources:
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" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
- Docker 패키지를 설치합니다.
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- Docker Compose 설치 (선택사항)
- docker-compose 사용 시 설치 필요
# Docker Compose 설치
curl -L "https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'tag_name' | cut -d '"' -f 4)/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
- 이미지를 실행하여 설치가 성공적으로 완료되었는지 확인하세요.
docker run hello-world
3.2 Dockerfile를 활용하여 Jenkins 컨테이너 내 Docker 설치하기
Dockerfile을 이용한 Docker 명령어로 Jenkins 컨테이너 내 Docker 설치
- Dockerfile 작성 및 저장
# Jenkins LTS 이미지를 베이스로 사용
FROM jenkins/jenkins:lts
USER root
# 필요한 패키지 설치 및 Docker 저장소 추가
RUN apt-get update && \
apt-get -y install apt-transport-https ca-certificates curl gnupg2 && \
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(grep VERSION_CODENAME /etc/os-release | cut -d'=' -f2) stable" > /etc/apt/sources.list.d/docker.list && \
apt-get update && \
apt-get -y install docker-ce-cli
# Docker Compose 설치
RUN curl -L "https://github.com/docker/compose/releases/download/v2.21.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose
USER jenkins
- 이미지 빌드 및 실행
docker build -t jenkins-with-docker .
docker run -d -p 8080:8080 -p 50000:50000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /home/junu/docker_data/jenkins:/var/jenkins_home \
--name jenkins jenkins-with-docker
- Dockerfile을 사용해 Docker CLI가 미리 설치된 Jenkins 이미지를 빌드한 후, 이를 Docker 명령어로 실행하여 Jenkins와 Docker를 함께 사용하는 환경을 구축합니다.
Dockerfile을 이용한 Docker Compose로 Jenkins 컨테이너 내 Docker 설치
Dockerfile과 Docker Compose를 함께 사용해 Docker CLI가 설치된 Jenkins 이미지를 빌드하고 관리하는 방법입니다.
- Dockerfile 작성 및 저장
# Jenkins LTS 이미지를 베이스로 사용
FROM jenkins/jenkins:lts
USER root
# 필요한 패키지 설치 및 Docker 저장소 추가
RUN apt-get update && \
apt-get -y install apt-transport-https ca-certificates curl gnupg2 && \
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(grep VERSION_CODENAME /etc/os-release | cut -d'=' -f2) stable" > /etc/apt/sources.list.d/docker.list && \
apt-get update && \
apt-get -y install docker-ce-cli
# Docker Compose 설치
RUN curl -L "https://github.com/docker/compose/releases/download/v2.21.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose
USER jenkins
- docker-compose.yml 작성
version: '3.9'
services:
jenkins:
build: .
container_name: jenkins
ports:
- "8080:8080"
- "50000:50000"
volumes:
- /home/junu/docker_data/jenkins:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
networks: {}
- 이미지 빌드 및 Compose 실행
docker-compose up --build -d
- Dockerfile을 사용하여 Docker가 설치된 Jenkins 이미지를 빌드하고 Docker Compose를 통해 Jenkins와 Docker를 함께 사용하는 환경을 구축하는 방법을 설명합니다. 이를 통해 Jenkins 컨테이너 내에서 Docker 명령어를 실행할 수 있게 설정합니다.
4. Jenkins와 GitHub 연동 및 JAR 파일 Docker 컨테이너에 배포
4.1 Dockerfile 사용하여 배포하는 방식
Dockerfile을 소스에 미리 생성해 놓고 Jenkins 파이프라인에서 이를 활용하여 Docker 이미지를 빌드하고 배포하는 방식입니다.
- Dockerfile (프로젝트 루트에 생성된 파일)
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY build/libs/movie-search-app.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
- 파이프라인 스크립트(Jenkinsfile) 작성
pipeline {
agent any
stages {
stage('Clone Repository') {
steps {
// 소스 코드 클론
git url: 'https://github.com/ssongjunu/movie-search-app.git', branch: 'main'
}
}
stage('Build') {
steps {
// Gradle 빌드를 위한 실행 권한 부여 및 빌드
sh 'chmod +x ./gradlew'
sh './gradlew clean build'
}
}
stage('Test') {
steps {
// Gradle 테스트 실행
sh './gradlew test'
}
}
stage('Deploy Docker Container') {
steps {
script {
def imageName = "movie-search-app-image"
def containerName = "movie-search-app-container"
// 기존 Docker 컨테이너 삭제
sh "docker rm -f ${containerName} || true"
// 기존 Docker 이미지 삭제 후 다시 빌드
sh "docker rmi ${imageName} || true"
// Docker 이미지 빌드 (Dockerfile 사용)
sh "docker build -t ${imageName} ."
// 새로운 Docker 컨테이너 실행
sh "docker run -d --name ${containerName} -p 8080:8080 ${imageName}"
}
}
}
}
post {
success {
echo 'Build, tests, and deployment were successful!'
}
failure {
echo 'Build, tests, or deployment failed.'
}
}
}
4.2 Docker Compose를 사용한 배포 방식
- Docker Compose.yml 파일 (프로젝트 루트에 생성된 파일)
version: '3.9'
services:
movie-search-app:
image: openjdk:17-jdk-slim
container_name: movie-search-app
ports:
- "8081:8080"
volumes:
- /home/junu/docker_data/jenkins/workspace/movie-search-app/build/libs/movie-search-app.jar:/app/app.jar # 절대경로
working_dir: /app
command: ["java", "-jar", "app.jar"]
- 파이프라인 스크립트(Jenkinsfile) 작성
pipeline {
agent any
stages {
stage('Clone Repository') {
steps {
// 소스 코드 클론
git url: 'https://github.com/ssongjunu/movie-search-app.git', branch: 'main'
}
}
stage('Build') {
steps {
// Gradle 빌드를 위한 실행 권한 부여 및 빌드
sh 'chmod +x ./gradlew'
sh './gradlew clean build'
}
}
stage('Test') {
steps {
// Gradle 테스트 실행
sh './gradlew test'
}
}
stage('Deploy Docker Compose') {
steps {
script {
// Docker Compose를 사용해 컨테이너 배포
sh 'docker-compose down || true' // 기존 컨테이너 종료
sh 'docker-compose up --build -d' // 새로운 컨테이너 빌드 및 실행
}
}
}
}
post {
success {
echo 'Build, tests, and deployment were successful!'
}
failure {
echo 'Build, tests, or deployment failed.'
}
}
}
5. 배포 확인
배포가 성공적으로 완료되면, Jenkins 콘솔 출력을 통해 확인할 수 있으며 애플리케이션은 지정된 포트에서 정상적으로 동작해야 합니다.
6. 마치며
이 글에서는 Jenkins와 GitHub을 연동하여 지속적 배포(CD)를 설정하고, 빌드된 애플리케이션을 Docker 컨테이너에 배포하는 방법을 다뤘습니다. Docker 소켓을 공유하여 Jenkins가 Docker 명령어를 실행할 수 있도록 설정하는 과정과, Docker Compose를 이용한 배포 방법을 설명했습니다. Docker Compose 파일은 프로젝트의 루트 디렉토리에 생성하고 GitHub 저장소에 포함시켜 팀원들과 공유하는 것이 좋습니다. 이를 통해 CI/CD 파이프라인을 더 효율적으로 관리할 수 있습니다.
'데브옵스 > CICD' 카테고리의 다른 글
[Docker] Jenkins와 GitHub 연동하기: 지속적 통합(Continuous Integration, CI) (0) | 2024.10.05 |
---|---|
Docker로 Jenkins 설치하기: 단계별 가이드 (0) | 2024.10.04 |