From 3eb766dc84eb9dd5845ca820586540910651301a Mon Sep 17 00:00:00 2001 From: rlaxxwls13 Date: Thu, 7 May 2026 00:37:10 +0900 Subject: [PATCH 1/4] =?UTF-8?q?chore:=20Dockerfile=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 46 +++++++++++++ gradlew.bat | 188 ++++++++++++++++++++++++++-------------------------- 2 files changed, 140 insertions(+), 94 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e0358c9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ +# syntax=docker/dockerfile:1.7 + +# ===== Stage 1: Build ===== +FROM eclipse-temurin:21-jdk-jammy AS builder + +WORKDIR /app + +# 빌드 설정 파일만 먼저 복사 (의존성 레이어 캐시 최적화) +COPY gradlew . +COPY gradle gradle +COPY build.gradle settings.gradle ./ + +RUN chmod +x gradlew + +# 의존성만 먼저 다운로드 (소스 변경 시에도 이 레이어는 캐시됨) +RUN ./gradlew bootJar -x test --no-daemon || true + +# 소스 복사 후 빌드 +COPY src src +RUN ./gradlew clean bootJar --no-daemon -x test + +# 빌드된 jar에서 layer 추출 +RUN java -Djarmode=layertools -jar build/libs/*.jar extract + + +# ===== Stage 2: Runtime ===== +FROM eclipse-temurin:21-jre-jammy + +# 비-root 유저 생성 +RUN useradd -ms /bin/bash spring + +WORKDIR /app + +# layered jar 복사 (변경 빈도 낮은 순서대로) +COPY --from=builder --chown=spring:spring /app/dependencies/ ./ +COPY --from=builder --chown=spring:spring /app/spring-boot-loader/ ./ +COPY --from=builder --chown=spring:spring /app/snapshot-dependencies/ ./ +COPY --from=builder --chown=spring:spring /app/application/ ./ + +USER spring + +EXPOSE 8888 + +ENV JAVA_OPTS="" + +ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS org.springframework.boot.loader.launch.JarLauncher"] diff --git a/gradlew.bat b/gradlew.bat index 5eed7ee..db3a6ac 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,94 +1,94 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH= - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 6efb5685164b36101dae6504cdbbbca06d87f58a Mon Sep 17 00:00:00 2001 From: rlaxxwls13 Date: Thu, 7 May 2026 11:02:30 +0900 Subject: [PATCH 2/4] =?UTF-8?q?chore:=20docker-compose.yml=20/=20ci=20work?= =?UTF-8?q?flow=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related to #8 --- .github/workflows/ci.yml | 44 ++++++++++++++++++++++++++++++++++++++++ Dockerfile | 5 ++++- build.gradle | 1 + docker-compose.yml | 33 ++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml create mode 100644 docker-compose.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6cd8c62 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,44 @@ +name: CI + +on: + pull_request: + branches: + - main + - dev + push: + branches: + - main + - dev + +jobs: + build-and-test: + runs-on: ubuntu-latest + env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v3 + + - name: Grant execute permission to gradlew + run: chmod +x gradlew + + - name: Build & Test + run: ./gradlew build --no-daemon + + - name: Upload test report (on failure) + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-report + path: build/reports/tests/ + retention-days: 7 diff --git a/Dockerfile b/Dockerfile index e0358c9..0fe86aa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,9 @@ RUN java -Djarmode=layertools -jar build/libs/*.jar extract # ===== Stage 2: Runtime ===== FROM eclipse-temurin:21-jre-jammy +# healthcheck 위해 curl 설치 +RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* + # 비-root 유저 생성 RUN useradd -ms /bin/bash spring @@ -39,7 +42,7 @@ COPY --from=builder --chown=spring:spring /app/application/ ./ USER spring -EXPOSE 8888 +EXPOSE 8080 ENV JAVA_OPTS="" diff --git a/build.gradle b/build.gradle index a8d75cd..5050b68 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ ext { } dependencies { + implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.cloud:spring-cloud-config-server' diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5509a66 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,33 @@ +version: '3.9' + +services: + config-server: + build: + context: . + dockerfile: Dockerfile + image: config-server:latest + container_name: config-server + ports: + - "8888:8080" + environment: + SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod} + CONFIG_SERVER_USERNAME: ${CONFIG_SERVER_USERNAME} + CONFIG_SERVER_PASSWORD: ${CONFIG_SERVER_PASSWORD} + GIT_USERNAME: ${GIT_USERNAME} + GIT_PASSWORD: ${GIT_PASSWORD} + EUREKA_URL: ${EUREKA_URL:-http://eureka-server:8761/eureka/} + JAVA_OPTS: "-XX:MaxRAMPercentage=75.0 -XX:+UseG1GC" + networks: + - first-ticket-network + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] + interval: 30s + timeout: 5s + start_period: 60s + retries: 3 + restart: unless-stopped + +networks: + first-ticket-network: + external: true + name: first-ticket-network From 9ed59e1de5b98357cf6f194c56d133e6ac32029e Mon Sep 17 00:00:00 2001 From: rlaxxwls13 Date: Thu, 7 May 2026 11:13:53 +0900 Subject: [PATCH 3/4] =?UTF-8?q?chore:=20application-test.yml=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related to #8 --- .../ConfigServerApplicationTests.java | 10 +++------- src/test/resources/application-test.yml | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 src/test/resources/application-test.yml diff --git a/src/test/java/com/firstticket/configserver/ConfigServerApplicationTests.java b/src/test/java/com/firstticket/configserver/ConfigServerApplicationTests.java index cf64c4c..e9f0184 100644 --- a/src/test/java/com/firstticket/configserver/ConfigServerApplicationTests.java +++ b/src/test/java/com/firstticket/configserver/ConfigServerApplicationTests.java @@ -2,14 +2,10 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; -@SpringBootTest(properties = { - "spring.cloud.config.server.git.clone-on-start=false", - "spring.cloud.config.server.git.uri=https://example.com/dummy.git", - "spring.cloud.config.server.git.username=dummy", - "spring.cloud.config.server.git.password=dummy", - "eureka.client.enabled=false" -}) +@ActiveProfiles("test") +@SpringBootTest class ConfigServerApplicationTests { @Test diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml new file mode 100644 index 0000000..4956eb2 --- /dev/null +++ b/src/test/resources/application-test.yml @@ -0,0 +1,17 @@ +spring: + cloud: + config: + server: + git: + uri: https://example.com/dummy + username: dummy + password: dummy + clone-on-start: false + security: + user: + name: testuser + password: testpass + +eureka: + client: + enabled: false From 4176bdb43315a45195f48c426216411eff394e4f Mon Sep 17 00:00:00 2001 From: rlaxxwls13 Date: Thu, 7 May 2026 11:15:40 +0900 Subject: [PATCH 4/4] =?UTF-8?q?chore:=20CodeRabbit=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20=E2=80=94=20apt-get=20install=20=EC=97=90?= =?UTF-8?q?=20--no-install-recommends=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 불필요한 추천 패키지 설치 억제로 이미지 크기 최소화 Related to #8 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0fe86aa..57a60c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN java -Djarmode=layertools -jar build/libs/*.jar extract FROM eclipse-temurin:21-jre-jammy # healthcheck 위해 curl 설치 -RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/* # 비-root 유저 생성 RUN useradd -ms /bin/bash spring