-
Notifications
You must be signed in to change notification settings - Fork 1
[REFACTOR] 인프라 구조를 Docker로 전환 #237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
c3c30b9
89415ed
9bde176
6cbfb9e
e95dcc1
a3043fb
5d85094
4ab47ed
afef700
20cce50
4cb4824
8de6dbf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| FROM eclipse-temurin:17-jdk-alpine AS builder | ||
| WORKDIR /workspace | ||
| ARG JAR_FILE=build/libs/*.jar | ||
| COPY ${JAR_FILE} app.jar | ||
| RUN java -Djarmode=layertools -jar app.jar extract | ||
|
|
||
| FROM eclipse-temurin:17-jre-alpine | ||
leegwichan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| WORKDIR /workspace | ||
|
|
||
| ADD https://dtdg.co/latest-java-tracer ./dd-java-agent.jar | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: Latest Datadog
Sources: GitHub releases list (DataDog/dd-trace-java) [1] plus per-version Maven Central publish dates via MvnRepository [2]-[10]. 🌐 Web query:
💡 Result: Best practices for checksum verification with
|
||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 문서화할 때 지금 전부다 jar로 마는 거랑 얼마나 효율화되었는지 수치로 나타내봐도 좋을듯! |
||
| COPY --from=builder /workspace/dependencies/ ./ | ||
| COPY --from=builder /workspace/spring-boot-loader/ ./ | ||
| COPY --from=builder /workspace/snapshot-dependencies/ ./ | ||
| COPY --from=builder /workspace/application/ ./ | ||
|
|
||
| ENTRYPOINT ["java", "-javaagent:./dd-java-agent.jar", "org.springframework.boot.loader.launch.JarLauncher"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| services: | ||
| datadog-agent: | ||
| image: gcr.io/datadoghq/agent:7 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| container_name: datadog-agent | ||
| environment: | ||
| - DD_API_KEY=${DD_API_KEY} | ||
| - DD_SITE=us5.datadoghq.com | ||
| - DD_APM_ENABLED=true | ||
| - DD_APM_NON_LOCAL_TRAFFIC=true | ||
| - DD_APM_IGNORE_RESOURCES=/monitoring/health | ||
| - DD_DOGSTATSD_NON_LOCAL_TRAFFIC=true | ||
| - DD_LOGS_ENABLED=true | ||
| - DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true | ||
| - DD_PROCESS_AGENT_ENABLED=true | ||
| - DD_TAGS=env:${ENV:-dev},project:debate-timer | ||
| ports: | ||
| - "8125:8125/udp" # Metrics (StatsD) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 일단 데이터독 docker compose 이미지로 만드니까 확실히 문서화 효과가 있어서 좋은 것 같아유. 그런데 데이터 독 배경지식이 없어서 그런데 메트릭은 udp, apm은 tcp로 소통하는 이유가 있나요? 아니면 데이터 독 자체 스펙인가?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 추후 문서화 예정이라 대략적인 제미나이의 답변 공유드립니다. 1. 포트 8125 (UDP) - DogStatsD (Metrics)
2. 포트 8126 (TCP) - Trace Agent (APM)
|
||
| - "8126:8126/tcp" # APM (Trace) | ||
| volumes: | ||
| - /var/run/docker.sock:/var/run/docker.sock:ro # 로그 수집 필수 | ||
| - /proc/:/host/proc/:ro | ||
| - /sys/fs/cgroup/:/host/sys/fs/cgroup/:ro | ||
| networks: | ||
| - debate-timer-net | ||
| healthcheck: | ||
| test: ["CMD", "agent", "health"] | ||
| interval: 60s | ||
| timeout: 10s | ||
| retries: 5 | ||
| start_period: 120s | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| x-app-template: &app-template | ||
| image: debatetimer/debate_timer:${ENV:-dev} | ||
| environment: | ||
| - SERVER_FORWARD_HEADERS_STRATEGY=framework | ||
| - SPRING_PROFILES_ACTIVE=${PROFILE:-dev,monitor} | ||
| - TZ=Asia/Seoul | ||
|
|
||
| - DD_AGENT_HOST=datadog-agent | ||
| - DD_SERVICE=debate-timer | ||
| - DD_ENV=${ENV:-dev} | ||
| - DD_VERSION=1.0.0 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| - DD_LOGS_INJECTION=true | ||
| - DD_PROFILING_ENABLED=true | ||
| - DD_PROFILING_ALLOCATION_ENABLED=true | ||
| - DD_PROFILING_HEAP_ENABLED=true | ||
|
|
||
| - MANAGEMENT_STATSD_METRICS_EXPORT_ENABLED=true | ||
| - MANAGEMENT_STATSD_METRICS_EXPORT_FLAVOR=datadog | ||
| - MANAGEMENT_STATSD_METRICS_EXPORT_HOST=datadog-agent | ||
| - MANAGEMENT_STATSD_METRICS_EXPORT_PORT=8125 | ||
| - MANAGEMENT_STATSD_METRICS_EXPORT_PROTOCOL=UDP | ||
|
|
||
| networks: | ||
| - debate-timer-net | ||
|
|
||
| depends_on: | ||
| traefik: | ||
| condition: service_healthy | ||
| datadog-agent: | ||
| condition: service_healthy | ||
|
|
||
| healthcheck: | ||
| test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8083/monitoring/health" ] | ||
| interval: 60s | ||
| retries: 5 | ||
| start_period: 300s | ||
leegwichan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| services: | ||
| app-blue: | ||
| <<: *app-template | ||
| container_name: app-blue | ||
| labels: | ||
| - "traefik.enable=true" | ||
| - "traefik.http.routers.app-blue.rule=Host(`api.${ENV:-dev}.debate-timer.com`)" | ||
| - "traefik.http.routers.app-blue.entrypoints=websecure" | ||
| - "traefik.http.routers.app-blue.tls=true" | ||
| - "traefik.http.routers.app-blue.tls.certresolver=myresolver" | ||
| - "traefik.http.services.app-blue.loadbalancer.server.port=8080" | ||
| - "traefik.http.routers.app-blue.service=app-blue" | ||
|
|
||
| - "traefik.http.routers.app-blue-monitor.rule=PathPrefix(`/`)" | ||
| - "traefik.http.routers.app-blue-monitor.entrypoints=monitoring" | ||
| - "traefik.http.routers.app-blue-monitor.service=app-blue-monitor-svc" | ||
| - "traefik.http.services.app-blue-monitor-svc.loadbalancer.server.port=8083" | ||
|
|
||
| - "com.datadoghq.ad.logs=[{\"source\": \"java\", \"service\": \"debate-timer\"}]" | ||
|
|
||
| app-green: | ||
| <<: *app-template | ||
| container_name: app-green | ||
| labels: | ||
| - "traefik.enable=true" | ||
| - "traefik.http.routers.app-green.rule=Host(`api.${ENV:-dev}.debate-timer.com`)" | ||
| - "traefik.http.routers.app-green.entrypoints=websecure" | ||
| - "traefik.http.routers.app-green.tls=true" | ||
| - "traefik.http.routers.app-green.tls.certresolver=myresolver" | ||
leegwichan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - "traefik.http.services.app-green.loadbalancer.server.port=8080" | ||
| - "traefik.http.routers.app-green.service=app-green" | ||
|
|
||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - "traefik.http.routers.app-green-monitor.rule=PathPrefix(`/`)" | ||
| - "traefik.http.routers.app-green-monitor.entrypoints=monitoring" | ||
| - "traefik.http.routers.app-green-monitor.service=app-green-monitor-svc" | ||
| - "traefik.http.services.app-green-monitor-svc.loadbalancer.server.port=8083" | ||
|
|
||
| - "com.datadoghq.ad.logs=[{\"source\": \"java\", \"service\": \"debate-timer\"}]" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| services: | ||
| traefik: | ||
| image: traefik:v2.11 | ||
| container_name: traefik | ||
| ports: | ||
| - "80:80" | ||
| - "443:443" | ||
| - "8080:8080" | ||
| - "8083:8083" | ||
| environment: | ||
| - DOCKER_API_VERSION=1.44 | ||
| command: | ||
| - "--api.insecure=true" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| - "--ping=true" | ||
| - "--log.level=INFO" | ||
| - "--providers.docker=true" | ||
| - "--providers.docker.exposedbydefault=false" | ||
|
|
||
| - "--entrypoints.web.address=:80" | ||
| - "--entrypoints.web.http.redirections.entryPoint.to=websecure" | ||
| - "--entrypoints.web.http.redirections.entryPoint.scheme=https" | ||
| - "--entrypoints.websecure.address=:443" | ||
|
|
||
| - "--certificatesresolvers.myresolver.acme.tlschallenge=true" | ||
| - "--certificatesresolvers.myresolver.acme.email=debatetimekeeping@gmail.com" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 내 이메일 주소 ㅠㅠ Certbot 없이 자동으로 발급받고 관리해주네... 미쳤다.. 확실히 편한듯
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 노출되고 크게 문제 없는 정보니까, 이렇게 그대로 해도 되겠죠? -> 그대로 가도 괜찮을듯 ㅇㅇ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" | ||
|
|
||
| - "--entrypoints.monitoring.address=:8083" | ||
| healthcheck: | ||
| test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8080/ping"] | ||
leegwichan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| interval: 60s | ||
| timeout: 10s | ||
| retries: 5 | ||
| start_period: 120s | ||
| volumes: | ||
| - /var/run/docker.sock:/var/run/docker.sock:ro | ||
| - ../letsencrypt:/letsencrypt | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
- letsencrypt:/letsencrypt |
||
| networks: | ||
| - debate-timer-net | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 단순 질문입니다.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yml 하고 yaml 하고 차이 없어서 아무거나 사용했습니다.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
비토 의견
비토/커찬 논의 결론
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 개인의견) 이건 진짜 개인 취향 문제라 생각하긴 하는디... 나는 개인적으로 각 docker compose의 목적이 다르기 때문에 모듈화해두는게 좋다고 생각하기는 하는 것 같아. 단일 파일로 실행할 가능성은 거의 없지만 커밋 내역이나 diff에서도 어떤 파일이 수정되었는지를 기반으로 chnage 추적하기 더 쉬울 것 같기도 함(대충 이 compose 수정되었으면 ~~ 컴포넌트에 수정 있었겠구나를 들어가보지 않고 일단 인지하게 되니까) 또 application-local, application-dev 처럼 하나의 app 컴포넌트 내에서 프로파일이나 성격별로 분리하는게 아니라 각자 별도의 역할을 가진 컴포넌트라는 점에서 분리는 지향되어야 한다고 생각함.
물론 프로젝트 진행 속도나 인프라 변경이 잦지 않다는 특성을 고려하면 한파일 내에서 모두 모아두어도 추후 유지보수에는 큰 문제는 없을 것 같긴 해서 이건 강하게 주장 못하겠음.. 하위폴더:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 만약에 docker-compose랑 그 하위 파일들까지 전부 나눠서 관리 할 것이라면, Dockerfile 도 다른 폴더로 나눠서 관리하는게 좀 더 통일될 것 같다는 생각이 듦 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| name: debate-timer-server | ||
|
|
||
| include: | ||
| - docker-compose.traefik.yml | ||
| - docker-compose.spring.yml | ||
| - docker-compose.datadog.yml | ||
|
|
||
| networks: | ||
| debate-timer-net: | ||
| name: debate-timer-net | ||
| driver: bridge |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| #!/bin/bash | ||
|
|
||
| set -e # 스크립트 실행 중 에러 발생 시 즉시 중단 (안전 장치) | ||
|
|
||
| # --- 설정 변수 --- | ||
| SWAP_FILE="/swapfile" | ||
| SWAP_SIZE=${1:-"2G"} | ||
| FSTAB_FILE="/etc/fstab" | ||
|
Comment on lines
5
to
8
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 도커 설치하는 스크립트처럼 최소한 SWAP_SIZE 만이라도 입력으로 받는 건 어떤가요?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네, 반영하겠습니다~ |
||
|
|
||
| # 1. 루트 권한 확인 | ||
| if [ "$EUID" -ne 0 ]; then | ||
| echo "오류: 이 스크립트는 root 권한(sudo)으로 실행해야 합니다." | ||
| exit 1 | ||
| fi | ||
|
|
||
| # 2. 기존 스왑 파일 존재 여부 확인 | ||
| if [ -f "$SWAP_FILE" ]; then | ||
| echo "알림: $SWAP_FILE 이 이미 존재합니다." | ||
| echo "작업을 중단합니다." | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "=== Swap 메모리 생성 시작 ($SWAP_SIZE) ===" | ||
|
|
||
| # 3. Swap 파일 생성 | ||
| fallocate -l $SWAP_SIZE $SWAP_FILE | ||
| echo " -> 파일 생성 완료" | ||
|
|
||
| # 4. 권한 설정 (600) | ||
| chmod 600 $SWAP_FILE | ||
| echo " -> 권한 설정 완료" | ||
|
|
||
| # 5. Swap 활성화 | ||
| mkswap $SWAP_FILE > /dev/null | ||
| swapon $SWAP_FILE | ||
| echo " -> Swap 활성화 완료" | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # 6. /etc/fstab 등록 (재부팅 후에도 유지) | ||
| if ! grep -q "$SWAP_FILE" "$FSTAB_FILE"; then | ||
| echo "$SWAP_FILE swap swap defaults 0 0" >> "$FSTAB_FILE" | ||
| echo " -> fstab 등록 완료 (자동 실행 설정)" | ||
| fi | ||
|
|
||
| echo "=== 모든 작업이 완료되었습니다 ===" | ||
| echo "[현재 메모리 상태]" | ||
| free -h | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #!/bin/bash | ||
|
|
||
| set -e # 스크립트 실행 중 에러 발생 시 즉시 중단 (안전 장치) | ||
|
|
||
| DOCKER_USER=$1 | ||
| DOCKER_TOKEN=$2 | ||
|
|
||
| echo "=== Docker 설치를 시작합니다 ===" | ||
|
|
||
| echo "1. 필수 패키지 설치 및 GPG 키 설정 진행" | ||
| sudo apt-get update | ||
| sudo apt-get install -y ca-certificates curl gnupg | ||
| sudo install -m 0755 -d /etc/apt/keyrings | ||
| curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg --yes | ||
| sudo chmod a+r /etc/apt/keyrings/docker.gpg | ||
|
|
||
| echo "2. 리포지토리 설정 진행" | ||
| echo \ | ||
| "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ | ||
| $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ | ||
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null | ||
|
|
||
| echo "3. Docker Engine 설치 진행" | ||
| sudo apt-get update | ||
| sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin | ||
|
|
||
| echo "4. 사용자 권한 설정 진행" | ||
| sudo usermod -aG docker $USER | ||
|
|
||
| echo "5. 로그인 진행 (변수 입력했을 경우에만)" | ||
| if [ -n "$DOCKER_USER" ] && [ -n "$DOCKER_TOKEN" ]; then | ||
| echo "입력된 정보로 Docker Hub 로그인을 시도합니다..." | ||
|
|
||
| if echo "$DOCKER_TOKEN" | sg docker -c "docker login -u \"$DOCKER_USER\" --password-stdin"; then | ||
| echo "✅ 로그인 성공! (config.json이 생성되었습니다)" | ||
| else | ||
| echo "❌ 로그인 실패. 아이디/토큰을 확인하거나 'newgrp docker' 후 다시 시도하세요." | ||
| fi | ||
| else | ||
| echo "로그인 정보가 입력되지 않아 로그인을 건너뜁니다." | ||
| echo "추후 'docker login' 명령어로 로그인하세요." | ||
| fi | ||
|
|
||
| echo "6. Docker 권한이 적용된 새로운 쉘로 전환" | ||
| exec newgrp docker |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #!/bin/bash | ||
|
|
||
| cd "$(dirname "$0")" || exit 1 | ||
|
|
||
| mkdir -p ../../letsencrypt | ||
| touch ../../letsencrypt/acme.json | ||
| chmod 600 ../../letsencrypt/acme.json | ||
|
|
||
| echo "✅ 스크립트 위치($(pwd))에 letsencrypt 폴더를 생성했습니다." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
음..의존성 변경의 의미가 수집하여 반환하는 형식이 변경되었다~ 정도로 이해하고 있는데 맞을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
맞아요~ 기존에는 Datadog Agent가 WAS에 요청을 보내서 가져가는 형식이었음
이번에는 WAS에서 Datadog Agent로 보내는 형식으로 변경함 (블루-그린 적용해도 로그 수집이 원활이 되도록 함)