CI/CD 설정하기 (Docker, AWS, EC2, RDB)

icebox127·2026년 3월 31일

졸업 프로젝트 시작에 앞서, ci/cd 설정을 하였다.

배포 흐름

Spring Boot 코드 작성
↓
GitHub Actions가 빌드
↓
Docker 이미지 생성
↓
Docker Hub에 업로드
↓
EC2에서 최신 이미지 pull
↓
EC2 안에서 컨테이너 실행
↓
사용자가 서버 접속

Amazon EC2

EC2란?

Amazon Elastic Compute Cloud
안전하고 크기 조정이 가능한 컴퓨팅 파워를 클라우드에서 제공하는 웹서비스
=> 컴퓨팅을 빌려쓰는 서비스

전 세계 어디서나 가용 영역에서 인스턴스를 시작할 수 있음

EC2는 인스턴스, EBS, AMI, 보안그룹으로 구성된다.

  • 인스턴스: 클라우드에서 사용하는 가상서버
  • EBS(Elastic Block Storage): 클라우드에서 사용하는 가상 하드디스크
  • AMI(Amazon Machine Image): EC2 인스턴스를 실행하기 위한 정보를 담고 있는 이미지
  • 보안 그룹: 가상의 방화벽

EC2 인스턴스 생성

RDS


앞서 생성한 EC2에 연결하여 rds 생성

Docker

배포 시 Docker를 사용하는 이유

보통 프로젝트에서 Docker를 쓰는 이유는 다음과 같다

  1. 환경 통일: 로컬 개발 환경, 테스트 서버, 운영 서버가 모두 동일한 JDK, OS, 라이브러리 버전에서 실행되도록 보장.
  2. 배포 간편화: docker run 한 줄로 어디서든 같은 환경에서 애플리케이션 실행 가능
  3. 의존성 격리: 시스템에 직접 JDK나 DB 등 설치하지 않아도 컨테이너 내부에서 격리된 환경에서 실행
  4. CI/CD 연동: GitHub Actions, Jenkins 등에서 컨테이너 단위로 빌드-배포 자동화 가능

관련 용어

  • 도커 이미지
    • 도커에서 서비스 운영에 필요한 서버 프로그램, 소스코드 및 라이브러리, 컴파일된 실행 파일을 묶는 형태
  • 도커 컨테이너
    • 응용 프로그램의 종송석과 함께 응용 프로그램 자체를 패키징 또는 캡슐화하여 격리된 공간에서 프로세스를 동작시키는 기술(이미지를 실행한 상태)

Dockerfile

FROM eclipse-temurin:21-jdk

WORKDIR /app

COPY build/libs/app.jar app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]

docker-compose.yml

version: "3.8"

services:
  app:
    image: ${DOCKERHUB_USERNAME}/git-turl-backend:latest
    ports:
      - "8080:8080"
    environment:
      DB_URL: ${DB_URL}
      DB_USERNAME: ${DB_USERNAME}
      DB_PASSWORD: ${DB_PASSWORD}
      JWT_SECRET: ${JWT_SECRET}
    restart: always

git actions

  • 환경변수 설정

  • .github/workflows/deploy.yml

name: Spring Boot Docker CI/CD

on:
  push:
    branches: [ "main", "develop" ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: 코드 가져오기
        uses: actions/checkout@v4

      - name: JDK 21 설치
        uses: actions/setup-java@v4
        with:
          java-version: '21'
          distribution: 'temurin'

      - name: Gradle 실행 권한 부여
        run: chmod +x ./gradlew

      - name: Spring Boot jar 빌드
        run: ./gradlew clean bootJar -x test

      - name: Docker Hub 로그인
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Docker 이미지 빌드 및 Push
        run: |
          docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/git-turl-backend:latest .
          docker push ${{ secrets.DOCKERHUB_USERNAME }}/git-turl-backend:latest

      - name: EC2 서버에서 .env 생성 + 최신 이미지 배포
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          script: |
            mkdir -p ~/app
            cat > ~/app/.env <<EOF
            DB_URL=${{ secrets.DB_URL }}
            DB_USERNAME=${{ secrets.DB_USERNAME }}
            DB_PASSWORD=${{ secrets.DB_PASSWORD }}
            JWT_SECRET=${{ secrets.JWT_SECRET }}
            DOCKERHUB_USERNAME=${{ secrets.DOCKERHUB_USERNAME }}
            EOF

            cd ~/app
            if docker compose version > /dev/null 2>&1; then
              docker compose --env-file .env pull
              docker compose --env-file .env down
              docker compose --env-file .env up -d
            else
              docker-compose --env-file .env pull
              docker-compose --env-file .env down
              docker-compose --env-file .env up -d
            fi

            docker image prune -f

결과

배포 경로로 스웨거가 실행된다

profile
감자의 공부기록🥔

0개의 댓글