Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions cs25-service/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM gradle:8.10.2-jdk17 AS builder
# 작업 디렉토리 설정
WORKDIR /build

# 소스 복사 (모듈 전체가 아닌 현재 모듈만 복사)
# 소스 복사
COPY gradlew settings.gradle build.gradle ./
COPY gradle gradle/
COPY cs25-service cs25-service/
Expand All @@ -12,6 +12,8 @@ COPY cs25-common cs25-common/

# 테스트 생략하여 빌드 안정화
RUN ./gradlew :cs25-service:bootJar --stacktrace --no-daemon


FROM eclipse-temurin:17-jre-jammy

# 메타 정보
Expand All @@ -20,12 +22,23 @@ LABEL type="application" module="cs25-service"
# 작업 디렉토리
WORKDIR /apps

# Node.js + npm 설치 후, MCP 서버 전역 설치
# Node.js + npm 설치 후, MCP 서버 전역 설치 + 심볼릭 링크 생성 + 빌드 타임 확인
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& npm install -g @modelcontextprotocol/server-brave-search \
Comment on lines 26 to 30
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

curl | bash(노드소스 설치) 보안/재현성 개선 필요.

  • curl | bash 패턴은 보안상 바람직하지 않습니다. GPG 키링을 사용한 apt 소스 등록을 권장합니다.
  • 빌드 실패 시 즉시 중단·디버깅 강화를 위해 set -euxo pipefail 추가를 권장합니다.
  • Node 및 글로벌 패키지 버전 고정으로 재현성 확보를 권장합니다(예: ARG로 버전 주입).

보안/재현성 개선 예시:

-RUN apt-get update \
- && apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
- && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
- && apt-get install -y --no-install-recommends nodejs \
- && npm install -g @modelcontextprotocol/server-brave-search \
+RUN set -euxo pipefail; \
+  apt-get update \
+  && apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
+  # NodeSource GPG 키 등록 및 소스 추가(20.x 고정)
+  && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
+    | gpg --dearmor -o /usr/share/keyrings/nodesource.gpg \
+  && echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" \
+    > /etc/apt/sources.list.d/nodesource.list \
+  && apt-get update \
+  && apt-get install -y --no-install-recommends nodejs \
+  # 글로벌 패키지 버전 고정 및 불필요한 동작 비활성화
+  && npm config set fund=false audit=false \
+  && npm install -g @modelcontextprotocol/server-brave-search@${MCP_SERVER_VERSION:-latest} \

추가로, Dockerfile 상단(해당 단계 시작부)에 다음 ARG를 선언하면 버전 고정이 용이합니다:

ARG MCP_SERVER_VERSION

