Docker Compose와 Jenkins로 CI/CD하기

Hannana·2025년 3월 1일
0
post-thumbnail

아키텍처 설계

User → Nginx (SSL) → Jenkins (Docker 컨테이너)
                        ↳ FastAPI-1 (Docker 컨테이너, 가상환경 포함)
                        ↳ FastAPI-2 (Docker 컨테이너, 가상환경 포함)
                        ↳ RabbitMQ (브로커)
                        ↳ Redis (세션 저장)

클라우드 배포

NCP 서버 할당받기

  • 네이버 클라우드에서 제공하는 100,000 크레딧으로 서버 구축할 예정이다.
  • 다양한 클라우드사, 서버를 비교했을 때 메모리에 제약이 적은 NCP를 사용해보기로 했다.
    그것도 그런게, 4G나 제공해줘서 aws 프리티어 ec2(t2기준) 1G에 비하면.. 감사합니다.. (스왑 효과 있는지도 모르겠음)

VPC생성

subnet 생성

서버 사양 선택 (우분투)

이 정도면 충분하다.
공인IP할당하고, 네트워크 인터페이스도 할당

서버 환경 구축

컨테이너들(worker,fastAPI)

FastAPI-1

파이썬 가상환경에서 돌렸기 때문에
도커 파일에 가상 환경을 사용하도록 설정해주자.

# Python 3.9 기반 이미지 사용
FROM python:3.9

# 작업 디렉토리 생성
WORKDIR /app

# ✅ 가상환경 생성
RUN python -m venv /app/venv

# ✅ 가상환경 활성화
ENV PATH="/app/venv/bin:$PATH"

# 보안 스캐너 설치 (Trivy, Syft)
RUN curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin \
    && curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

# Python 패키지 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 앱 소스 복사
COPY . .

# ✅ 환경 변수 로드
ENV PYTHONUNBUFFERED=1

# ✅ FastAPI 실행 (백그라운드)
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Worker

fastAPI와 같은 가상 환경을 공유해야 한다.

# ✅ Celery Worker 실행용 Dockerfile
FROM python:3.9

WORKDIR /app

# ✅ 부모 디렉토리의 코드도 포함하여 복사
COPY . /app

# ✅ 가상환경을 새로 만들지 않고 기존 환경을 사용
ENV PATH="/app/venv/bin:$PATH"


# ✅ 환경 변수 로드
ENV PYTHONUNBUFFERED=1

# ✅ Celery Worker 실행 (RabbitMQ & Redis 대기 후 실행)
CMD ["sh", "-c", "sleep 10 && celery -A workers.worker worker --loglevel=info"]
  • 기존 가상 환경을 가져다가 쓰고
  • 부모 디렉토리 코드 있어야 worker돌아가는 점 유의하자
    물론, 실행은 순차적으로 해야한다.

Jenkins

인증

#자바 17설치
sudo apt install -y openjdk-17-jdk
wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'

sudo apt update
sudo apt install -y curl gnupg2
# NO PUBKEY 에러 방지 수동 등록
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee /usr/share/keyrings/jenkins-keyring.asc > /dev/null
# jenkins 설치
sudo apt update && sudo apt install -y jenkins
sudo systemctl start jenkins
sudo systemctl enable jenkins

자바는 17버전으로 해야 호환 된다.

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

패스워드 확인

  • 프로세스로 실행ver.
    8080포트 접속해서 패스워드로 접속


젠킨스 메모리 아끼기 위해 필요한 것만 설치하기

회원가입 하고 로그인까지하면

접속 완료. 다시 끊고..

  • 도커 컨테이너에 올려서 실행ver.
docker run -d -p 8080:8080 -p 50000:50000 --name jenkins -u root \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts
  
docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword

컨테이너로 올리기
나머지도 컨테이너로 올려주자.

  • 깃헙 인증
    1) GitHub에서 토큰 생성 => 인증X
    GitHub ➝ Settings ➝ Developer Settings ➝ Personal access tokens -> Generate new token 버튼 클릭

위와 같이 권한 체크 후 발급

  • jenkins에 등록

=> 인증 안됨

2) ssh인증
-Jenkins 서버에서 SSH 키 생성

ssh-keygen -t rsa -b 4096 -C "your-email@example.com"

~/.ssh/id_rsa (개인 키)와 ~/.ssh/id_rsa.pub (공개 키) 생성됨

-GitHub에 SSH 공개 키 등록
GitHub → Settings → SSH and GPG keys
"New SSH Key" 클릭
Title: Jenkins Key

Key: cat ~/.ssh/id_rsa.pub로 출력된 값 복붙

Jenkins 프로젝트 → "Configure"
Source Code Management → "Git"
Repository URL을 SSH 형식으로 변경

git@github.com:***.git

Credentials에서 "SSH Key" 추가
Kind: SSH Username with private key
Username: GitHub 사용자명
Private Key: ~/.ssh/id_rsa 내용 복붙

=> 비대칭키 방식 통해 ssh접속 -> 성공

Jenkins 쉘 작성

  • 현재 Jenkins 컨테이너에서 8080 포트 돌아가고 있음
  • 그 안에서 docker compose 실행 -> 깃헙 최신 버전 pull (build & 재배포)
    -> docker가 Jenkins 쉘에 설치되어있어야 돌아간다.
  • Docker compose 설정 시 아래와 같이 /var/run/docker.sock을 통해 호스트(서버)의 Docker 데몬과 통신
    -> Jenkins container에 권한 부여
services:
  jenkins:
    image: jenkins/jenkins:lts
    user: root
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock 
      - jenkins_home:/var/jenkins_home
    environment:
      - DOCKER_HOST=unix:///var/run/docker.sock
    ports:
      - "8080:8080"
  • Jenkins 내부가 아닌 호스트(서버)의 Docker 데몬에서 컨테이너가 실행된다.
    -> 컨테이너 내 Jenkins가 외부에서 다른 컨테이너(FastAPI, Redis, RabbitMQ)들을 실행하는 구조

github_detection (FastAPI 앱)
celery-worker-github_detection (Celery Worker)
redis (Redis DB)
rabbitmq (RabbitMQ 메시지 브로커)

#!/bin/bash

set -e  #에러 발생 시 즉시 종료

echo "현재 Jenkins 작업 경로: $(pwd)"

#Docker 실행 가능하도록 PATH 설정
export PATH=$PATH:/usr/bin:/usr/local/bin
echo "현재 PATH: $PATH"

#최신 코드 가져오기
echo "최신 코드 가져오는 중..."
git fetch origin main
git reset --hard origin/main

# 기존 컨테이너 종료 (Jenkins 제외)
echo "기존 컨테이너 종료 중..."
docker-compose down || echo "일부 컨테이너가 이미 종료되었거나 실행되지 않았습니다."

#Jenkins 제외하고 컨테이너 실행
echo "새로운 컨테이너 실행 중 (Jenkins 제외)..."
docker-compose up --build -d github_detection celery-worker-github_detection rabbitmq redis

#컨테이너 실행 상태 확인
echo "실행된 컨테이너 목록:"
docker ps

echo "모든 작업이 완료되었습니다!"

빌드 완료.
이제 깃헙 push하면 자동 빌드&배포가 되게끔
CI/CD구성 완료

이렇게 커밋한 내용, 변경 된 내용이 뜨고
로그도 각 푸시 별로 뜬다.
개인적으로 초기 설정의 어려움, 메모리 문제만 빼면 깃헙 액션보다 빠르고 UI가 보기 편해 유지보수가 쉽다는 느낌이 들었다.

profile
성장하는 하루를 쌓아가는 블로그

0개의 댓글