From c3c30b9db05c6f9cffb47b5d31be7689b3afc060 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Wed, 28 Jan 2026 18:17:18 +0900 Subject: [PATCH 01/12] =?UTF-8?q?feat:=20Traefik=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.spring.yaml | 34 ++++++++++++++++++++++++++++++ docker/docker-compose.traefik.yaml | 28 ++++++++++++++++++++++++ docker/docker-compose.yaml | 12 +++++++++++ 3 files changed, 74 insertions(+) create mode 100644 docker/docker-compose.spring.yaml create mode 100644 docker/docker-compose.traefik.yaml create mode 100644 docker/docker-compose.yaml diff --git a/docker/docker-compose.spring.yaml b/docker/docker-compose.spring.yaml new file mode 100644 index 0000000..d3b1e22 --- /dev/null +++ b/docker/docker-compose.spring.yaml @@ -0,0 +1,34 @@ +services: + app-blue: + image: my-app:latest + container_name: app-blue + labels: + - "traefik.enable=true" + - "traefik.http.routers.app-blue.rule=Host(`test.debate-timer.com`)" + - "traefik.http.services.app-blue.loadbalancer.server.port=8080" + - "traefik.http.routers.app-blue.entrypoints=websecure" + - "traefik.http.routers.app-blue.tls=true" + - "traefik.http.routers.app-blue.tls.certresolver=myresolver" + networks: + - web-gateway + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] + interval: 10s + retries: 3 + + app-green: + image: my-app:latest + container_name: app-green + labels: + - "traefik.enable=true" + - "traefik.http.routers.app-green.rule=Host(`test.debate-timer.com`)" + - "traefik.http.services.app-green.loadbalancer.server.port=8080" + - "traefik.http.routers.app-green.entrypoints=websecure" + - "traefik.http.routers.app-green.tls=true" + - "traefik.http.routers.app-green.tls.certresolver=myresolver" + networks: + - web-gateway + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] + interval: 10s + retries: 3 diff --git a/docker/docker-compose.traefik.yaml b/docker/docker-compose.traefik.yaml new file mode 100644 index 0000000..125ad3b --- /dev/null +++ b/docker/docker-compose.traefik.yaml @@ -0,0 +1,28 @@ +services: + traefik: + image: traefik:v3.0 + ports: + - "80:80" + - "443:443" + - "8080:8080" + command: + # 1. 기본 설정 + - "--api.insecure=true" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + + # 2. EntryPoints 설정 (HTTP -> HTTPS 리다이렉트) + - "--entrypoints.web.address=:80" + - "--entrypoints.web.http.redirections.entryPoint.to=websecure" + - "--entrypoints.web.http.redirections.entryPoint.scheme=https" + - "--entrypoints.websecure.address=:443" + + # 3. 인증서 발급 설정 (Let's Encrypt) + - "--certificatesresolvers.myresolver.acme.tlschallenge=true" + - "--certificatesresolvers.myresolver.acme.email=debatetimekepping@gmail.com" + - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./letsencrypt:/letsencrypt + networks: + - web-gateway diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml new file mode 100644 index 0000000..319118e --- /dev/null +++ b/docker/docker-compose.yaml @@ -0,0 +1,12 @@ +version: '4.5' + +name: debate-timer-server + +include: + - docker-compose.traefik.yaml + - docker-compose.spring.yaml + +networks: + web-gateway: + name: web-gateway + driver: bridge From 89415ed612477f8dd52c149416ab32a8799e4693 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Wed, 28 Jan 2026 18:20:26 +0900 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20Traefik=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 319118e..6b106ce 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -1,5 +1,3 @@ -version: '4.5' - name: debate-timer-server include: From 9bde176eb551aaf94ef99551d7cf94a09feb6647 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Tue, 3 Feb 2026 15:16:55 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20Dockerfile=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++++ docker/Dockerfile | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 docker/Dockerfile diff --git a/build.gradle b/build.gradle index e0a42d5..aa7cfcb 100644 --- a/build.gradle +++ b/build.gradle @@ -81,6 +81,10 @@ bootJar { dependsOn("openapi3") } +jar { + enabled = false +} + jacoco { toolVersion = '0.8.9' } diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..6515f18 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,15 @@ +FROM openjdk:17-jdk-slim as builder +WORKDIR /workspace +ARG JAR_FILE=build/libs/*.jar +COPY ${JAR_FILE} app.jar +RUN java -Djarmode=layertools -jar app.jar extract + +FROM openjdk:17-jdk-slim +WORKDIR /workspace + +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", "org.springframework.boot.loader.launch.JarLauncher"] \ No newline at end of file From 6cbfb9e9d9ebafbc3049a2e92bf60905eeb822fd Mon Sep 17 00:00:00 2001 From: leegwichan Date: Tue, 3 Feb 2026 18:50:13 +0900 Subject: [PATCH 04/12] =?UTF-8?q?feat:=20=EC=84=9C=EB=B2=84=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=20=EC=84=B8=ED=8C=85=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20(=EC=8A=A4=EC=99=91=20=EB=A9=94=EB=AA=A8=EB=A6=AC,?= =?UTF-8?q?=20=EB=8F=84=EC=BB=A4=20=EC=84=B8=ED=8C=85)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/init/auto_swap.sh | 45 ++++++++++++++++++++++++++++++++++++ scripts/init/init_docker.sh | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 scripts/init/auto_swap.sh create mode 100644 scripts/init/init_docker.sh diff --git a/scripts/init/auto_swap.sh b/scripts/init/auto_swap.sh new file mode 100644 index 0000000..2c621c5 --- /dev/null +++ b/scripts/init/auto_swap.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# --- 설정 변수 --- +SWAP_FILE="/swapfile" +SWAP_SIZE="2G" +FSTAB_FILE="/etc/fstab" + +# 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 활성화 완료" + +# 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 "" +echo "[현재 메모리 상태]" +free -h \ No newline at end of file diff --git a/scripts/init/init_docker.sh b/scripts/init/init_docker.sh new file mode 100644 index 0000000..9f9a8b5 --- /dev/null +++ b/scripts/init/init_docker.sh @@ -0,0 +1,46 @@ +#!/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 로그인을 시도합니다..." + echo "$DOCKER_TOKEN" | sg docker -c "docker login -u $DOCKER_USER --password-stdin" + + if [ $? -eq 0 ]; then + echo "✅ 로그인 성공! (config.json이 생성되었습니다)" + else + echo "❌ 로그인 실패. 아이디/토큰을 확인하거나 'newgrp docker' 후 다시 시도하세요." + fi +else + echo "로그인 정보가 입력되지 않아 로그인을 건너뜁니다." + echo "추후 'docker login' 명령어로 로그인하세요." +fi + +echo "6. Docker 권한이 적용된 새로운 쉘로 전환" +exec newgrp docker \ No newline at end of file From e95dcc1017b2bbc399d07aaca0a685dee7ba4fbb Mon Sep 17 00:00:00 2001 From: leegwichan Date: Tue, 3 Feb 2026 20:35:35 +0900 Subject: [PATCH 05/12] =?UTF-8?q?fix:=20docker=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/Dockerfile | 6 +++--- docker/docker-compose.spring.yaml | 16 ++++++++++------ docker/docker-compose.traefik.yaml | 6 +++++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 6515f18..cad80f3 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,10 +1,10 @@ -FROM openjdk:17-jdk-slim as builder +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 openjdk:17-jdk-slim +FROM eclipse-temurin:17-jre-alpine WORKDIR /workspace COPY --from=builder /workspace/dependencies/ ./ @@ -12,4 +12,4 @@ COPY --from=builder /workspace/spring-boot-loader/ ./ COPY --from=builder /workspace/snapshot-dependencies/ ./ COPY --from=builder /workspace/application/ ./ -ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"] \ No newline at end of file +ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"] diff --git a/docker/docker-compose.spring.yaml b/docker/docker-compose.spring.yaml index d3b1e22..085bfa2 100644 --- a/docker/docker-compose.spring.yaml +++ b/docker/docker-compose.spring.yaml @@ -1,10 +1,10 @@ services: app-blue: - image: my-app:latest + image: debatetimer/debate_timer:${TAG:-latest} container_name: app-blue labels: - "traefik.enable=true" - - "traefik.http.routers.app-blue.rule=Host(`test.debate-timer.com`)" + - "traefik.http.routers.app-blue.rule=Host(`api.test.debate-timer.com`)" - "traefik.http.services.app-blue.loadbalancer.server.port=8080" - "traefik.http.routers.app-blue.entrypoints=websecure" - "traefik.http.routers.app-blue.tls=true" @@ -12,16 +12,16 @@ services: networks: - web-gateway healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/actuator/health"] interval: 10s retries: 3 app-green: - image: my-app:latest + image: debatetimer/debate_timer:${TAG:-latest} container_name: app-green labels: - "traefik.enable=true" - - "traefik.http.routers.app-green.rule=Host(`test.debate-timer.com`)" + - "traefik.http.routers.app-green.rule=Host(`api.test.debate-timer.com`)" - "traefik.http.services.app-green.loadbalancer.server.port=8080" - "traefik.http.routers.app-green.entrypoints=websecure" - "traefik.http.routers.app-green.tls=true" @@ -29,6 +29,10 @@ services: networks: - web-gateway healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/actuator/health"] interval: 10s retries: 3 + +networks: + web-gateway: + external: true diff --git a/docker/docker-compose.traefik.yaml b/docker/docker-compose.traefik.yaml index 125ad3b..a283ace 100644 --- a/docker/docker-compose.traefik.yaml +++ b/docker/docker-compose.traefik.yaml @@ -19,10 +19,14 @@ services: # 3. 인증서 발급 설정 (Let's Encrypt) - "--certificatesresolvers.myresolver.acme.tlschallenge=true" - - "--certificatesresolvers.myresolver.acme.email=debatetimekepping@gmail.com" + - "--certificatesresolvers.myresolver.acme.email=debatetimekeeping@gmail.com" - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt networks: - web-gateway + +networks: + web-gateway: + external: true From a3043fb14dcf61acdb666444805996c7b57c5d7e Mon Sep 17 00:00:00 2001 From: leegwichan Date: Wed, 4 Feb 2026 14:46:02 +0900 Subject: [PATCH 06/12] =?UTF-8?q?fix:=20docker=20=EC=8B=A4=ED=96=89?= =?UTF-8?q?=EC=9D=B4=20=EC=A0=95=EC=83=81=20=EC=9E=91=EB=8F=99=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.spring.yaml | 38 ++++++++++++++----- docker/docker-compose.traefik.yaml | 28 +++++++++----- docker/docker-compose.yaml | 5 ++- scripts/init/{auto_swap.sh => auto-swap.sh} | 0 .../init/{init_docker.sh => init-docker.sh} | 0 scripts/init/init-letsencrypt.sh | 9 +++++ 6 files changed, 59 insertions(+), 21 deletions(-) rename scripts/init/{auto_swap.sh => auto-swap.sh} (100%) rename scripts/init/{init_docker.sh => init-docker.sh} (100%) create mode 100644 scripts/init/init-letsencrypt.sh diff --git a/docker/docker-compose.spring.yaml b/docker/docker-compose.spring.yaml index 085bfa2..46a9063 100644 --- a/docker/docker-compose.spring.yaml +++ b/docker/docker-compose.spring.yaml @@ -2,23 +2,38 @@ services: app-blue: image: debatetimer/debate_timer:${TAG:-latest} container_name: app-blue + environment: + - SPRING_PROFILES_ACTIVE=${PROFILE:-dev,monitor} + - TZ=Asia/Seoul labels: - "traefik.enable=true" - "traefik.http.routers.app-blue.rule=Host(`api.test.debate-timer.com`)" - - "traefik.http.services.app-blue.loadbalancer.server.port=8080" - "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" networks: - - web-gateway + - debate-timer-net + depends_on: + traefik: + condition: service_healthy healthcheck: - test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/actuator/health"] + test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8083/monitoring/health" ] interval: 10s retries: 3 app-green: image: debatetimer/debate_timer:${TAG:-latest} container_name: app-green + environment: + - SPRING_PROFILES_ACTIVE=${PROFILE:-dev,monitor} + - TZ=Asia/Seoul labels: - "traefik.enable=true" - "traefik.http.routers.app-green.rule=Host(`api.test.debate-timer.com`)" @@ -26,13 +41,18 @@ services: - "traefik.http.routers.app-green.entrypoints=websecure" - "traefik.http.routers.app-green.tls=true" - "traefik.http.routers.app-green.tls.certresolver=myresolver" + + - "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" networks: - - web-gateway + - debate-timer-net + depends_on: + traefik: + condition: service_healthy healthcheck: - test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/actuator/health"] + test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8083/monitoring/health" ] interval: 10s retries: 3 - -networks: - web-gateway: - external: true + start_period: 180s diff --git a/docker/docker-compose.traefik.yaml b/docker/docker-compose.traefik.yaml index a283ace..a15a19b 100644 --- a/docker/docker-compose.traefik.yaml +++ b/docker/docker-compose.traefik.yaml @@ -1,32 +1,40 @@ services: traefik: - image: traefik:v3.0 + image: traefik:v2.11 ports: - "80:80" - "443:443" - "8080:8080" + - "8083:8083" + environment: + - DOCKER_API_VERSION=1.44 command: - # 1. 기본 설정 - "--api.insecure=true" + - "--log.level=DEBUG" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - # 2. EntryPoints 설정 (HTTP -> HTTPS 리다이렉트) - "--entrypoints.web.address=:80" - "--entrypoints.web.http.redirections.entryPoint.to=websecure" - "--entrypoints.web.http.redirections.entryPoint.scheme=https" - "--entrypoints.websecure.address=:443" - # 3. 인증서 발급 설정 (Let's Encrypt) - "--certificatesresolvers.myresolver.acme.tlschallenge=true" - "--certificatesresolvers.myresolver.acme.email=debatetimekeeping@gmail.com" - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" + + - "--entrypoints.monitoring.address=:8083" + + - "--api.insecure=true" + - "--ping=true" + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8080/ping"] + interval: 10s + timeout: 5s + retries: 3 + start_period: 5s volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - - ./letsencrypt:/letsencrypt + - ../letsencrypt:/letsencrypt networks: - - web-gateway - -networks: - web-gateway: - external: true + - debate-timer-net diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 6b106ce..15f12b2 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -5,6 +5,7 @@ include: - docker-compose.spring.yaml networks: - web-gateway: - name: web-gateway + debate-timer-net: + name: debate-timer-net driver: bridge + diff --git a/scripts/init/auto_swap.sh b/scripts/init/auto-swap.sh similarity index 100% rename from scripts/init/auto_swap.sh rename to scripts/init/auto-swap.sh diff --git a/scripts/init/init_docker.sh b/scripts/init/init-docker.sh similarity index 100% rename from scripts/init/init_docker.sh rename to scripts/init/init-docker.sh diff --git a/scripts/init/init-letsencrypt.sh b/scripts/init/init-letsencrypt.sh new file mode 100644 index 0000000..e3a2603 --- /dev/null +++ b/scripts/init/init-letsencrypt.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cd "$(dirname "$0")" + +mkdir -p ../../letsencrypt +touch ../../letsencrypt/acme.json +chmod 600 ../../letsencrypt/acme.json + +echo "✅ 스크립트 위치($(pwd))에 letsencrypt 폴더를 생성했습니다." From 5d850944847ac235025d5ebad1bf0be57e912541 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Wed, 4 Feb 2026 23:54:46 +0900 Subject: [PATCH 07/12] =?UTF-8?q?feat:=20datadog=20agent=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- docker/Dockerfile | 4 +- docker/docker-compose.datadog.yaml | 30 +++++++++++++ docker/docker-compose.spring.yaml | 51 ++++++++++++++++++++-- docker/docker-compose.traefik.yaml | 1 + docker/docker-compose.yaml | 2 +- src/main/resources/application-monitor.yml | 9 ++++ 7 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 docker/docker-compose.datadog.yaml diff --git a/build.gradle b/build.gradle index aa7cfcb..3d36f46 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,7 @@ dependencies { // Monitoring implementation 'org.springframework.boot:spring-boot-starter-actuator' - implementation 'io.micrometer:micrometer-registry-prometheus' + implementation 'io.micrometer:micrometer-registry-statsd' // DB schema manager implementation 'org.flywaydb:flyway-mysql' diff --git a/docker/Dockerfile b/docker/Dockerfile index cad80f3..17299ce 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -7,9 +7,11 @@ RUN java -Djarmode=layertools -jar app.jar extract FROM eclipse-temurin:17-jre-alpine WORKDIR /workspace +ADD https://dtdg.co/latest-java-tracer ./dd-java-agent.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", "org.springframework.boot.loader.launch.JarLauncher"] +ENTRYPOINT ["java", "-javaagent:./dd-java-agent.jar", "org.springframework.boot.loader.launch.JarLauncher"] diff --git a/docker/docker-compose.datadog.yaml b/docker/docker-compose.datadog.yaml new file mode 100644 index 0000000..c823950 --- /dev/null +++ b/docker/docker-compose.datadog.yaml @@ -0,0 +1,30 @@ +services: + datadog-agent: + image: gcr.io/datadoghq/agent:7 + 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:${TAG:-dev},project:debate-timer + ports: + - "8125:8125/udp" # Metrics (StatsD) + - "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: 30s + timeout: 5s + retries: 5 + start_period: 60s diff --git a/docker/docker-compose.spring.yaml b/docker/docker-compose.spring.yaml index 46a9063..cf1819b 100644 --- a/docker/docker-compose.spring.yaml +++ b/docker/docker-compose.spring.yaml @@ -1,10 +1,27 @@ services: app-blue: - image: debatetimer/debate_timer:${TAG:-latest} + image: debatetimer/debate_timer:${TAG} container_name: app-blue 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=${TAG} + - DD_VERSION=1.0.0 + - DD_LOGS_INJECTION=true + - DD_PROFILING_ENABLED=true + - DD_PROFILING_ALLOCATION_ENABLED=true + - DD_PROFILING_HEAP_ENABLED=true + + - MANAGEMENT_METRICS_EXPORT_STATSD_ENABLED=true + - MANAGEMENT_METRICS_EXPORT_STATSD_FLAVOR=datadog + - MANAGEMENT_METRICS_EXPORT_STATSD_HOST=datadog-agent + - MANAGEMENT_METRICS_EXPORT_STATSD_PORT=8125 + - MANAGEMENT_METRICS_EXPORT_STATSD_PROTOCOL=UDP + labels: - "traefik.enable=true" - "traefik.http.routers.app-blue.rule=Host(`api.test.debate-timer.com`)" @@ -18,22 +35,45 @@ services: - "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\"}]" + 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: 10s retries: 3 + start_period: 300s app-green: - image: debatetimer/debate_timer:${TAG:-latest} + image: debatetimer/debate_timer:${TAG} container_name: app-green 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=${TAG} + - DD_VERSION=1.0.0 + - DD_LOGS_INJECTION=true + - DD_PROFILING_ENABLED=true + - DD_PROFILING_ALLOCATION_ENABLED=true + - DD_PROFILING_HEAP_ENABLED=true + + - MANAGEMENT_METRICS_EXPORT_STATSD_ENABLED=true + - MANAGEMENT_METRICS_EXPORT_STATSD_FLAVOR=datadog + - MANAGEMENT_METRICS_EXPORT_STATSD_HOST=datadog-agent + - MANAGEMENT_METRICS_EXPORT_STATSD_PORT=8125 + - MANAGEMENT_METRICS_EXPORT_STATSD_PROTOCOL=UDP + labels: - "traefik.enable=true" - "traefik.http.routers.app-green.rule=Host(`api.test.debate-timer.com`)" @@ -46,13 +86,18 @@ services: - "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\"}]" + 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: 10s retries: 3 - start_period: 180s + start_period: 300s diff --git a/docker/docker-compose.traefik.yaml b/docker/docker-compose.traefik.yaml index a15a19b..db8355c 100644 --- a/docker/docker-compose.traefik.yaml +++ b/docker/docker-compose.traefik.yaml @@ -1,6 +1,7 @@ services: traefik: image: traefik:v2.11 + container_name: traefik ports: - "80:80" - "443:443" diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 15f12b2..6961d05 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -3,9 +3,9 @@ name: debate-timer-server include: - docker-compose.traefik.yaml - docker-compose.spring.yaml + - docker-compose.datadog.yaml networks: debate-timer-net: name: debate-timer-net driver: bridge - diff --git a/src/main/resources/application-monitor.yml b/src/main/resources/application-monitor.yml index d9809cb..0e9fca0 100644 --- a/src/main/resources/application-monitor.yml +++ b/src/main/resources/application-monitor.yml @@ -1,4 +1,13 @@ management: + statsd: + metrics: + export: + enabled: true + flavor: datadog + host: ${MANAGEMENT_METRICS_EXPORT_STATSD_HOST:localhost} + port: 8125 + protocol: UDP + server: port: 8083 From 4ab47ed72662b8b93429605f14a946fa985c9629 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Thu, 5 Feb 2026 21:16:07 +0900 Subject: [PATCH 08/12] =?UTF-8?q?refactor:=20=EC=B4=88=EA=B8=B0=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/init/init-docker.sh | 7 +++---- scripts/init/init-letsencrypt.sh | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/init/init-docker.sh b/scripts/init/init-docker.sh index 9f9a8b5..c515ffa 100644 --- a/scripts/init/init-docker.sh +++ b/scripts/init/init-docker.sh @@ -30,9 +30,8 @@ sudo usermod -aG docker $USER echo "5. 로그인 진행 (변수 입력했을 경우에만)" if [ -n "$DOCKER_USER" ] && [ -n "$DOCKER_TOKEN" ]; then echo "입력된 정보로 Docker Hub 로그인을 시도합니다..." - echo "$DOCKER_TOKEN" | sg docker -c "docker login -u $DOCKER_USER --password-stdin" - - if [ $? -eq 0 ]; then + + if echo "$DOCKER_TOKEN" | sg docker -c "docker login -u \"$DOCKER_USER\" --password-stdin"; then echo "✅ 로그인 성공! (config.json이 생성되었습니다)" else echo "❌ 로그인 실패. 아이디/토큰을 확인하거나 'newgrp docker' 후 다시 시도하세요." @@ -43,4 +42,4 @@ else fi echo "6. Docker 권한이 적용된 새로운 쉘로 전환" -exec newgrp docker \ No newline at end of file +exec newgrp docker diff --git a/scripts/init/init-letsencrypt.sh b/scripts/init/init-letsencrypt.sh index e3a2603..5223ca6 100644 --- a/scripts/init/init-letsencrypt.sh +++ b/scripts/init/init-letsencrypt.sh @@ -1,6 +1,6 @@ #!/bin/bash -cd "$(dirname "$0")" +cd "$(dirname "$0")" || exit 1 mkdir -p ../../letsencrypt touch ../../letsencrypt/acme.json From afef7000a09b8804091e029a5f88eb9312f4bebc Mon Sep 17 00:00:00 2001 From: leegwichan Date: Thu, 5 Feb 2026 21:21:45 +0900 Subject: [PATCH 09/12] =?UTF-8?q?refactor:=20docker-compose=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.datadog.yaml | 8 +- docker/docker-compose.spring.yaml | 114 ++++++++------------- docker/docker-compose.traefik.yaml | 12 +-- src/main/resources/application-monitor.yml | 2 +- 4 files changed, 53 insertions(+), 83 deletions(-) diff --git a/docker/docker-compose.datadog.yaml b/docker/docker-compose.datadog.yaml index c823950..cfa62de 100644 --- a/docker/docker-compose.datadog.yaml +++ b/docker/docker-compose.datadog.yaml @@ -12,7 +12,7 @@ services: - DD_LOGS_ENABLED=true - DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true - DD_PROCESS_AGENT_ENABLED=true - - DD_TAGS=env:${TAG:-dev},project:debate-timer + - DD_TAGS=env:${ENV:-dev},project:debate-timer ports: - "8125:8125/udp" # Metrics (StatsD) - "8126:8126/tcp" # APM (Trace) @@ -24,7 +24,7 @@ services: - debate-timer-net healthcheck: test: ["CMD", "agent", "health"] - interval: 30s - timeout: 5s + interval: 60s + timeout: 10s retries: 5 - start_period: 60s + start_period: 120s diff --git a/docker/docker-compose.spring.yaml b/docker/docker-compose.spring.yaml index cf1819b..a678bbe 100644 --- a/docker/docker-compose.spring.yaml +++ b/docker/docker-compose.spring.yaml @@ -1,30 +1,47 @@ -services: - app-blue: - image: debatetimer/debate_timer:${TAG} - container_name: app-blue - environment: - - SERVER_FORWARD_HEADERS_STRATEGY=framework - - SPRING_PROFILES_ACTIVE=${PROFILE:-dev,monitor} - - TZ=Asia/Seoul +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 + - DD_LOGS_INJECTION=true + - DD_PROFILING_ENABLED=true + - DD_PROFILING_ALLOCATION_ENABLED=true + - DD_PROFILING_HEAP_ENABLED=true - - DD_AGENT_HOST=datadog-agent - - DD_SERVICE=debate-timer - - DD_ENV=${TAG} - - DD_VERSION=1.0.0 - - 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 - - MANAGEMENT_METRICS_EXPORT_STATSD_ENABLED=true - - MANAGEMENT_METRICS_EXPORT_STATSD_FLAVOR=datadog - - MANAGEMENT_METRICS_EXPORT_STATSD_HOST=datadog-agent - - MANAGEMENT_METRICS_EXPORT_STATSD_PORT=8125 - - MANAGEMENT_METRICS_EXPORT_STATSD_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 + +services: + app-blue: + <<: *app-template + container_name: app-blue labels: - "traefik.enable=true" - - "traefik.http.routers.app-blue.rule=Host(`api.test.debate-timer.com`)" + - "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" @@ -38,49 +55,17 @@ services: - "com.datadoghq.ad.logs=[{\"source\": \"java\", \"service\": \"debate-timer\"}]" - 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: 10s - retries: 3 - start_period: 300s - app-green: - image: debatetimer/debate_timer:${TAG} + <<: *app-template container_name: app-green - 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=${TAG} - - DD_VERSION=1.0.0 - - DD_LOGS_INJECTION=true - - DD_PROFILING_ENABLED=true - - DD_PROFILING_ALLOCATION_ENABLED=true - - DD_PROFILING_HEAP_ENABLED=true - - - MANAGEMENT_METRICS_EXPORT_STATSD_ENABLED=true - - MANAGEMENT_METRICS_EXPORT_STATSD_FLAVOR=datadog - - MANAGEMENT_METRICS_EXPORT_STATSD_HOST=datadog-agent - - MANAGEMENT_METRICS_EXPORT_STATSD_PORT=8125 - - MANAGEMENT_METRICS_EXPORT_STATSD_PROTOCOL=UDP - labels: - "traefik.enable=true" - - "traefik.http.routers.app-green.rule=Host(`api.test.debate-timer.com`)" - - "traefik.http.services.app-green.loadbalancer.server.port=8080" + - "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" + - "traefik.http.services.app-green.loadbalancer.server.port=8080" + - "traefik.http.routers.app-green.service=app-green" - "traefik.http.routers.app-green-monitor.rule=PathPrefix(`/`)" - "traefik.http.routers.app-green-monitor.entrypoints=monitoring" @@ -88,16 +73,3 @@ services: - "traefik.http.services.app-green-monitor-svc.loadbalancer.server.port=8083" - "com.datadoghq.ad.logs=[{\"source\": \"java\", \"service\": \"debate-timer\"}]" - - 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: 10s - retries: 3 - start_period: 300s diff --git a/docker/docker-compose.traefik.yaml b/docker/docker-compose.traefik.yaml index db8355c..219dcab 100644 --- a/docker/docker-compose.traefik.yaml +++ b/docker/docker-compose.traefik.yaml @@ -11,6 +11,7 @@ services: - DOCKER_API_VERSION=1.44 command: - "--api.insecure=true" + - "--ping=true" - "--log.level=DEBUG" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" @@ -25,15 +26,12 @@ services: - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" - "--entrypoints.monitoring.address=:8083" - - - "--api.insecure=true" - - "--ping=true" healthcheck: test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8080/ping"] - interval: 10s - timeout: 5s - retries: 3 - start_period: 5s + interval: 60s + timeout: 10s + retries: 5 + start_period: 120s volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ../letsencrypt:/letsencrypt diff --git a/src/main/resources/application-monitor.yml b/src/main/resources/application-monitor.yml index 0e9fca0..682582b 100644 --- a/src/main/resources/application-monitor.yml +++ b/src/main/resources/application-monitor.yml @@ -4,7 +4,7 @@ management: export: enabled: true flavor: datadog - host: ${MANAGEMENT_METRICS_EXPORT_STATSD_HOST:localhost} + host: ${MANAGEMENT_STATSD_METRICS_EXPORT_HOST:localhost} port: 8125 protocol: UDP From 20cce504ca33f212eb6bd6c306ff08c58d251b22 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Sun, 8 Feb 2026 16:09:14 +0900 Subject: [PATCH 10/12] =?UTF-8?q?refactor:=20docker-compose=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=ED=99=95=EC=9E=A5=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...cker-compose.datadog.yaml => docker-compose.datadog.yml} | 0 ...docker-compose.spring.yaml => docker-compose.spring.yml} | 0 ...cker-compose.traefik.yaml => docker-compose.traefik.yml} | 2 +- docker/{docker-compose.yaml => docker-compose.yml} | 6 +++--- 4 files changed, 4 insertions(+), 4 deletions(-) rename docker/{docker-compose.datadog.yaml => docker-compose.datadog.yml} (100%) rename docker/{docker-compose.spring.yaml => docker-compose.spring.yml} (100%) rename docker/{docker-compose.traefik.yaml => docker-compose.traefik.yml} (97%) rename docker/{docker-compose.yaml => docker-compose.yml} (54%) diff --git a/docker/docker-compose.datadog.yaml b/docker/docker-compose.datadog.yml similarity index 100% rename from docker/docker-compose.datadog.yaml rename to docker/docker-compose.datadog.yml diff --git a/docker/docker-compose.spring.yaml b/docker/docker-compose.spring.yml similarity index 100% rename from docker/docker-compose.spring.yaml rename to docker/docker-compose.spring.yml diff --git a/docker/docker-compose.traefik.yaml b/docker/docker-compose.traefik.yml similarity index 97% rename from docker/docker-compose.traefik.yaml rename to docker/docker-compose.traefik.yml index 219dcab..54e2a2c 100644 --- a/docker/docker-compose.traefik.yaml +++ b/docker/docker-compose.traefik.yml @@ -12,7 +12,7 @@ services: command: - "--api.insecure=true" - "--ping=true" - - "--log.level=DEBUG" + - "--log.level=INFO" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yml similarity index 54% rename from docker/docker-compose.yaml rename to docker/docker-compose.yml index 6961d05..9bb209d 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yml @@ -1,9 +1,9 @@ name: debate-timer-server include: - - docker-compose.traefik.yaml - - docker-compose.spring.yaml - - docker-compose.datadog.yaml + - docker-compose.traefik.yml + - docker-compose.spring.yml + - docker-compose.datadog.yml networks: debate-timer-net: From 4cb4824b125376a29029b687f2010d3e7dfd4b1a Mon Sep 17 00:00:00 2001 From: leegwichan Date: Sun, 8 Feb 2026 16:10:00 +0900 Subject: [PATCH 11/12] =?UTF-8?q?feat:=20auto-swap.sh=20=EC=9D=98=20?= =?UTF-8?q?=EC=8A=A4=EC=99=91=20=EC=82=AC=EC=9D=B4=EC=A6=88=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/init/auto-swap.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/init/auto-swap.sh b/scripts/init/auto-swap.sh index 2c621c5..be475b6 100644 --- a/scripts/init/auto-swap.sh +++ b/scripts/init/auto-swap.sh @@ -2,7 +2,7 @@ # --- 설정 변수 --- SWAP_FILE="/swapfile" -SWAP_SIZE="2G" +SWAP_SIZE=${1:-"2G"} FSTAB_FILE="/etc/fstab" # 1. 루트 권한 확인 @@ -40,6 +40,5 @@ if ! grep -q "$SWAP_FILE" "$FSTAB_FILE"; then fi echo "=== 모든 작업이 완료되었습니다 ===" -echo "" echo "[현재 메모리 상태]" -free -h \ No newline at end of file +free -h From 8de6dbf1eec1edaa73e846a1ff131ca1601a607e Mon Sep 17 00:00:00 2001 From: leegwichan Date: Sun, 8 Feb 2026 16:50:41 +0900 Subject: [PATCH 12/12] =?UTF-8?q?refactor:=20auto-swap.sh=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/init/auto-swap.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/init/auto-swap.sh b/scripts/init/auto-swap.sh index be475b6..56e97a9 100644 --- a/scripts/init/auto-swap.sh +++ b/scripts/init/auto-swap.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -e # 스크립트 실행 중 에러 발생 시 즉시 중단 (안전 장치) + # --- 설정 변수 --- SWAP_FILE="/swapfile" SWAP_SIZE=${1:-"2G"}