원하시면 위 변경을 반영한 전체 RUN 블록을 정리해 드리겠습니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& npm install -g @modelcontextprotocol/server-brave-search \
# (Ensure you have `ARG MCP_SERVER_VERSION` declared above this stage for version pinning)
RUN set -euxo pipefail; \
apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates gnupg bash \
# NodeSource GPG 키 등록 및 소스 추가 (20.x 고정)
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
| gpg --dearmor -o /usr/share/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" \
> /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends nodejs \
# 글로벌 패키지 버전 고정 및 불필요한 동작 비활성화
&& npm config set fund=false audit=false \
&& npm install -g @modelcontextprotocol/server-brave-search@${MCP_SERVER_VERSION:-latest} \
🤖 Prompt for AI Agents
In cs25-service/Dockerfile around lines 26-30, replace the insecure curl | bash
NodeSource install with adding NodeSource's APT repository using its GPG key and
signed repo entry, declare ARGs for NODE_MAJOR (or NODE_VERSION) and
MCP_SERVER_VERSION at the top and use them to pin the node and global npm
package versions, add a shell safety header (set -euxo pipefail) at the start of
the RUN step to fail fast and aid debugging, and ensure apt-get commands use
--no-install-recommends and apt-get clean && rm -rf /var/lib/apt/lists/* to keep
image small and reproducible.

&& ln -sf "$(npm bin -g)/server-brave-search" /usr/local/bin/server-brave-search \
\
# ===== 실행 가능 여부 확인 =====
&& echo "=== npm bin 경로 확인 ===" \
&& npm bin -g \
&& echo "=== server-brave-search 바이너리 확인 ===" \
&& ls -l "$(npm bin -g)/server-brave-search" \
&& ls -l /usr/local/bin/server-brave-search \
&& echo "=== server-brave-search --help 실행 ===" \
&& /usr/local/bin/server-brave-search --help || (echo "[ERROR] server-brave-search 실행 실패" && exit 1) \
\
Comment on lines +31 to +41
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

심볼릭 링크 자기참조(무한 루프) 가능성 및 검증 로직 보강 제안.

npm bin -g/usr/local/bin을 반환하는 환경에서 현재 명령은 자기 자신을 가리키는 심볼릭 링크를 만들 수 있어(ELOOP) 빌드가 실패합니다. 대상/목적지가 동일할 경우 링크 생성을 생략하도록 가드하고, 바이너리 검증은 command -v로도 확인하면 좋습니다.

적용 제안:

- && ln -sf "$(npm bin -g)/server-brave-search" /usr/local/bin/server-brave-search \
- \
- # ===== 실행 가능 여부 확인 =====
- && echo "=== npm bin 경로 확인 ===" \
- && npm bin -g \
- && echo "=== server-brave-search 바이너리 확인 ===" \
- && ls -l "$(npm bin -g)/server-brave-search" \
- && ls -l /usr/local/bin/server-brave-search \
- && echo "=== server-brave-search --help 실행 ===" \
- && /usr/local/bin/server-brave-search --help || (echo "[ERROR] server-brave-search 실행 실패" && exit 1) \
+ && BIN_DIR="$(npm bin -g)" \
+ && TARGET="${BIN_DIR}/server-brave-search" \
+ && DEST="/usr/local/bin/server-brave-search" \
+ && if [ "${TARGET}" != "${DEST}" ]; then ln -sf "${TARGET}" "${DEST}"; fi \
+ \
+ # ===== 실행 가능 여부 확인 =====
+ && echo "=== npm bin 경로 확인 ===" \
+ && echo "${BIN_DIR}" \
+ && echo "=== server-brave-search 경로 확인(command -v) ===" \
+ && command -v server-brave-search \
+ && echo "=== server-brave-search 바이너리 확인 ===" \
+ && ls -l "${TARGET}" \
+ && if [ -e "${DEST}" ]; then ls -l "${DEST}"; fi \
+ && echo "=== server-brave-search --help 실행 ===" \
+ && server-brave-search --help \
🤖 Prompt for AI Agents
In cs25-service/Dockerfile around lines 31 to 41, the current ln -sf step can
create a self-referential symlink when npm bin -g resolves to /usr/local/bin
causing ELOOP; update the Dockerfile to (1) resolve the absolute paths of the
global npm bin and the intended link target and compare them, skipping ln when
they are identical to avoid creating a self-link, (2) maintain the existing ls
checks but add a command -v server-brave-search check to validate the binary is
on PATH, and (3) ensure the help invocation is still run and that failures emit
a clear error and exit non‑zero.

&& npm cache clean --force \
&& apt-get purge -y gnupg \
&& apt-get autoremove -y --purge \
Expand All @@ -35,8 +48,8 @@ RUN apt-get update \
# jar 복사
COPY --from=builder /build/cs25-service/build/libs/*.jar app.jar
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

JAR 복사 글롭 충돌 가능성(다중 매칭 시 실패).

*.jar 글롭은 build/libs에 plain jar와 boot jar가 동시에 존재할 경우 다중 매칭으로 실패할 수 있습니다. 아래 중 하나로 안정화해 주세요.

대안:

  • Gradle에서 plain jar 비활성화(권장): jar { enabled = false } (KTS: tasks.jar { enabled = false }). 이렇게 하면 bootJar만 남아 글롭 충돌이 사라집니다.
  • bootJar 파일명을 고정: bootJar { archiveFileName = "app.jar" } 후 Docker에서는 COPY --from=builder /build/cs25-service/build/libs/app.jar app.jar.
  • 최소한 패턴을 좁힘: cs25-service-*-SNAPSHOT.jar 등(단, 여전히 단일 매칭을 보장해야 함).

원하시면 Gradle 설정 변경까지 포함한 PR 보조 패치를 제안드릴 수 있습니다.


🏁 Script executed:

#!/bin/bash
# cs25-service 모듈의 Gradle 설정에서 JAR 관련 태스크가 어떻게 정의됐는지 확인
rg -n "tasks\\.jar" -n cs25-service
rg -n "bootJar" -n cs25-service
rg -n "archiveFileName" -n cs25-service

Length of output: 235


JAR 복사 glob 충돌 위험: 패턴 안정화 필요

현재 cs25-service/Dockerfile(49행)의

COPY --from=builder /build/cs25-service/build/libs/*.jar app.jar

글롭 패턴 *.jar은 build/libs에 plain JAR과 boot JAR이 공존할 경우 다중 매칭으로 실패할 수 있습니다. 또한 cs25-service/build.gradle(55행)에는 bootJar 블록만 정의되어 있고 plain JAR 비활성화나 파일명 고정 설정이 없어 두 개의 JAR이 생성됩니다. 아래 대안 중 하나를 적용해 단일 JAR을 안정적으로 복사하도록 해 주세요:

  • Gradle plain JAR 비활성화 (권장)
    cs25-service/build.gradle에 추가

    tasks.jar { enabled = false }

    → bootJar만 남아 glob 충돌 해소

  • boot JAR 파일명 고정
    cs25-service/build.gradle의 bootJar 블록 수정

    bootJar {
      archiveFileName.set("app.jar")
    }

    Dockerfile도 함께 변경

    - COPY --from=builder /build/cs25-service/build/libs/*.jar app.jar
    + COPY --from=builder /build/cs25-service/build/libs/app.jar app.jar
  • glob 패턴 구체화

    - COPY --from=builder /build/cs25-service/build/libs/*.jar app.jar
    + COPY --from=builder /build/cs25-service/build/libs/cs25-service-*-SNAPSHOT.jar app.jar

위 방법 중 하나를 선택해 Docker 이미지 빌드가 항상 단일 JAR을 복사하도록 수정해 주세요.

🤖 Prompt for AI Agents
In cs25-service/Dockerfile around line 49 the COPY uses a fragile glob
"build/libs/*.jar" that can match multiple outputs if both plain and boot JARs
are produced; fix by ensuring only one JAR is emitted or by targeting a single
filename: either (A) disable the plain jar in cs25-service/build.gradle by
adding tasks.jar { enabled = false } so only bootJar remains, or (B) set bootJar
archiveFileName to a fixed name like "app.jar" in build.gradle and update the
Dockerfile COPY to reference that exact filename, or (C) tighten the COPY glob
to match the boot JAR filename pattern (for example the boot JAR classifier) so
the Docker step always copies exactly one file.


# 포트 오픈 (service는 8080)
# 포트 오픈
EXPOSE 8080

# 실행
ENTRYPOINT ["java", "-jar", "/apps/app.jar"]
ENTRYPOINT ["java", "-jar", "/apps/app.jar"]