solyrion
Spring Boot 빌드: GitHub Actions vs Dockerfile 본문
개요
최근 Express, Spring 서버에 CI/CD를 적용하고 있었습니다.
Express 서버랑 다르게 Spring 서버의 경우 빌드를 진행하면 .jar 이라는 일종의 산출물이 나오게 되고
이것을 실행하는 방식으로 서버를 실행합니다.
그렇기 때문에 Dockerfile로 Spring 서버를 실행한다면 Multi Stage(빌드 스테이지 → 실행 스테이지)로 실행됩니다.
빌드 시점
이러한 방식이다보니 Spring 서버의 빌드 시점, 위치에 대한 고민이 있었습니다.
Docker를 쓰는 상황에서 CI 작업을 Github Actions에서 진행한다면 빌드 위치는 여러 곳일 수 있습니다.
- Docker
- Github Actions
두 군데에서 모두 빌드할 필요는 없다고 생각했고 둘 중 1군데에서 진행하면 되는데
어디서 진행해야 할지에 대한 고민이 있었습니다.
Express의 경우 빌드 산출물이 나오지는 않기 때문에 이러한 고민이 필요 없지만
Spring은 .jar 이 빌드 이후 나오기 때문에 적절한 빌드 위치가 고민되었습니다.
Github Actions에서 빌드
### Dockerfile
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
### ci-cd.yml
name: Spring Boot Docker CI-CD
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
spring-ci:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
cache: gradle
- name: Set Gradle permissions
run: chmod +x gradlew
- name: Run Tests
run: ./gradlew test --no-daemon
- name: Build Spring Boot JAR
run: ./gradlew clean build --no-daemon
# --- DockerHub Login ---
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
# --- Docker Build & Push ---
- name: Build & Push Spring Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/community-be:latest .
docker push ${{ secrets.DOCKER_USERNAME }}/community-be:latest
Github Actions에서 빌드한다면 위의 코드처럼 Dockerfile에는 실행 명령만 존재합니다.
결과

Docker에서 빌드
### Dockerfile
FROM gradle:8.5-jdk21 AS builder
WORKDIR /app
COPY build.gradle settings.gradle ./
COPY gradle ./gradle
RUN gradle dependencies --no-daemon || true
COPY . .
RUN gradle clean bootJar --no-daemon
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
### ci-cd.yml
name: Spring Boot Docker CI-CD
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
spring-ci:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
cache: gradle
- name: Set Gradle permissions
run: chmod +x gradlew
- name: Run Tests
run: ./gradlew test --no-daemon
# --- DockerHub Login ---
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
# --- Docker Build & Push ---
- name: Build & Push Spring Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/community-be:latest .
docker push ${{ secrets.DOCKER_USERNAME }}/community-be:latest
ci-cd.yml에서 빌드 작업을 삭제하고 테스트만 진행합니다.
결과

비교
Github Actions에서 빌드하고 Docker에서는 실행만 하는 방식이 대략 30초 정도 빠르게 작동했습니다.
물론 환경, 코드, 방식에 따라 편차는 있을 수 있지만 유의미하게 Github Actions에서 빌드하는 방식이 빠르게 작동했습니다.
왜 그럴까요?
GitHub Actions에서 빌드 → Docker는 실행만 방식이 더 빠른 이유
- Dockerfile multi-stage 빌드는 매번 전체 빌드가 발생합니다.
- (COPY . . 때문에 캐시가 거의 무효화된다)
- Docker 내부의 Gradle 빌드는 CI Runner보다 I/O가 느려서 더 오래 걸립니다.
- 프로젝트 전체를 Docker 컨텍스트로 압축/전송 (수 MB~수백 MB)
- Docker 파일 시스템에서 gradle 빌드 실행 (속도 낮음)
- Docker 레이어 저장/추가 작업
- GitHub Actions는 Gradle 캐시를 활용해 빌드 속도가 훨씬 빠릅니다.
- actions/setup-java의 gradle cache 옵션을 통해 캐시된 의존성, 빌드 캐시, 로컬 JVM 캐시를 전부 활용할 수 있습니다.
그럼에도 Docker에서 빌드를 진행하는 것이 유용한 경우도 있습니다.
- 빌드 환경을 완전히 통일해야 할 때
- 로컬, CI, 서버마다 JDK·Gradle 버전이 다르면 빌드 결과가 달라질 수 있습니다.
- Kubernetes나 BuildKit 기반의 빌드 파이프라인을 사용할 때
- Kaniko, BuildKit 같은 도커 빌드 최적화 도구를 쓰는 환경에서는 Dockerfile 빌드가 기본 흐름이기 때문에 multi-stage가 더 자연스럽습니다.
- 여러 OS를 사용하는 팀에서 환경 차이가 문제일 때
- Docker 빌드 방식은 OS에 상관없이 동일한 결과를 제공합니다.
- 팀원들이 Windows·macOS·Linux를 섞어서 사용하면 로컬 빌드 결과가 달라질 수 있습니다.
- jar 외에 추가로 빌드해야 할 리소스가 있을 때
- 부가적인 빌드가 많다면 Dockerfile에서 전체 빌드 흐름을 관리하는 것이 더 깔끔할 수 있습니다.
- 프런트 빌드, protobuf, native image, graalvm 등
정리
Spring Boot CI/CD에서 “어디에서 빌드할 것인가?”는 실제로 배포 속도와
전체적인 파이프라인 구조에 영향을 주는 중요한 선택지입니다.
- GitHub Actions에서 빌드 → Docker는 실행만
- → 속도가 빠르고, 일반적인 프로젝트에 가장 효율적
- Dockerfile multi-stage에서 빌드까지 수행
- → 환경 통일성, 재현성, Kubernetes 환경에서 유리
즉, GitHub Actions 빌드는 속도 Docker 빌드 환경 통일성과 안정성에 장점이 있습니다.