스프링 프로젝트를 도커로 컨테이너화하고 AWS EC2 인스턴스에 배포한 후, 이를 자동화하여 코드 변경 시마다 자동으로 빌드하고 배포하는 CI/CD 파이프라인을 구축해보겠습니다. 이를 통해 개발 속도를 높이고, 배포 과정에서 발생할 수 있는 오류를 최소화할 수 있습니다.
1. CI/CD 파이프라인 개요
CI/CD는 지속적인 통합(Continuous Integration)과 지속적인 배포(Continuous Deployment)의 약자로, 소프트웨어 개발과 배포를 자동화하여 효율성을 극대화하는 방법론입니다.
- Continuous Integration (CI): 코드 변경 사항을 주기적으로 통합하고, 자동화된 빌드와 테스트를 수행하여 코드의 품질을 유지합니다.
- Continuous Deployment (CD): CI 과정을 통해 검증된 코드를 자동으로 프로덕션 환경에 배포합니다.
이번 파트에서는 GitHub Actions를 사용하여 코드가 GitHub에 푸시될 때마다 자동으로 빌드, 테스트, 도커 이미지 생성, 도커 허브로 푸시, 그리고 AWS EC2 인스턴스에 배포하는 파이프라인을 구축합니다.
2. GitHub 리포지토리 준비
먼저, GitHub에 프로젝트 리포지토리를 준비해야 합니다.
a. GitHub 리포지토리 생성
- GitHub에 로그인합니다.
- 오른쪽 상단의 "+" 버튼을 클릭하고 "New repository"를 선택합니다.
- Repository name에 프로젝트 이름(예: babylion)을 입력합니다.
- Public 또는 Private 여부를 선택합니다.
- Initialize this repository with a README는 선택 해제한 후, 기존 로컬 프로젝트와 연결합니다.
- Create repository를 클릭합니다.
b. 로컬 리포지토리와 GitHub 리포지토리 연결
이미 로컬에 프로젝트가 있다면, 이를 GitHub 리포지토리와 연결합니다.
cd C:\Users\mike7\Desktop\멋사\babylion
git init
git remote add origin https://github.com/your-username/babylion.git
git add .
git commit -m "Initial commit"
git push -u origin master
참고: your-username을 GitHub 사용자 이름으로 변경하세요.
성공적으로 푸시되었다면, GitHub 리포지토리 페이지에서 파일들이 정상적으로 업로드된 것을 확인할 수 있습니다.
3. GitHub Secrets 설정
CI/CD 파이프라인에서 Docker Hub와 AWS EC2에 접근하기 위해 필요한 민감한 정보를 GitHub Secrets에 저장합니다.
a. GitHub Secrets 접근
- GitHub 리포지토리 페이지로 이동합니다.
- 오른쪽 상단의 "Settings" 탭을 클릭합니다.
- 왼쪽 사이드바에서 "Secrets and variables" > "Actions"를 선택합니다.
- "New repository secret" 버튼을 클릭합니다.
b. 필요한 Secrets 추가
다음과 같은 Secrets를 추가합니다:
- DOCKERHUB_USERNAME
- Name: DOCKERHUB_USERNAME
- Value: Docker Hub 사용자 이름
- DOCKERHUB_ACCESS_TOKEN
- Name: DOCKERHUB_ACCESS_TOKEN
- Value: Docker Hub Access Token (비밀번호 대신 사용하는 토큰)
- 참고: Docker Hub에서 Access Token 생성 후 사용
- EC2_HOST
- Name: EC2_HOST
- Value: EC2 인스턴스의 퍼블릭 IP 주소 (예: 52.78.149.48)
- EC2_USERNAME
- Name: EC2_USERNAME
- Value: EC2 인스턴스의 사용자 이름 (ubuntu)
- EC2_KEY
- Name: EC2_KEY
- Value: EC2 인스턴스에 접속할 때 사용하는 SSH 키의 내용 (.pem 파일의 내용)
4. GitHub Actions 워크플로우 작성
GitHub Actions를 사용하여 CI/CD 파이프라인을 설정합니다. 워크플로우 파일은 리포지토리의 .github/workflows 디렉터리에 YAML 파일로 저장됩니다.
a. 워크플로우 파일 생성
- 로컬 프로젝트에서 .github/workflows 디렉터리를 생성합니다.
b. 워크플로우 파일 내용 작성
ci-cd-pipeline.yml 파일에 다음 내용을 추가합니다:
.github/workflows/ci-cd-pipeline.yml
name: CI/CD Pipeline
on:
push:
branches:
- master
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
# 1. 코드 체크아웃
- name: Checkout code
uses: actions/checkout@v3
# 2. JDK 설정
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: '17'
# 3. Maven 빌드 및 테스트
- name: Build with Maven
run: mvn clean install
# 4. Docker Hub 로그인
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
# 5. 도커 이미지 빌드
- name: Build Docker image
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/babylion:latest .
# 6. 도커 이미지 푸시
- name: Push Docker image
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/babylion:latest
# 7. AWS EC2에 SSH 접속하여 도커 컨테이너 업데이트
- name: Deploy to EC2
uses: appleboy/ssh-action@v0.1.8
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_KEY }}
script: |
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/babylion:latest
docker stop babylion || true
docker rm babylion || true
docker run -d --name babylion -p 8081:8080 ${{ secrets.DOCKERHUB_USERNAME }}/babylion:latest
c. 워크플로우 파일 설명
- name: 워크플로우의 이름입니다. CI/CD Pipeline으로 설정했습니다.
- on: 워크플로우를 트리거할 이벤트를 정의합니다. 여기서는 master 또는 main 브랜치에 푸시될 때마다 실행됩니다.
- jobs: 워크플로우 내에서 실행할 작업들을 정의합니다. 여기서는 build라는 하나의 작업만 정의했습니다.
- steps: 작업 내에서 실행할 일련의 단계를 정의합니다.
단계별 설명
- Checkout code: 리포지토리의 코드를 체크아웃합니다.
- Set up JDK 17: JDK 17을 설정하여 Maven 빌드를 준비합니다.
- Build with Maven: mvn clean install 명령어로 프로젝트를 빌드하고 테스트를 실행합니다.
- Login to Docker Hub: Docker Hub에 로그인합니다. GitHub Secrets에 저장된 Docker Hub 자격 증명을 사용합니다.
- Build Docker image: 도커 이미지를 빌드합니다. 이미지 이름은 dockerhub-username/babylion:latest 형식입니다.
- Push Docker image: 빌드한 도커 이미지를 Docker Hub에 푸시합니다.
- Deploy to EC2: SSH를 통해 AWS EC2 인스턴스에 접속하여 도커 컨테이너를 업데이트합니다.
- docker pull: 최신 도커 이미지를 풀합니다.
- docker stop: 기존의 babylion 컨테이너를 중지합니다. 컨테이너가 없을 경우 오류를 무시합니다.
- docker rm: 기존의 babylion 컨테이너를 삭제합니다.
- docker run: 새로운 도커 컨테이너를 실행합니다. 여기서 포트를 8081:8080으로 매핑했습니다.
d. GitHub Actions 워크플로우 활성화
GitHub 리포지토리에 변경 사항을 커밋하고 푸시하면, 워크플로우가 자동으로 실행됩니다.
git add .github/workflows/ci-cd-pipeline.yml
git commit -m "Add CI/CD pipeline with GitHub Actions"
git push origin master
5. AWS EC2 인스턴스 설정
CI/CD 파이프라인이 AWS EC2 인스턴스에 도커 컨테이너를 배포할 수 있도록 EC2 인스턴스를 올바르게 설정해야 합니다.
a. SSH 키 준비
이미 EC2 인스턴스를 설정하고 SSH로 접속할 수 있는 상태라면, GitHub Actions가 EC2에 접속할 수 있도록 SSH 키를 준비합니다.
1. SSH 키 생성 (로컬에서):
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f ~/.ssh/babylion_key
- 파일 이름: babylion_key
- 비밀번호: 설정하지 않도록 권장합니다 (자동화 스크립트에서 사용하기 위함).
2. 퍼블릭 키를 EC2에 추가:
- AWS 콘솔에서 EC2 인스턴스를 선택하고, 보안 그룹 > 인바운드 규칙에서 SSH(22번 포트)가 허용되어 있는지 확인합니다.
- EC2 인스턴스에 퍼블릭 키 추가:
cat ~/.ssh/babylion_key.pub | ssh -i ~/.ssh/khtml.pem ubuntu@[EC2 IP주소] 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'
- SSH 키 권한 설정:
ssh -i ~/.ssh/khtml.pem ubuntu@[EC2 IP주소]
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
exit

