Skip to content

배포를 위한 docker-compose 파일 추가 및 securityConfig 수정, deploy 파일 추가 - #61

Merged
roode1017 merged 3 commits into
devfrom
feat/#59
Aug 14, 2025
Merged

배포를 위한 docker-compose 파일 추가 및 securityConfig 수정, deploy 파일 추가#61
roode1017 merged 3 commits into
devfrom
feat/#59

Conversation

@roode1017

@roode1017 roode1017 commented Aug 14, 2025

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • 인증 없이 접근 가능한 헬스 체크 엔드포인트 추가로 가용성 모니터링이 용이해졌습니다.
  • Chores
    • 메인 브랜치 푸시 시 자동 빌드·배포하는 파이프라인을 도입하여 릴리스 속도와 일관성을 개선했습니다. 선택적으로 CDN 캐시 무효화를 지원합니다.
  • Infrastructure
    • 프로덕션용 컨테이너 구성 추가: 다중 API 인스턴스와 Redis, Elasticsearch, Kafka를 포함해 확장성·안정성을 강화했습니다.

@roode1017 roode1017 self-assigned this Aug 14, 2025
@roode1017 roode1017 added the enhancement New feature or request label Aug 14, 2025
@roode1017 roode1017 linked an issue Aug 14, 2025 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Aug 14, 2025

Copy link
Copy Markdown

Walkthrough

메인 브랜치 푸시 시 EC2로 배포하는 GitHub Actions 워크플로우와 프로덕션용 docker-compose를 추가했다. 백엔드에 /health 엔드포인트를 신설하고, Spring Security에서 해당 경로를 공개 허용하도록 규칙을 추가했다.

Changes

Cohort / File(s) Summary of changes
배포 워크플로우
.github/workflows/deploy.yml
메인 푸시 트리거, JDK 21/Gradle 빌드, 산출물 업로드, EC2 SSH 접속 후 Docker/Compose 설치, docker-compose-prod로 컨테이너 재빌드/재기동, 선택적 이미지 정리 및 선택적 CloudFront 무효화 추가
헬스 체크 엔드포인트
backendProject/src/main/java/.../global/health/HealthController.java
@RestController 추가, GET /health에서 "ok" 반환
보안 설정 갱신
backendProject/src/main/java/.../global/security/config/SecurityConfig.java
보안 규칙에 /health 경로 permitAll 추가
프로덕션 컴포즈 스택
docker-compose-prod.yml
api1/api2 서비스, Redis 3노드, Elasticsearch, Zookeeper, Kafka 정의; 헬스체크 및 네트워크/볼륨 설정 포함

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant SpringSecurity as Spring Security
  participant HealthController as HealthController

  Client->>SpringSecurity: GET /health
  SpringSecurity-->>HealthController: permitAll (인증 불필요)
  HealthController-->>Client: 200 OK ("ok")
Loading
sequenceDiagram
  autonumber
  participant GitHub as GitHub Actions
  participant EC2 as EC2 Host
  participant Docker as Docker/Compose
  participant AWS as CloudFront (optional)

  GitHub->>GitHub: Checkout, JDK 21, Gradle build -x test
  GitHub->>EC2: SCP 산출물(.env, JAR, Dockerfile, docker-compose-prod.yml)
  GitHub->>EC2: SSH 접속 (Docker/Compose 설치 확인)
  GitHub->>Docker: docker compose down (if running)
  GitHub->>Docker: docker compose build --no-cache
  GitHub->>Docker: docker compose up -d
  alt CF_DISTRIBUTION_ID 존재
    GitHub->>AWS: Invalidate CloudFront cache
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

토끼는 깡충, “ok!”를 전해, /health에 인사해요
컨테이너 두둥탁, api가 둘이서 노래해요
레디스, 카프카, 엘라스틱 줄 맞춰 춤추고
구름길 캐시도 휘익—사라져요
메인에 푸시하면, 밤하늘에 배포별이 반짝! 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#59

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🔭 Outside diff range comments (1)
backendProject/src/main/java/likelion/mlb/backendProject/global/security/config/SecurityConfig.java (1)

38-54: 모든 요청이 permitAll로 풀려 있어 보안이 사실상 무력화됨 — 최소 권한 원칙으로 재정렬 필요

