2026-01-27 Git action + Docker를 활용한 CI/CD 구축

Ckd gus·2026년 2월 2일

GitHub Actions + Docker 기반 CI/CD 구축 흐름 (Spring Boot 배포)

목표: main 브랜치 push/merge → GitHub Actions 빌드 → Docker 이미지 생성 → 레지스트리 푸시 → EC2에서 컨테이너 재기동
구성: Spring Boot(Gradle) + Docker + Docker Hub(또는 ECR) + EC2 + docker compose


0. 전체 흐름 요약

CI/CD 파이프라인은 다음 순서로 동작한다.

1) 코드 푸시(main)
2) GitHub Actions CI: 빌드/테스트
3) Docker 이미지 빌드
4) Docker 레지스트리 푸시(Docker Hub/ECR)
5) EC2에서 최신 이미지 pull + 컨테이너 재기동(CD)

즉,

코드 푸시 → GitHub Actions 빌드 → Docker 이미지 생성 → 레지스트리 푸시 → EC2에서 컨테이너 재기동


1. GitHub Push (Trigger)

main 브랜치에 push 되거나 PR merge가 되면, GitHub Actions 워크플로우가 자동 실행된다.
추가로 workflow_dispatch를 설정하면 GitHub UI에서 수동 실행도 가능하다.


2. CI 단계 (빌드 & 테스트)

GitHub Actions 러너(ubuntu-latest)에서:

  • JDK 설치 (예: Temurin 21)
  • Gradle 빌드 수행 (bootJar)
  • 테스트는 상황에 따라 수행/스킵 가능 (-x test)

이 단계의 목적은 배포 전에 빌드 실패를 미리 걸러내는 것이다.


3. Docker 이미지 빌드

빌드 결과물(JAR)을 기반으로 Docker 이미지를 생성한다.

  • Dockerfile런타임 환경(JDK 이미지)과 실행 명령(java -jar)을 정의
  • docker build로 이미지를 생성

4. Docker 레지스트리 푸시

빌드된 Docker 이미지를 레지스트리(Docker Hub 또는 ECR)에 업로드한다.

  • 인증 정보는 GitHub Secrets로 관리
  • docker logindocker push

5. CD 단계 (EC2 배포)

EC2에서 해야 할 일은 단순하다.

  • 최신 이미지 pull
  • 컨테이너 재기동

가장 깔끔한 패턴은 docker-compose 기반으로 운영하는 것이다.


GitHub Actions 설정 파일

GitHub Actions를 사용하기 위해서는 레포지토리 루트에 다음 경로의 파일이 필요하다.

.github/workflows/deploy.yml

name: Deploy to EC2


on:
push:
branches: ["main"]
workflow_dispatch:


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


steps:
- name: Checkout source
uses: actions/checkout@v4


- name: Set up Java 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"


- name: Build with Gradle
run: |
chmod +x gradlew
./gradlew clean bootJar -x test


- name: Docker login
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | \
docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin


- name: Docker build & push
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/myapp:latest .
docker push ${{ secrets.DOCKER_USERNAME }}/myapp:latest


- name: Upload docker-compose.yml
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
source: "deploy/docker-compose.yml"
target: "/home/ec2-user/app"
overwrite: true


- name: Deploy on EC2
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
set -e
cd /home/ec2-user/app
docker compose pull
docker compose up -d
docker compose ps

필수 Secrets

이름설명
EC2_HOSTEC2 퍼블릭 IP 또는 도메인
EC2_USEREC2 로그인 유저
EC2_SSH_KEYEC2 Private Key (.pem 전체 내용)
DOCKER_USERNAMEDocker Hub 계정 ID
DOCKER_PASSWORDDocker Hub Access Token

실무 환경에서 사용하는 Secrets

이름설명
SPRING_PROFILES_ACTIVEprod
DB_URLDB 접속 URL
DB_USERNAMEDB 계정
DB_PASSWORDDB 비밀번호
JWT_SECRETJWT 서명 키

Dockerfile

Dockerfile은 Docker 이미지를 생성하고 애플리케이션 실행 환경을 정의하는 파일이다.

FROM eclipse-temurin:21-jdk-jammy


WORKDIR /app


COPY build/libs/*.jar app.jar


EXPOSE 8080


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

애플리케이션 실행에 필요한 설정만 정의되므로 생각보다 내용이 단순하다.


docker-compose.yml

version: "3.9"


services:
mysql:
image: mysql:8.0
container_name: mysql
restart: always
env_file:
- .env
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
networks:
- app-net


app:
image: ${DOCKER_USERNAME}/myapp:latest
container_name: myapp
restart: always
depends_on:
- mysql
env_file:
- .env
ports:
- "8080:8080"
networks:
- app-net


volumes:
mysql_data:


networks:
app-net:
driver: bridge

필수 파일 구조

레포지토리 기준으로 다음 구조를 추천한다.

├─ .github/
│ └─ workflows/
│ └─ deploy.yml
├─ Dockerfile
└─ deploy/
└─ docker-compose.yml


마무리

CI/CD 설정에 필요한 문서와 설정 파일은 AI의 도움을 받아 빠르게 작성할 수 있다.

처음에는 모든 내용을 완벽히 이해하기 어렵지만, AI가 생성한 코드를 기준으로 하나씩 분석하며 학습하는 방식이 매우 효과적이라고 생각한다.

나 또한 이 방식을 통해 여러 기술들을 학습하고 있다.

profile
백엔드 공부중입니다.

0개의 댓글