이 글에서는 스프링 부트 프로젝트를 개발하면서 깃허브에 코드를 푸시하는 순간부터 빌드, 도커 이미지 생성, 도커 허브 업데이트, 그리고 최종적으로 서버에 배포되는 과정을 자동화하는 방법에 대해 자세히 알아보겠습니다. 이를 통해 개발자는 코드 작성에만 집중하고, 반복적인 작업을 줄여 생산성을 향상시킬 수 있습니다.
핵심 기술:
- GitHub Actions: 깃허브에서 제공하는 CI/CD 워크플로우 자동화 도구
- Docker: 컨테이너 기반의 애플리케이션 패키징 및 배포 도구
- Docker Hub: 도커 이미지를 저장하고 관리하는 클라우드 기반 레지스트리
왜 자동화가 필요한가?
- 시간 절약: 수동으로 진행하던 빌드, 테스트, 배포 과정을 자동화하여 시간을 절약하고 효율성을 높입니다.
- 오류 감소: 사람이 직접 수행하는 작업에서 발생할 수 있는 실수를 줄이고, 일관된 빌드 및 배포 환경을 구축합니다.
- 빠른 피드백: 코드 변경 사항이 즉시 반영되어 서비스에 적용되기 때문에 빠른 피드백을 얻을 수 있습니다.
- 확장성: 프로젝트 규모가 커지더라도 자동화 시스템을 확장하여 유연하게 대처할 수 있습니다.
단계별 설정 가이드
1. Dockerfile 작성
- Dockerfile은 도커 이미지를 생성하기 위한 스크립트입니다. 스프링 부트 애플리케이션을 실행하기 위한 환경을 설정하고, 필요한 라이브러리와 의존성을 설치합니다.
- BASE 이미지: 기본 이미지로 Java, Spring Boot 런타임 이미지를 사용합니다.
- WORKDIR: 작업 디렉토리를 설정합니다.
- COPY: 애플리케이션 코드를 이미지 내부로 복사합니다.
- EXPOSE: 애플리케이션이 사용할 포트를 노출시킵니다.
- CMD: 애플리케이션 실행 명령을 지정합니다.
FROM openjdk:11-jdk-alpine
WORKDIR /app
COPY build/libs/your-app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
2. GitHub Actions 설정
- .github/workflows 디렉토리: GitHub Actions 워크플로우 파일을 저장하는 디렉토리입니다.
- yml 파일: 워크플로우를 정의하는 YAML 파일을 생성합니다.
- 트리거: 푸시, 풀 리퀘스트 등 특정 이벤트 발생 시 워크플로우가 실행되도록 설정합니다.
- 잡: 워크플로우의 실행 단위로, 빌드, 테스트, 배포 등 각 단계를 정의합니다.
- 액션: 잡 내에서 실행되는 개별 작업 단위로, 다양한 오픈 소스 액션을 활용하거나 커스텀 액션을 만들 수 있습니다.
name: CI/CD
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build with Maven
run: mvn package
- name: Build the Docker image
run: docker build -t my-image .
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Push the Docker image
run: docker push my-image
3. 서버 배포 설정
- SSH 키: 깃허브에서 생성한 SSH 키를 서버에 등록하여 워크플로우에서 서버에 접속할 수 있도록 합니다.
- SSH 액션: GitHub Actions에서 제공하는 SSH 액션을 사용하여 서버에 연결하고 명령을 실행합니다.
- Docker Compose: 여러 개의 컨테이너를 정의하고 관리하는 도구를 사용하여 서버에 배포된 이미지를 실행합니다.
- name: Deploy to server
uses: ssh-actions/ssh@v1
with:
host: your-server-ip
username: your-username
key: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
docker-compose up -d
GitHub Actions가 이미지를 Docker Hub에 push하더라도, 실제 내회사의 서버에서 컨테이너를 자동으로 갱신하려면 추가적인 설정이 필요합니다. 이를 위해 보통 서버에서 Docker Hub를 모니터링하고 자동으로 이미지를 pull하여 갱신하는 방식으로 자동화를 구현합니다. 몇 가지 방법을 소개하겠습니다.
1. Docker Hub Webhook 사용
Docker Hub에서 제공하는 Webhook 기능을 사용하면, Docker Hub에 새로운 이미지가 push될 때 서버로 알림을 보낼 수 있습니다. 이를 활용하여 서버에서 자동으로 이미지를 pull하고, 컨테이너를 갱신할 수 있습니다.
설정 방법
- Docker Hub 저장소 설정 페이지에서 Webhooks 섹션으로 이동하여, Webhook을 추가합니다.
- Webhook URL을 서버의 특정 엔드포인트로 지정합니다. 예를 들어, http://your-server-ip:8080/webhook와 같은 URL로 지정할 수 있습니다.
- 서버에 Webhook을 처리할 간단한 서버 스크립트를 작성하여, 요청이 올 때 이미지를 pull하고 컨테이너를 재시작하도록 합니다.
Webhook 처리 스크립트 예시
서버에서 Webhook 요청을 처리하는 간단한 Bash 스크립트를 작성할 수 있습니다.
#!/bin/bash
# 웹 서버로부터 webhook 요청을 수신
echo "Waiting for webhook..."
# webhook 수신 시 실행되는 부분
while true; do
# nc 명령으로 8080 포트에서 수신 대기
echo -e "HTTP/1.1 200 OK\n\n Image pull triggered" | nc -l -p 8080 -q 1
# Docker Hub로부터 새 이미지 pull
docker pull your-dockerhub-username/your-app-name:latest
# 기존 컨테이너 중지 및 제거
docker stop your-container-name
docker rm your-container-name
# 새로운 이미지로 컨테이너 재실행
docker run -d --name your-container-name -p 8080:8080 your-dockerhub-username/your-app-name:latest
echo "Updated Docker container with the latest image."
done
이 스크립트는 Docker Hub Webhook의 요청을 수신하면, 새로운 이미지를 pull한 후 기존 컨테이너를 중단하고, 새 이미지로 컨테이너를 재시작합니다.
2. cron을 사용한 주기적 이미지 pull 및 재배포
만약 Webhook 설정이 어렵다면, cron 작업을 통해 주기적으로 Docker Hub에서 최신 이미지를 pull하도록 할 수도 있습니다. 예를 들어, 5분마다 Docker Hub에서 이미지를 pull하고 최신으로 갱신하는 스크립트를 실행하도록 할 수 있습니다.
*/5 * * * * docker pull your-dockerhub-username/your-app-name:latest && \
docker stop your-container-name && \
docker rm your-container-name && \
docker run -d --name your-container-name -p 8080:8080 your-dockerhub-username/your-app-name:latest
이 cron 작업은 매 5분마다 새로운 이미지를 pull하고, 갱신이 있을 경우 컨테이너를 재시작합니다.
3. Docker Compose + Watchtower
또 다른 방법으로, Watchtower라는 도구를 사용할 수 있습니다. Watchtower는 컨테이너의 이미지가 변경되었는지 자동으로 감지하고, 새로운 이미지가 있을 경우 해당 컨테이너를 재배포합니다.
설정 방법
- 서버에 Watchtower를 설치합니다.
- Watchtower가 자동으로 모든 컨테이너를 감시하고, 새로운 이미지가 push될 때 해당 컨테이너를 업데이트합니다. 특정 컨테이너만 감시하도록 설정할 수도 있습니다.
docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower
이러한 방법을 사용하면, GitHub에서 Docker Hub로 이미지를 push하는 것뿐만 아니라 서버에서도 자동으로 새로운 이미지로 컨테이너가 갱신되도록 설정할 수 있습니다.
마무리
이 글에서는 스프링 부트 프로젝트를 자동화하는 간단한 예시를 소개했습니다. 실제 환경에서는 더 복잡한 설정과 다양한 기능이 필요할 수 있습니다. 예를 들어, 테스트 자동화, 캐시 초기화, 데이터베이스 마이그레이션 등을 추가할 수 있습니다.
주의사항:
- 보안: 깃허브 시크릿에 민감한 정보(Docker Hub 계정 정보, SSH 키 등)를 저장할 때 주의해야 합니다.
- 오류 처리: 워크플로우 실행 중 오류가 발생할 경우 이를 처리하고 알림을 받을 수 있도록 설정해야 합니다.
- 테스트: 자동화 시스템을 도입하기 전에 충분한 테스트를 수행하여 문제가 없는지 확인해야 합니다.
참고:
- GitHub Actions 문서: https://docs.github.com/en/actions
- Docker 문서: https://docs.docker.com/
추가 기능:
- 캐시: 빌드 캐시를 활용하여 빌드 시간을 단축할 수 있습니다.
- 테스트 커버리지: 테스트 커버리지를 측정하여 코드 품질을 관리할 수 있습니다.
- 배포 전략: Canary 배포, Blue-Green 배포 등 다양한 배포 전략을 적용할 수 있습니다.
결론:
GitHub Actions와 Docker를 활용하여 스프링 부트 프로젝트의 CI/CD 파이프라인을 구축하면 개발 생산성을 향상시키고, 안정적인 서비스 운영을 보장할 수 있습니다.
'SpringBoot 를 배워보자' 카테고리의 다른 글
스프링 부트에서 SQL 쿼리 로그 출력: 개발 생산성을 높이는 효과적인 방법 (0) | 2024.11.04 |
---|---|
스프링 부트 프로젝트, 메이븐으로 Docker 이미지 간편하게 생성하기: 상세 가이드 (0) | 2024.11.03 |
WAR 파일과 JAR 파일: 자바 개발자라면 꼭 알아야 할 차이점 (0) | 2024.11.02 |
UN/EDIFACT 메시지를 처리하는 웹 서비스를 구현 (0) | 2024.10.21 |
JPA 예제 (MySQL) 상세 설명 (0) | 2024.10.19 |