현재 규칙의 첫 줄에서 "/**"를 permitAll로 허용하고, 마지막에서도 anyRequest().permitAll()을 선언해 JWT 기반 인증이 전혀 적용되지 않습니다. /health 허용 추가 자체는 맞지만, 상위 전역 permitAll 때문에 의미가 없어집니다. 또한 동일한 매처 중복 선언이 다수 존재합니다.

아래와 같이 전역 permitAll을 제거하고, 허용해야 할 경로만 명시적으로 permitAll, 그 외는 authenticated로 닫아주세요. 정적 리소스 매처와 swagger, oauth, 드래프트 관련 경로는 필요 시 유지하되 중복을 제거합니다.

-        .authorizeHttpRequests(auth -> auth
-            .requestMatchers("/**").permitAll()
-            .requestMatchers("/api/auth/**", "/oauth2/**", "/login.html").permitAll()
-            .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
-            .requestMatchers("/login.html", "/login-success.html").permitAll()
-            .requestMatchers("/api/**", "/oauth2/**", "/login.html").permitAll()
-            .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
-            .requestMatchers("/health").permitAll()
-            .requestMatchers("/ws/**").permitAll()
-            .requestMatchers(
-                "/swagger-ui/**",
-                "/v3/api-docs/**"
-            ).permitAll()
-            .requestMatchers("/draft/**", "/api/draft/**", "/ws-draft", "/topic/**", "/js/**").permitAll() // 선수 드래프트 관련 잠시 허용
-            //.requestMatchers("/api/**").authenticated()
-            .anyRequest().permitAll()
-        )
+        .authorizeHttpRequests(auth -> auth
+            // 정적 자원
+            .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
+            // 공개 허용 엔드포인트
+            .requestMatchers(
+                "/health",
+                "/api/auth/**",
+                "/oauth2/**",
+                "/login.html",
+                "/login-success.html",
+                "/swagger-ui/**",
+                "/v3/api-docs/**",
+                "/ws/**",
+                "/draft/**", "/api/draft/**", "/ws-draft", "/topic/**", "/js/**"
+            ).permitAll()
+            // 그 외는 인증 필요
+            .anyRequest().authenticated()
+        )

추가 제안:

  • CORS 사전 요청(OPTIONS)을 명시적으로 허용해야 한다면 HttpMethod.OPTIONS에 대한 permitAll 매처를 추가하는 것도 고려하세요.
  • 위 수정 후에 실제 보호되어야 할 API가 정상적으로 인증 흐름(JWT 필터)을 타는지 통합 테스트로 검증하시길 권장합니다.
🧹 Nitpick comments (5)
backendProject/src/main/java/likelion/mlb/backendProject/global/health/HealthController.java (1)

7-13: 심플하고 충분하지만, 운영환경에서는 Actuator 사용 또는 콘텐츠 타입 명시 고려

현재 구현은 가볍고 충분합니다. 다만 운영/배포 환경 건강 체크 용도로는 Spring Boot Actuator의 /actuator/health 사용이 표준적이며, 추가 메트릭/상태 점검과 통합이 용이합니다. 계속 커스텀 엔드포인트를 사용할 경우, 텍스트 응답의 명확성을 위해 produces를 명시하는 것을 추천합니다.

예시(선택):

-import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.http.MediaType;

-  @GetMapping("/health")
+  @GetMapping(value = "/health", produces = MediaType.TEXT_PLAIN_VALUE)
   public ResponseEntity<String> healthCheck() {
     return ResponseEntity.ok("ok");
   }

또는 Actuator 도입:

  • 의존성 추가: spring-boot-starter-actuator
  • application 설정으로 /actuator/health만 외부 노출
  • SecurityConfig에서 /actuator/health permitAll
docker-compose-prod.yml (2)

95-133: Zookeeper/Kafka 헬스체크의 bash 의존성과 외부 포트 노출 재검토

  • 현재 헬스체크가 bash -lc 'echo > /dev/tcp/...'에 의존합니다. 이미지에 bash가 없으면 헬스체크가 실패합니다. 가능하면 curl/wget 기반 체크 또는 Dockerfile HEALTHCHECK 활용으로 전환하세요.
  • Kafka 9092 포트를 호스트로 노출하고 있습니다. 외부에서 접근이 필요 없다면 포트 노출을 제거하거나 방화벽/보안 그룹으로 제한하세요. 내부 통신만 필요하다면 노출 불필요합니다.