b. GitHub Secrets에 SSH 키 추가
- SSH 키 내용을 복사:출력된 키 내용을 복사합니다.
cat ~/.ssh/babylion_key
- GitHub Secrets에 추가:
- GitHub 리포지토리의 Settings > Secrets and variables > Actions로 이동합니다.
- "New repository secret"을 클릭합니다.
- Name: EC2_KEY
- Value: 복사한 SSH 키 내용 (개인 키)
- 저장을 클릭합니다.
6. 배포 스크립트 작성
GitHub Actions 워크플로우에서 실행할 배포 스크립트를 작성하여 EC2 인스턴스에서 도커 컨테이너를 업데이트합니다.
a. 배포 스크립트 이해
워크플로우 파일에서 사용한 배포 스크립트는 다음과 같습니다:
docker pull mike705114/babylion:latest
docker stop babylion || true
docker rm babylion || true
docker run -d --name babylion -p 8081:8080 mike705114/babylion:latest
- docker pull: Docker Hub에서 최신 이미지를 가져옵니다.
- docker stop: 기존 컨테이너를 중지합니다. 컨테이너가 없으면 무시합니다.
- docker rm: 기존 컨테이너를 삭제합니다. 컨테이너가 없으면 무시합니다.
- docker run: 새로운 도커 컨테이너를 실행합니다.
- -d: 백그라운드에서 실행
- --name babylion: 컨테이너 이름 설정
- -p 8081:8080: 호스트의 8081 포트를 컨테이너의 8080 포트와 매핑
7. CI/CD 파이프라인 테스트
모든 설정이 완료되었으므로, 이제 파이프라인을 테스트해 보겠습니다.
a. 코드 변경 및 푸시
로컬 프로젝트에서 코드에 변경을 가한 후, 이를 GitHub에 푸시합니다.
# 예시: README 파일 수정
echo "CI/CD 파이프라인 테스트" >> README.md
git add README.md
git commit -m "Test CI/CD pipeline"
git push origin master
b. GitHub Actions 실행 확인
- GitHub 리포지토리 페이지로 이동합니다.
- 상단의 "Actions" 탭을 클릭합니다.
- 방금 푸시한 커밋에 대한 워크플로우가 실행되는 것을 확인합니다.
- 각 단계가 성공적으로 완료되었는지 확인합니다.
- Checkout code: 코드가 정상적으로 체크아웃되었는지 확인합니다.
- Set up JDK 17: JDK 17이 제대로 설정되었는지 확인합니다.
- Build with Maven: Maven 빌드가 성공적으로 완료되었는지 확인합니다.
- Login to Docker Hub: Docker Hub에 정상적으로 로그인되었는지 확인합니다.
- Build Docker image: 도커 이미지가 정상적으로 빌드되었는지 확인합니다.
- Push Docker image: 도커 이미지가 Docker Hub에 정상적으로 푸시되었는지 확인합니다.
- Deploy to EC2: 배포 스크립트가 정상적으로 실행되어 EC2 인스턴스에 도커 컨테이너가 업데이트되었는지 확인합니다
c. AWS EC2에서 애플리케이션 확인
- 웹 브라우저를 열고 다음 URL로 이동합니다:
http://<EC2_PUBLIC_IP>:8081
애플리케이션이 정상적으로 실행되고 있는지 확인합니다.
실행은 되긴 하는데 더 명시적으로 컨트롤러를 하나 추가해 보겠습니다
d. Controller 추가
배포가 성공적으로 이루어졌다면, 새로운 컨트롤러를 추가하여 변경사항이 잘 반영되었는지 확인할 수 있습니다.
e. GitHub Actions 실행 확인
주황 동그라미가 체크 표시로 변하면 브라우저에서 변경사항 확인!
f. 스웨거 확인
Swagger UI를 통해 API 문서가 정상적으로 표시되는지 확인합니다.
결론
이번 파트에서는 GitHub Actions를 활용하여 CI/CD 파이프라인을 구축하는 방법을 자세히 살펴보았습니다. 이를 통해 코드가 GitHub에 푸시될 때마다 자동으로 빌드, 테스트, 도커 이미지 생성 및 푸시, 그리고 AWS EC2 인스턴스에 배포되는 과정을 자동화할 수 있었습니다. 이러한 자동화는 개발 효율성을 높이고, 배포 과정에서 발생할 수 있는 오류를 최소화하는 데 큰 도움이 됩니다.
마무리
CI/CD 파이프라인을 구축함으로써, 스프링 애플리케이션의 빌드와 배포 과정을 자동화하여 개발 효율성과 배포의 신뢰성을 크게 향상할 수 있었습니다. 앞으로 더 많은 자동화와 최적화를 통해 더욱 견고하고 확장 가능한 애플리케이션을 운영할 수 있게 될 것입니다. 다음 포스팅에서는 고가용성 설정 및 로드 밸런싱에 대해 다루겠습니다. 감사합니다! 😊
'백엔드 > Docker' 카테고리의 다른 글
[Docker] Docker 배포 시 Timezone 설정 문제 해결하기 (실행 시점에 타임존 설정) (2) | 2024.10.16 |
---|---|
[Docker] AWS Access Key 유출 방지 및 GitHub Secrets 활용하여 안전한 Docker 배포 방법 (4) | 2024.10.16 |
[Docker] EC2 인스턴스에 도커(Docker) 설치 및 설정 (3) | 2024.10.09 |
[Docker] 스프링 프로젝트를 도커(Docker)로 컨테이너화하기 (3) | 2024.10.08 |