1. 왜 CI/CD를 직접 구성해봤나
프로젝트를 진행하면서 매번
- 로컬에서 빌드
- 서버에 접속해 재배포
- 설정 하나만 바뀌어도 다시 반복
이 과정이 너무 비효율적이라고 느꼈다.
그래서 코드를 push하면 자동으로 빌드되고 서버에 반영되는 환경을 직접 구성해 보기로 했다.
이번 목표는 다음과 같다.
- GitHub에 코드 push
- 자동으로 빌드(Test 포함)
- AWS EC2에 자동 배포
- Docker 기반으로 실행 환경 통일
2. 전체 CI/CD 구조
최종적으로 구성한 흐름은 아래와 같다.
[Local]
└─ git push
[GitHub Actions]
└─ Gradle build
└─ Docker image build
[AWS EC2]
└─ SSH 접속
└─ git pull
└─ docker run
초기 학습 목적이기 때문에
ECR, ECS 없이 EC2에 직접 배포하는 “초간단 CD 구조”로 시작했다.
3. CI 구성 (GitHub Actions + Gradle)
3-1. GitHub Actions 워크플로우 생성
GitHub에서 자동 생성해주는 gradle.yml을 기반으로 CI를 구성했다.
//.github/workflows/gradle.yml
name: Java CI with Gradle
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Gradle
run: ./gradlew build
3-2. CI에서 확인한 포인트
- GitHub Actions 러너에는 Docker와 JDK가 기본 설치되어 있음
- 별도 환경 설정 없이 바로 Gradle 빌드 가능
- 테스트 실패 시 배포 이전 단계에서 자동 차단 가능
4. Docker 설정
4-1. Dockerfile 위치와 규칙
- 프로젝트 루트에 Dockerfile 생성
- 파일명은 반드시 Dockerfile (확장자 없음)
4-2. Spring Boot Dockerfile
//Dockerfile
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY build/libs/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app/app.jar"]
4-3. jar 파일 충돌 문제 해결
Gradle 빌드 시 *-plain.jar와 bootJar가 동시에 생성되어
COPY build/libs/*.jar에서 에러가 발생했다.
해결 방법:
//build.gradle
bootJar {
archiveFileName = "app.jar"
}
jar {
enabled = false
}
5. CD 구성 (GitHub Actions → EC2)
5-1. EC2 준비
- Ubuntu EC2 생성
- Docker 설치
- Java 17 설치
- 보안 그룹:
- 22 (SSH)
- 80 (HTTP)
5-2. GitHub Secrets 설정
GitHub → Settings → Secrets and variables → Actions
| Name | 설명 |
| EC2_HOST | EC2 퍼블릭 IP |
| EC2_USER | ubuntu |
| EC2_SSH_KEY | EC2 pem 개인키 전체 |
6. 배포용 GitHub Actions 워크플로우
//.github/workflows/deploy-ec2-simple.yml
name: Deploy to EC2 (Simple)
on:
push:
branches: ["main"]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: SSH and deploy
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
set -e
if [ ! -d "$HOME/apps/CI-CDTest/.git" ]; then
cd "$HOME/apps"
git clone https://github.com/OWNER/REPO.git CI-CDTest
fi
cd "$HOME/apps/CI-CDTest"
git fetch --all
git reset --hard origin/main
./gradlew clean build
docker build -t cicdtest:latest .
docker stop cicdtest || true
docker rm cicdtest || true
docker run -d --name cicdtest -p 80:8080 cicdtest:latest
7. 실제로 겪었던 문제들과 해결
7-1. openjdk:17 이미지 pull 실패
manifest for openjdk:17 not found -> eclipse-temurin:17-jre로 변경하여 해결
7-2. Docker COPY 에러
When using COPY with more than one source file... -> jar 파일 이름 고정 + jar.enabled = false로 해결
8. 배포 성공 확인
docker ps
docker logs -f cicdtest
브라우저:
http://EC2_PUBLIC_IP/
'Spring-Boot' 카테고리의 다른 글
| Spring Security 로그인 방식 변경하기 (1) | 2023.07.06 |
|---|---|
| Spring-Boot JPA 설정 (0) | 2023.03.15 |