41-70: Redis 3개 컨테이너는 클러스터/센티널 설정 없이 단순 병렬 구동 — 목적 확인 필요

현재 구성은 redis1만 healthcheck와 depends_on에 사용되고, redis2/3는 클러스터나 센티널 설정이 없습니다. 고가용성/샤딩이 의도라면 추가 설정이 필요합니다. 단일 인스턴스만 사용한다면 불필요한 컨테이너를 제거하는 것이 단순하고 안전합니다.

.github/workflows/deploy.yml (2)

24-26: Gradle 빌드 캐시 적용으로 CI 시간 단축 가능

반복 빌드가 잦다면 Gradle 캐시를 추가하여 빌드 시간을 줄일 수 있습니다. 예: actions/cache 사용.


57-76: Docker 설치/권한 처리 스크립트 안정성 개선 제안

  • usermod -aG docker $USER는 현재 SSH 세션에는 즉시 반영되지 않습니다. 이후에도 sudo docker를 사용하고 있으므로 이 행은 생략 가능.
  • Amazon Linux 2023의 경우 docker 설치는 dnf가 맞지만, 환경에 따라 amazon-linux-extras 경로가 더 안정적일 수 있습니다. 배포 대상 OS 버전을 기준으로 설치 경로를 고정하는 것을 권장합니다.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8510a96 and 5751e4e.

📒 Files selected for processing (4)
  • .github/workflows/deploy.yml (1 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/global/health/HealthController.java (1 hunks)
  • backendProject/src/main/java/likelion/mlb/backendProject/global/security/config/SecurityConfig.java (1 hunks)
  • docker-compose-prod.yml (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
backendProject/src/main/java/likelion/mlb/backendProject/global/security/config/SecurityConfig.java (1)
backendProject/src/main/java/likelion/mlb/backendProject/global/configuration/WebMvcConfig.java (1)
  • Override (23-30)
🪛 actionlint (1.7.7)
.github/workflows/deploy.yml

88-88: context "secrets" is not allowed here. available contexts are "env", "github", "inputs", "job", "matrix", "needs", "runner", "steps", "strategy", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details

(expression)


96-96: context "secrets" is not allowed here. available contexts are "env", "github", "inputs", "job", "matrix", "needs", "runner", "steps", "strategy", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details

(expression)

Comment on lines +33 to +44
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
source: |
docker-compose-prod.yml
backendProject/Dockerfile
backendProject/build/libs/*.jar
.env
target: ${{ secrets.EC2_APP_DIR }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

.env 파일을 레포에서 전달하는 방식은 위험/취약 — 서버 측 생성으로 전환 권장

.env를 레포에서 전송하면 비밀정보 노출 위험이 있고, 레포에 파일이 없을 경우 scp 단계가 실패할 수 있습니다. 업로드 대상에서 .env를 제거하고, 다음과 같이 SSH 단계에서 서버 내에 비밀을 작성하는 방식을 권장합니다.

업로드 목록에서 제거:

           source: |
             docker-compose-prod.yml
             backendProject/Dockerfile
             backendProject/build/libs/*.jar
-            .env

서버에서 .env 생성(예시 — 필요한 키만 포함):

      - name: Write .env 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
            APP_DIR="${{ secrets.EC2_APP_DIR }}"
            mkdir -p "$APP_DIR"
            cat > "$APP_DIR/.env" << 'EOF'
            SPRING_PROFILES_ACTIVE=prod
            # 예: DB_URL, DB_USER, DB_PASSWORD, JWT_SECRET, ...
            DB_URL=${{ secrets.DB_URL }}
            DB_USER=${{ secrets.DB_USER }}
            DB_PASSWORD=${{ secrets.DB_PASSWORD }}
            JWT_SECRET=${{ secrets.JWT_SECRET }}
            EOF
            chmod 600 "$APP_DIR/.env"

원하시면 위 내용을 현재 비밀 키 이름 체계에 맞춰 구체화해 드리겠습니다.

Comment on lines +88 to +97
if: ${{ secrets.CF_DISTRIBUTION_ID != '' }}
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}

- name: Invalidate CloudFront
if: ${{ secrets.CF_DISTRIBUTION_ID != '' }}
run: |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

actionlint 경고: if 조건식에서 secrets 컨텍스트 사용 불가 — env로 우회 필요

actionlint 힌트대로 현재 위치의 if에서 secrets 컨텍스트를 사용할 수 없습니다. job-level env에 값을 매핑한 뒤 env를 참조하도록 수정하세요.

해당 if 라인 수정:

-      - name: Configure AWS credentials
-        if: ${{ secrets.CF_DISTRIBUTION_ID != '' }}
+      - name: Configure AWS credentials
+        if: ${{ env.CF_DISTRIBUTION_ID != '' }}
@@
-      - name: Invalidate CloudFront
-        if: ${{ secrets.CF_DISTRIBUTION_ID != '' }}
+      - name: Invalidate CloudFront
+        if: ${{ env.CF_DISTRIBUTION_ID != '' }}

job-level env 추가(파일 상단 jobs.deploy 아래에 삽입):

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      CF_DISTRIBUTION_ID: ${{ secrets.CF_DISTRIBUTION_ID }}
🧰 Tools
🪛 actionlint (1.7.7)

88-88: context "secrets" is not allowed here. available contexts are "env", "github", "inputs", "job", "matrix", "needs", "runner", "steps", "strategy", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details

(expression)


96-96: context "secrets" is not allowed here. available contexts are "env", "github", "inputs", "job", "matrix", "needs", "runner", "steps", "strategy", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details

(expression)

🤖 Prompt for AI Agents
.github/workflows/deploy.yml around lines 88 to 97: actionlint flags using the
secrets context directly in an if expression here; move the secret into a
job-level env and update the if to reference env.CF_DISTRIBUTION_ID instead of
secrets.CF_DISTRIBUTION_ID. Add under jobs.deploy (near top of jobs block) an
env mapping CF_DISTRIBUTION_ID: ${{ secrets.CF_DISTRIBUTION_ID }}, then change
the two if lines in this block to: if: ${{ env.CF_DISTRIBUTION_ID != '' }} so
the workflow uses env for conditional checks.

Comment thread docker-compose-prod.yml
Comment on lines +5 to +22
api1:
build:
context: ./backendProject
container_name: mlb-api-1
ports:
- "8080:8080"
env_file:
- .env
depends_on:
mlb-redis1:
condition: service_healthy
mlb-elasticsearch:
condition: service_healthy
mlb-kafka:
condition: service_healthy
networks:
- backend

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

API 컨테이너에 restart 정책과 헬스체크 추가 권장

배포 안정성을 위해 재시작 정책을 추가하고, 로드밸런서/오케스트레이션과의 연계를 위해 컨테이너 헬스체크를 정의하는 것을 권장합니다. 현 이미지에 curl/wget이 없을 수 있어, 가능하면 Dockerfile에 HEALTHCHECK를 정의하는 방식을 추천합니다.

Compose 측 최소 변경(재시작 정책):

   api1:
     build:
       context: ./backendProject
     container_name: mlb-api-1
+    restart: unless-stopped
     ports:
       - "8080:8080"

Dockerfile(backendProject/Dockerfile) 예시(이미지에 curl 설치 가능 시):

# 이미지에 curl이 없다면 설치 (예: debian/ubuntu 기반)
# RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

HEALTHCHECK --interval=30s --timeout=3s --retries=10 CMD curl -fsS http://localhost:8080/health || exit 1

검증 요청:

  • 현재 애플리케이션 베이스 이미지에 curl/wget/bash 등 어떤 툴이 포함되어 있는지 확인 부탁드립니다. 포함 여부에 따라 HEALTHCHECK 구현 방식을 조정하겠습니다.

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== docker-compose-prod.yml (first 200 lines) =="
sed -n '1,200p' docker-compose-prod.yml || true
echo

echo "== Check for backendProject/Dockerfile =="
if [ -f backendProject/Dockerfile ]; then
  echo "Found backendProject/Dockerfile - showing up to 300 lines:"
  sed -n '1,300p' backendProject/Dockerfile || true
else
  echo "backendProject/Dockerfile not found. Searching for Dockerfiles and relevant keywords in repo..."
  rg -n --hidden --glob '!.git' '(^FROM)|HEALTHCHECK|curl|wget|bash' || true
fi

Length of output: 4134


API 컨테이너에 restart 정책 추가 및 HEALTHCHECK 적용 필요 — 수정 필요

검증 결과: docker-compose-prod.yml의 api1/api2에 restart 정책이 빠져 있고, backendProject/Dockerfile(runtime: openjdk:17-jre-slim)에는 HEALTHCHECK가 주석 처리되어 있어 현재 헬스체크가 동작하지 않습니다. 아래 변경을 권장합니다.

주의할 점:

  • Spring Actuator를 사용 중이면 헬스 엔드포인트(/actuator/health 등)를 확인해 HEALTHCHECK 경로를 맞춰주세요.
  • 이미지에 curl/wget이 없으면 A 옵션 대신 B(TCP) 옵션을 사용하거나 Dockerfile에 curl을 설치하세요.

수정 대상:

  • docker-compose-prod.yml: api1, api2에 restart 정책 추가
  • backendProject/Dockerfile: runtime stage에 HEALTHCHECK 추가(옵션 A: curl 사용 / 옵션 B: TCP 검사)

제안된 변경(diff 예시)

docker-compose-prod.yml (간단 변경)

   api1:
     build:
       context: ./backendProject
     container_name: mlb-api-1
+    restart: unless-stopped
     ports:
       - "8080:8080"
@@
   api2:
     build:
       context: ./backendProject
     container_name: mlb-api-2
+    restart: unless-stopped
     ports:
       - "8081:8080"

backendProject/Dockerfile — Option A (curl 설치 후 Actuator 엔드포인트 검사)

FROM openjdk:17-jre-slim
WORKDIR /app
ENV JAVA_TOOL_OPTIONS="-XX:+UseG1GC -Xms256m -Xmx512m"

# curl 설치
RUN apt-get update && apt-get install -y --no-install-recommends curl \
 && rm -rf /var/lib/apt/lists/*

COPY --from=builder /app/build/libs/*.jar /app/app.jar
EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD curl -fsS http://localhost:8080/actuator/health || exit 1

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

backendProject/Dockerfile — Option B (추가 패키지 없이 TCP 포트 확인)

FROM openjdk:17-jre-slim
WORKDIR /app
ENV JAVA_TOOL_OPTIONS="-XX:+UseG1GC -Xms256m -Xmx512m"

COPY --from=builder /app/build/libs/*.jar /app/app.jar
EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD-SHELL "echo > /dev/tcp/127.0.0.1/8080" || exit 1

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

간단 요청: 어떤 HEALTHCHECK 방식을 선호하는지(Actuator 엔드포인트 사용 / TCP 검사 / curl 설치) 알려주시면 Dockerfile 예시를 그에 맞춰 조정해 드리겠습니다.

Comment thread docker-compose-prod.yml
Comment on lines +23 to +40
api2:
build:
context: ./backendProject
container_name: mlb-api-2
ports:
- "8081:8080"
env_file:
- .env
depends_on:
mlb-redis1:
condition: service_healthy
mlb-elasticsearch:
condition: service_healthy
mlb-kafka:
condition: service_healthy
networks:
- backend

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

두 번째 API 컨테이너도 동일하게 재시작 정책과 헬스체크 정렬

api2에도 동일 정책을 적용해 이중화 시 한쪽 다운 시 자동 복구를 보장하세요.

  api2:
     build:
       context: ./backendProject
     container_name: mlb-api-2
+    restart: unless-stopped
     ports:
       - "8081:8080"
📝 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
api2:
build:
context: ./backendProject
container_name: mlb-api-2
ports:
- "8081:8080"
env_file:
- .env
depends_on:
mlb-redis1:
condition: service_healthy
mlb-elasticsearch:
condition: service_healthy
mlb-kafka:
condition: service_healthy
networks:
- backend
api2:
build:
context: ./backendProject
container_name: mlb-api-2
restart: unless-stopped
ports:
- "8081:8080"
env_file:
- .env
depends_on:
mlb-redis1:
condition: service_healthy
mlb-elasticsearch:
condition: service_healthy
mlb-kafka:
condition: service_healthy
networks:
- backend
🤖 Prompt for AI Agents
In docker-compose-prod.yml around lines 23 to 40, api2 is missing the same
restart policy and healthcheck configuration used for the other API container;
add a restart policy (e.g., restart: unless-stopped or restart: always) and a
healthcheck block mirroring the existing API service (providing test, interval,
timeout, retries and start_period) so the service can be auto-restarted and
marked healthy/unhealthy for failover; ensure the new healthcheck uses the same
command/port and timing values as the other API to keep behavior consistent.

Comment thread docker-compose-prod.yml
Comment on lines +71 to +94
# Elasticsearch
mlb-elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.13.4
container_name: mlb-elasticsearch
environment:
- node.name=es01
- discovery.type=single-node
- xpack.security.enabled=false
- xpack.security.transport.ssl.enabled=false
- ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
- "9200:9200"
- "9300:9300"
volumes:
- es_data:/usr/share/elasticsearch/data
healthcheck:
# TCP 열림 확인(의존 패키지 없이 동작)
test: ["CMD-SHELL", "bash -lc 'echo > /dev/tcp/127.0.0.1/9200'"]
interval: 10s
timeout: 3s
retries: 30
networks:
- backend

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Elasticsearch 보안/노출 설정 점검 필요: xpack 비활성화 + 포트 외부 공개는 프로덕션에서는 위험

  • xpack.security 비활성화 상태에서 9200/9300을 호스트로 노출하고 있어 외부 접근이 가능해집니다. 내부 네트워크에서만 접근하도록 포트 노출 제거 또는 보안 그룹/방화벽 제한을 권장합니다.
  • 헬스체크가 bash의 /dev/tcp 의존(“bash -lc”)에 묶여 있습니다. 이미지에 bash가 없으면 실패합니다. 가능하면 HTTP 핑(curl/wget)을 사용하거나 Dockerfile에 HEALTHCHECK를 정의하세요.

예시(포트 외부 미노출):

   mlb-elasticsearch:
     image: docker.elastic.co/elasticsearch/elasticsearch:8.13.4
     container_name: mlb-elasticsearch
@@
-    ports:
-      - "9200:9200"
-      - "9300:9300"
+    # 내부 통신만 필요하다면 포트 노출 제거 권장
+    # ports:
+    #  - "9200:9200"
+    #  - "9300:9300"

보안을 유지해야 하는 프로덕션이라면:

  • xpack.security.enabled=true로 전환하고 사용자/비밀번호 설정, TLS 구성 고려.
  • 외부 노출 시 보안 그룹/방화벽으로 접근 제한 필수.

긴급: docker-compose-prod.yml — Elasticsearch 보안과 헬스체크 수정 필요

검증 결과: 원 리뷰의 우려가 타당합니다. 현재 구성(xpack 비활성화 + 9200/9300 호스트 노출, bash 기반 헬스체크)은 프로덕션에서 위험합니다.

파일/위치

  • docker-compose-prod.yml — Lines 71-94 (서비스: mlb-elasticsearch)

문제 요약

  • environment에서 xpack.security.enabled=false 및 xpack.security.transport.ssl.enabled=false — 보안 비활성화 상태.
  • ports에 "9200:9200", "9300:9300" — 호스트에 포트가 노출되어 외부 접근 가능.
  • healthcheck가 "bash -lc 'echo > /dev/tcp/127.0.0.1/9200'"에 의존 — 이미지에 bash/해당 기능이 없으면 실패 가능.

권장 조치 (우선순위)

  • 프로덕션에서는 xpack.security.enabled=true 및 transport TLS 활성화(xpack.security.transport.ssl.enabled=true)로 전환하고 사용자/비밀번호와 TLS(인증서) 설정을 반드시 구성하세요.
  • 호스트 노출 제거: ports 매핑 제거 또는 내부 전용(expose 또는 네트워크 격리) 사용. 외부 노출이 필요하면 보안 그룹/방화벽으로 접근을 제한하세요.
  • 헬스체크 수정: bash-/dev/tcp 의존을 제거하고 HTTP 엔드포인트(예: /_cluster/health)를 이용한 체크로 교체하거나, 필요한 바이너리(curl/wget)를 포함해 Dockerfile에서 헬스체크를 정의하세요.

권장 변경 예시

   mlb-elasticsearch:
     image: docker.elastic.co/elasticsearch/elasticsearch:8.13.4
     container_name: mlb-elasticsearch
     environment:
       - node.name=es01
       - discovery.type=single-node
-      - xpack.security.enabled=false
-      - xpack.security.transport.ssl.enabled=false
+      # 프로덕션: 보안 활성화 권장 (추가 설정 필요: 계정/비밀번호, TLS 인증서)
+      - xpack.security.enabled=true
+      - xpack.security.transport.ssl.enabled=true
@@
-    ports:
-      - "9200:9200"
-      - "9300:9300"
+    # 내부 통신만 필요하면 호스트 포트 노출 제거 또는 expose 사용
+    # ports:
+    #  - "9200:9200"
+    #  - "9300:9300"
@@
-    healthcheck:
-      test: ["CMD-SHELL", "bash -lc 'echo > /dev/tcp/127.0.0.1/9200'"]
+    healthcheck:
+      # 이미지에 curl/wget이 없을 수 있으므로 Dockerfile에서 헬스체크 정의 고려
+      test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:9200/_cluster/health || exit 1"]

짧게 요약하면: 현재 설정은 프로덕션 환경에 부적합합니다. 보안 활성화, 포트 노출 제거/제한, 헬스체크 방법 개선을 적용해 주세요.

📝 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
# Elasticsearch
mlb-elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.13.4
container_name: mlb-elasticsearch
environment:
- node.name=es01
- discovery.type=single-node
- xpack.security.enabled=false
- xpack.security.transport.ssl.enabled=false
- ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
- "9200:9200"
- "9300:9300"
volumes:
- es_data:/usr/share/elasticsearch/data
healthcheck:
# TCP 열림 확인(의존 패키지 없이 동작)
test: ["CMD-SHELL", "bash -lc 'echo > /dev/tcp/127.0.0.1/9200'"]
interval: 10s
timeout: 3s
retries: 30
networks:
- backend
# Elasticsearch
mlb-elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.13.4
container_name: mlb-elasticsearch
environment:
- node.name=es01
- discovery.type=single-node
# 프로덕션: 보안 활성화 권장 (추가 설정 필요: 계정/비밀번호, TLS 인증서)
- xpack.security.enabled=true
- xpack.security.transport.ssl.enabled=true
- ES_JAVA_OPTS=-Xms512m -Xmx512m
# 내부 통신만 필요하면 호스트 포트 노출 제거 또는 expose 사용
# ports:
# - "9200:9200"
# - "9300:9300"
volumes:
- es_data:/usr/share/elasticsearch/data
healthcheck:
# 이미지에 curl/wget이 없을 수 있으므로 Dockerfile에서 헬스체크 정의 고려
test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:9200/_cluster/health || exit 1"]
interval: 10s
timeout: 3s
retries: 30
networks:
- backend
🤖 Prompt for AI Agents
In docker-compose-prod.yml around lines 71-94 (service: mlb-elasticsearch), the
compose disables Elasticsearch security, exposes 9200/9300 to the host, and uses
a fragile bash /dev/tcp healthcheck; update this for production by enabling
xpack (set xpack.security.enabled=true and
xpack.security.transport.ssl.enabled=true) and ensure you provision TLS certs
and Elasticsearch users/passwords (or integrate with a secrets store), remove
the host port mappings (delete "9200:9200" and "9300:9300" or replace with
expose + internal network only / firewall rules) so ES is not directly reachable
from the host network, and replace the healthcheck with an HTTP-based check
(call /_cluster/health or /_node/health with curl/wget) or ensure the image
provides a supported healthcheck binary rather than relying on bash /dev/tcp.

@roode1017
roode1017 merged commit 8b7e888 into dev Aug 14, 2025
1 check passed
@roode1017
roode1017 deleted the feat/#59 branch August 14, 2025 05:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat / 배포를 위한 코드 수정 2

1 participant