From e83a389ead51ab5bae470971373b316688edf9df Mon Sep 17 00:00:00 2001 From: leegwichan Date: Wed, 18 Feb 2026 18:28:49 +0900 Subject: [PATCH 01/12] =?UTF-8?q?feat:=20webhook=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=20-=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.datadog.yml | 2 +- docker/docker-compose.webhook.yml | 36 +++++++++++++++++ docker/docker-compose.yml | 1 + docker/hooks.json | 10 +++++ docker/webhook-entrypoint.sh | 4 ++ docker/webhook.Dockerfile | 7 ++++ scripts/deploy/deploy-docker.sh | 67 +++++++++++++++++++++++++++++++ scripts/init/init-letsencrypt.sh | 2 +- 8 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 docker/docker-compose.webhook.yml create mode 100644 docker/hooks.json create mode 100644 docker/webhook-entrypoint.sh create mode 100644 docker/webhook.Dockerfile create mode 100644 scripts/deploy/deploy-docker.sh diff --git a/docker/docker-compose.datadog.yml b/docker/docker-compose.datadog.yml index cfa62de8..11450517 100644 --- a/docker/docker-compose.datadog.yml +++ b/docker/docker-compose.datadog.yml @@ -3,7 +3,7 @@ services: image: gcr.io/datadoghq/agent:7 container_name: datadog-agent environment: - - DD_API_KEY=${DD_API_KEY} + - DD_API_KEY=${DD_API_KEY:-blank} - DD_SITE=us5.datadoghq.com - DD_APM_ENABLED=true - DD_APM_NON_LOCAL_TRAFFIC=true diff --git a/docker/docker-compose.webhook.yml b/docker/docker-compose.webhook.yml new file mode 100644 index 00000000..64510db5 --- /dev/null +++ b/docker/docker-compose.webhook.yml @@ -0,0 +1,36 @@ +services: + webhook: + build: + context: . + dockerfile: webhook.Dockerfile + container_name: webhook + user: root + command: ["-verbose", "-hooks=/etc/webhook/hooks.json", "-hotreload"] + environment: + - ENV=${ENV:-dev} + - DOCKER_USER=${DOCKER_USER:-blank} + - DOCKER_TOKEN=${DOCKER_TOKEN:-blank} + labels: + - "traefik.enable=true" + - "traefik.http.routers.webhook.rule=Host(`webhook.${ENV:-dev}.debate-timer.com`)" + - "traefik.http.routers.webhook.entrypoints=websecure" + - "traefik.http.routers.webhook.tls=true" + - "traefik.http.routers.webhook.tls.certresolver=myresolver" + - "traefik.http.services.webhook.loadbalancer.server.port=9000" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./hooks.json:/etc/webhook/hooks.json + - ../scripts/deploy:/home/ubuntu/scripts + - ../docker:/home/ubuntu/docker + networks: + - debate-timer-net + depends_on: + traefik: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "nc -z localhost 9000 || exit 1"] + interval: 120s + timeout: 30s + retries: 5 + start_period: 30s + restart: always diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 9bb209d9..936e0558 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -2,6 +2,7 @@ name: debate-timer-server include: - docker-compose.traefik.yml + - docker-compose.webhook.yml - docker-compose.spring.yml - docker-compose.datadog.yml diff --git a/docker/hooks.json b/docker/hooks.json new file mode 100644 index 00000000..1a5d95cf --- /dev/null +++ b/docker/hooks.json @@ -0,0 +1,10 @@ +[ + { + "id": "deploy", + "execute-command": "/home/ubuntu/scripts/deploy-docker.sh", + "command-working-directory": "/home/ubuntu", + "pass-arguments-to-command": [ + { "source": "entire-payload" } + ] + } +] diff --git a/docker/webhook-entrypoint.sh b/docker/webhook-entrypoint.sh new file mode 100644 index 00000000..25214cc9 --- /dev/null +++ b/docker/webhook-entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo "$DOCKER_TOKEN" | docker login -u "$DOCKER_USER" --password-stdin +exec /usr/local/bin/webhook "$@" diff --git a/docker/webhook.Dockerfile b/docker/webhook.Dockerfile new file mode 100644 index 00000000..6803e631 --- /dev/null +++ b/docker/webhook.Dockerfile @@ -0,0 +1,7 @@ +FROM almir/webhook:2.8.3 +USER root +RUN apk add --no-cache docker-cli docker-cli-compose curl bash +WORKDIR /etc/webhook + +COPY webhook-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["webhook-entrypoint.sh"] diff --git a/scripts/deploy/deploy-docker.sh b/scripts/deploy/deploy-docker.sh new file mode 100644 index 00000000..e0a00697 --- /dev/null +++ b/scripts/deploy/deploy-docker.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +TARGET_ENV=${ENV:-dev} +PROJECT_DIR="/home/ubuntu/docker" + +cd $PROJECT_DIR || { echo "디렉토리 이동 실패"; exit 1; } + +echo "--- 배포 시작 ENV: $TARGET_ENV at $(date) ---" + +# 현재 실행 중인 색상 확인 +if docker ps --filter "status=running" --format '{{.Names}}' | grep -q "app-blue"; then + CURRENT_SERVICE="app-blue" + TARGET_SERVICE="app-green" +elif docker ps --filter "status=running" --format '{{.Names}}' | grep -q "app-green"; then + CURRENT_SERVICE="app-green" + TARGET_SERVICE="app-blue" +else + CURRENT_SERVICE="" + TARGET_SERVICE="app-blue" +fi + +echo "현재 실행중인 서비스: ${CURRENT_SERVICE:-없음}" +echo "앞으로 띄울 서비스: $TARGET_SERVICE" + +export ENV=$TARGET_ENV # docker-compose.yml에서 ENV 변수를 사용할 수 있도록 설정 + +echo "최근 이미지 가져오는 중 (ENV: $TARGET_ENV)" +docker-compose pull $TARGET_SERVICE + +echo "컨테이너 실행 중 - $TARGET_SERVICE..." +docker-compose up -d $TARGET_SERVICE + +echo "헬스 체크 진행 중 - $TARGET_SERVICE" +MAX_RETRIES=60 +SLEEP_SECOND=10 +COUNT=0 + +while [ $COUNT -lt $MAX_RETRIES ]; do + # 컨테이너의 Health 상태 추출 + HEALTH_STATUS=$(docker inspect --format='{{.State.Health.Status}}' "$TARGET_SERVICE" 2>/dev/null) + + if [ "$HEALTH_STATUS" = "healthy" ]; then + echo "헬스 체크 완료 - $TARGET_SERVICE" + break + fi + + echo "헬스체크 진행 중 ($COUNT/$MAX_RETRIES) - 현재 상태: $HEALTH_STATUS" + # sleep $SLEEP_SECOND + COUNT=$((COUNT + 1)) +done + +if [ $COUNT -eq $MAX_RETRIES ]; then + echo "배포 실패: $TARGET_SERVICE did not become healthy." + docker-compose stop $TARGET_SERVICE + exit 1 +fi + +if [ ! -z "$CURRENT_SERVICE" ]; then + echo "이전 서비스 $CURRENT_SERVICE 중지 중..." + docker-compose stop $CURRENT_SERVICE +else + echo "이전 서비스가 없으므로 스위칭 단계 건너뜁니다." +fi + +docker image prune -f + +echo "--- $TARGET_ENV 배포 완료 at $(date) ---" diff --git a/scripts/init/init-letsencrypt.sh b/scripts/init/init-letsencrypt.sh index 5223ca63..f8820a66 100644 --- a/scripts/init/init-letsencrypt.sh +++ b/scripts/init/init-letsencrypt.sh @@ -6,4 +6,4 @@ mkdir -p ../../letsencrypt touch ../../letsencrypt/acme.json chmod 600 ../../letsencrypt/acme.json -echo "✅ 스크립트 위치($(pwd))에 letsencrypt 폴더를 생성했습니다." +echo "letsencrypt 폴더를 생성했습니다." From cd6fb00d2fff320c0066ff4280c5fd68fa99dd16 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Mon, 23 Feb 2026 22:11:11 +0900 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20webhook=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=20-=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.datadog.yml | 3 ++- docker/docker-compose.spring.yml | 8 +++----- docker/docker-compose.webhook.yml | 3 +-- docker/webhook-entrypoint.sh | 4 ---- docker/webhook.Dockerfile | 3 --- scripts/deploy/deploy-docker.sh | 9 ++++----- 6 files changed, 10 insertions(+), 20 deletions(-) delete mode 100644 docker/webhook-entrypoint.sh diff --git a/docker/docker-compose.datadog.yml b/docker/docker-compose.datadog.yml index 11450517..f7d82d27 100644 --- a/docker/docker-compose.datadog.yml +++ b/docker/docker-compose.datadog.yml @@ -5,6 +5,7 @@ services: environment: - DD_API_KEY=${DD_API_KEY:-blank} - DD_SITE=us5.datadoghq.com + - DD_HOSTNAME=debate-timer-${ENV:-dev}-server - DD_APM_ENABLED=true - DD_APM_NON_LOCAL_TRAFFIC=true - DD_APM_IGNORE_RESOURCES=/monitoring/health @@ -25,6 +26,6 @@ services: healthcheck: test: ["CMD", "agent", "health"] interval: 60s - timeout: 10s + timeout: 30s retries: 5 start_period: 120s diff --git a/docker/docker-compose.spring.yml b/docker/docker-compose.spring.yml index a678bbe3..76dec82a 100644 --- a/docker/docker-compose.spring.yml +++ b/docker/docker-compose.spring.yml @@ -2,7 +2,7 @@ x-app-template: &app-template image: debatetimer/debate_timer:${ENV:-dev} environment: - SERVER_FORWARD_HEADERS_STRATEGY=framework - - SPRING_PROFILES_ACTIVE=${PROFILE:-dev,monitor} + - SPRING_PROFILES_ACTIVE=${ENV:-dev},monitor - TZ=Asia/Seoul - DD_AGENT_HOST=datadog-agent @@ -26,14 +26,12 @@ x-app-template: &app-template 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 + retries: 10 + start_period: 450s services: app-blue: diff --git a/docker/docker-compose.webhook.yml b/docker/docker-compose.webhook.yml index 64510db5..177c4b5f 100644 --- a/docker/docker-compose.webhook.yml +++ b/docker/docker-compose.webhook.yml @@ -8,8 +8,6 @@ services: command: ["-verbose", "-hooks=/etc/webhook/hooks.json", "-hotreload"] environment: - ENV=${ENV:-dev} - - DOCKER_USER=${DOCKER_USER:-blank} - - DOCKER_TOKEN=${DOCKER_TOKEN:-blank} labels: - "traefik.enable=true" - "traefik.http.routers.webhook.rule=Host(`webhook.${ENV:-dev}.debate-timer.com`)" @@ -19,6 +17,7 @@ services: - "traefik.http.services.webhook.loadbalancer.server.port=9000" volumes: - /var/run/docker.sock:/var/run/docker.sock + - /home/ubuntu/.docker:/root/.docker:ro - ./hooks.json:/etc/webhook/hooks.json - ../scripts/deploy:/home/ubuntu/scripts - ../docker:/home/ubuntu/docker diff --git a/docker/webhook-entrypoint.sh b/docker/webhook-entrypoint.sh deleted file mode 100644 index 25214cc9..00000000 --- a/docker/webhook-entrypoint.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -echo "$DOCKER_TOKEN" | docker login -u "$DOCKER_USER" --password-stdin -exec /usr/local/bin/webhook "$@" diff --git a/docker/webhook.Dockerfile b/docker/webhook.Dockerfile index 6803e631..ca2b8ba1 100644 --- a/docker/webhook.Dockerfile +++ b/docker/webhook.Dockerfile @@ -2,6 +2,3 @@ FROM almir/webhook:2.8.3 USER root RUN apk add --no-cache docker-cli docker-cli-compose curl bash WORKDIR /etc/webhook - -COPY webhook-entrypoint.sh /usr/local/bin/ -ENTRYPOINT ["webhook-entrypoint.sh"] diff --git a/scripts/deploy/deploy-docker.sh b/scripts/deploy/deploy-docker.sh index e0a00697..356e604f 100644 --- a/scripts/deploy/deploy-docker.sh +++ b/scripts/deploy/deploy-docker.sh @@ -21,17 +21,16 @@ fi echo "현재 실행중인 서비스: ${CURRENT_SERVICE:-없음}" echo "앞으로 띄울 서비스: $TARGET_SERVICE" - -export ENV=$TARGET_ENV # docker-compose.yml에서 ENV 변수를 사용할 수 있도록 설정 +export ENV=$TARGET_ENV echo "최근 이미지 가져오는 중 (ENV: $TARGET_ENV)" docker-compose pull $TARGET_SERVICE echo "컨테이너 실행 중 - $TARGET_SERVICE..." -docker-compose up -d $TARGET_SERVICE +docker-compose up -d --no-deps $TARGET_SERVICE echo "헬스 체크 진행 중 - $TARGET_SERVICE" -MAX_RETRIES=60 +MAX_RETRIES=90 SLEEP_SECOND=10 COUNT=0 @@ -45,7 +44,7 @@ while [ $COUNT -lt $MAX_RETRIES ]; do fi echo "헬스체크 진행 중 ($COUNT/$MAX_RETRIES) - 현재 상태: $HEALTH_STATUS" - # sleep $SLEEP_SECOND + sleep $SLEEP_SECOND COUNT=$((COUNT + 1)) done From 9ad4ad0dbec62c73142ff812f9411459c0d3215a Mon Sep 17 00:00:00 2001 From: leegwichan Date: Wed, 25 Feb 2026 16:10:09 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20=EC=A4=91=EB=8B=A8=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=ED=98=95=ED=83=9C=EB=A1=9C=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=20=EB=B0=8F=20docker=20compose=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../docker-compose.application.yml | 53 ++++++++++++++ .../{ => datadog}/docker-compose.datadog.yml | 0 docker/docker-compose.spring.yml | 73 ------------------- docker/docker-compose.yml | 8 +- .../{ => traefik}/docker-compose.traefik.yml | 2 +- .../{ => webhook}/docker-compose.webhook.yml | 8 +- docker/{ => webhook}/hooks.json | 0 docker/{ => webhook}/webhook.Dockerfile | 0 scripts/deploy/deploy-docker.sh | 39 +++------- 9 files changed, 72 insertions(+), 111 deletions(-) create mode 100644 docker/application/docker-compose.application.yml rename docker/{ => datadog}/docker-compose.datadog.yml (100%) delete mode 100644 docker/docker-compose.spring.yml rename docker/{ => traefik}/docker-compose.traefik.yml (96%) rename docker/{ => webhook}/docker-compose.webhook.yml (87%) rename docker/{ => webhook}/hooks.json (100%) rename docker/{ => webhook}/webhook.Dockerfile (100%) diff --git a/docker/application/docker-compose.application.yml b/docker/application/docker-compose.application.yml new file mode 100644 index 00000000..6b718d4c --- /dev/null +++ b/docker/application/docker-compose.application.yml @@ -0,0 +1,53 @@ +services: + application: + image: debatetimer/debate_timer:${ENV:-dev} + container_name: application + environment: + - SERVER_FORWARD_HEADERS_STRATEGY=framework + - SPRING_PROFILES_ACTIVE=${ENV:-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 + + - 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 + + healthcheck: + test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8083/monitoring/health" ] + interval: 60s + retries: 10 + start_period: 450s + + labels: + - "traefik.enable=true" + - "traefik.http.routers.application.rule=Host(`api.${ENV:-dev}.debate-timer.com`)" + - "traefik.http.routers.application.entrypoints=websecure" + - "traefik.http.routers.application.tls=true" + - "traefik.http.routers.application.tls.certresolver=myresolver" + - "traefik.http.services.application.loadbalancer.server.port=8080" + + - "traefik.http.routers.application-monitor.rule=PathPrefix(`/`)" + - "traefik.http.routers.application-monitor.entrypoints=monitoring" + - "traefik.http.routers.application-monitor.service=application-monitor-svc" + - "traefik.http.services.application-monitor-svc.loadbalancer.server.port=8083" + + - "com.datadoghq.ad.logs=[{\"source\": \"java\", \"service\": \"debate-timer\"}]" + + restart: always diff --git a/docker/docker-compose.datadog.yml b/docker/datadog/docker-compose.datadog.yml similarity index 100% rename from docker/docker-compose.datadog.yml rename to docker/datadog/docker-compose.datadog.yml diff --git a/docker/docker-compose.spring.yml b/docker/docker-compose.spring.yml deleted file mode 100644 index 76dec82a..00000000 --- a/docker/docker-compose.spring.yml +++ /dev/null @@ -1,73 +0,0 @@ -x-app-template: &app-template - image: debatetimer/debate_timer:${ENV:-dev} - environment: - - SERVER_FORWARD_HEADERS_STRATEGY=framework - - SPRING_PROFILES_ACTIVE=${ENV:-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 - - - 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 - - healthcheck: - test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8083/monitoring/health" ] - interval: 60s - retries: 10 - start_period: 450s - -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" - - "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" - - "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\"}]" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 936e0558..7fc5b5b7 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,10 +1,10 @@ name: debate-timer-server include: - - docker-compose.traefik.yml - - docker-compose.webhook.yml - - docker-compose.spring.yml - - docker-compose.datadog.yml + - ./application/docker-compose.application.yml + - ./datadog/docker-compose.datadog.yml + - ./traefik/docker-compose.traefik.yml + - ./webhook/docker-compose.webhook.yml networks: debate-timer-net: diff --git a/docker/docker-compose.traefik.yml b/docker/traefik/docker-compose.traefik.yml similarity index 96% rename from docker/docker-compose.traefik.yml rename to docker/traefik/docker-compose.traefik.yml index 54e2a2cc..3fe979cb 100644 --- a/docker/docker-compose.traefik.yml +++ b/docker/traefik/docker-compose.traefik.yml @@ -34,6 +34,6 @@ services: start_period: 120s volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - - ../letsencrypt:/letsencrypt + - ../../letsencrypt:/letsencrypt networks: - debate-timer-net diff --git a/docker/docker-compose.webhook.yml b/docker/webhook/docker-compose.webhook.yml similarity index 87% rename from docker/docker-compose.webhook.yml rename to docker/webhook/docker-compose.webhook.yml index 177c4b5f..b9fad0f4 100644 --- a/docker/docker-compose.webhook.yml +++ b/docker/webhook/docker-compose.webhook.yml @@ -1,8 +1,8 @@ services: webhook: build: - context: . - dockerfile: webhook.Dockerfile + context: .. + dockerfile: ./webhook.Dockerfile container_name: webhook user: root command: ["-verbose", "-hooks=/etc/webhook/hooks.json", "-hotreload"] @@ -19,8 +19,8 @@ services: - /var/run/docker.sock:/var/run/docker.sock - /home/ubuntu/.docker:/root/.docker:ro - ./hooks.json:/etc/webhook/hooks.json - - ../scripts/deploy:/home/ubuntu/scripts - - ../docker:/home/ubuntu/docker + - ../../scripts/deploy:/home/ubuntu/scripts + - ..:/home/ubuntu/docker networks: - debate-timer-net depends_on: diff --git a/docker/hooks.json b/docker/webhook/hooks.json similarity index 100% rename from docker/hooks.json rename to docker/webhook/hooks.json diff --git a/docker/webhook.Dockerfile b/docker/webhook/webhook.Dockerfile similarity index 100% rename from docker/webhook.Dockerfile rename to docker/webhook/webhook.Dockerfile diff --git a/scripts/deploy/deploy-docker.sh b/scripts/deploy/deploy-docker.sh index 356e604f..fc9b57ce 100644 --- a/scripts/deploy/deploy-docker.sh +++ b/scripts/deploy/deploy-docker.sh @@ -2,42 +2,30 @@ TARGET_ENV=${ENV:-dev} PROJECT_DIR="/home/ubuntu/docker" +TARGET_SERVICE="application" cd $PROJECT_DIR || { echo "디렉토리 이동 실패"; exit 1; } -echo "--- 배포 시작 ENV: $TARGET_ENV at $(date) ---" - -# 현재 실행 중인 색상 확인 -if docker ps --filter "status=running" --format '{{.Names}}' | grep -q "app-blue"; then - CURRENT_SERVICE="app-blue" - TARGET_SERVICE="app-green" -elif docker ps --filter "status=running" --format '{{.Names}}' | grep -q "app-green"; then - CURRENT_SERVICE="app-green" - TARGET_SERVICE="app-blue" -else - CURRENT_SERVICE="" - TARGET_SERVICE="app-blue" -fi - -echo "현재 실행중인 서비스: ${CURRENT_SERVICE:-없음}" -echo "앞으로 띄울 서비스: $TARGET_SERVICE" +echo "--- 중단 배포 시작 ENV: $TARGET_ENV at $(date) ---" export ENV=$TARGET_ENV echo "최근 이미지 가져오는 중 (ENV: $TARGET_ENV)" docker-compose pull $TARGET_SERVICE +if docker ps --format '{{.Names}}' | grep -q "^${TARGET_SERVICE}$"; then + echo "기존 $TARGET_SERVICE 중지 및 제거 중..." + docker-compose stop $TARGET_SERVICE +fi -echo "컨테이너 실행 중 - $TARGET_SERVICE..." +echo "새 컨테이너 실행 중 - $TARGET_SERVICE..." docker-compose up -d --no-deps $TARGET_SERVICE echo "헬스 체크 진행 중 - $TARGET_SERVICE" -MAX_RETRIES=90 +MAX_RETRIES=100 SLEEP_SECOND=10 COUNT=0 while [ $COUNT -lt $MAX_RETRIES ]; do - # 컨테이너의 Health 상태 추출 HEALTH_STATUS=$(docker inspect --format='{{.State.Health.Status}}' "$TARGET_SERVICE" 2>/dev/null) - if [ "$HEALTH_STATUS" = "healthy" ]; then echo "헬스 체크 완료 - $TARGET_SERVICE" break @@ -49,18 +37,11 @@ while [ $COUNT -lt $MAX_RETRIES ]; do done if [ $COUNT -eq $MAX_RETRIES ]; then - echo "배포 실패: $TARGET_SERVICE did not become healthy." - docker-compose stop $TARGET_SERVICE + echo "배포 실패: $TARGET_SERVICE가 healthy 상태가 되지 않았습니다." + docker logs --tail 50 $TARGET_SERVICE exit 1 fi -if [ ! -z "$CURRENT_SERVICE" ]; then - echo "이전 서비스 $CURRENT_SERVICE 중지 중..." - docker-compose stop $CURRENT_SERVICE -else - echo "이전 서비스가 없으므로 스위칭 단계 건너뜁니다." -fi - docker image prune -f echo "--- $TARGET_ENV 배포 완료 at $(date) ---" From e05bfdcd23be505147006728f5aac882c1c68980 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Wed, 25 Feb 2026 17:16:15 +0900 Subject: [PATCH 04/12] =?UTF-8?q?fix=20:=20=ED=8C=8C=EC=9D=BC=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/application/docker-compose.application.yml | 1 + docker/webhook/docker-compose.webhook.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/application/docker-compose.application.yml b/docker/application/docker-compose.application.yml index 6b718d4c..4efe38ff 100644 --- a/docker/application/docker-compose.application.yml +++ b/docker/application/docker-compose.application.yml @@ -41,6 +41,7 @@ services: - "traefik.http.routers.application.entrypoints=websecure" - "traefik.http.routers.application.tls=true" - "traefik.http.routers.application.tls.certresolver=myresolver" + - "traefik.http.routers.application.service=application" - "traefik.http.services.application.loadbalancer.server.port=8080" - "traefik.http.routers.application-monitor.rule=PathPrefix(`/`)" diff --git a/docker/webhook/docker-compose.webhook.yml b/docker/webhook/docker-compose.webhook.yml index b9fad0f4..62c137b5 100644 --- a/docker/webhook/docker-compose.webhook.yml +++ b/docker/webhook/docker-compose.webhook.yml @@ -2,7 +2,7 @@ services: webhook: build: context: .. - dockerfile: ./webhook.Dockerfile + dockerfile: ./webhook/webhook.Dockerfile container_name: webhook user: root command: ["-verbose", "-hooks=/etc/webhook/hooks.json", "-hotreload"] From 5da021bf7b40f1bbf416e258150c73d24e438d63 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Wed, 25 Feb 2026 18:59:09 +0900 Subject: [PATCH 05/12] =?UTF-8?q?feat:=20=EB=B0=B0=ED=8F=AC=20=EC=A4=91=20?= =?UTF-8?q?=EC=9E=AC=EB=B0=B0=ED=8F=AC=20=EB=B0=A9=EC=A7=80=20=EB=B0=8F=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=ED=99=95=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/webhook/hooks.json | 6 ++++++ scripts/deploy/check-deploy-status.sh | 14 ++++++++++++++ scripts/deploy/deploy-docker.sh | 6 ++++++ 3 files changed, 26 insertions(+) create mode 100644 scripts/deploy/check-deploy-status.sh diff --git a/docker/webhook/hooks.json b/docker/webhook/hooks.json index 1a5d95cf..76a97e68 100644 --- a/docker/webhook/hooks.json +++ b/docker/webhook/hooks.json @@ -6,5 +6,11 @@ "pass-arguments-to-command": [ { "source": "entire-payload" } ] + }, + { + "id": "status", + "execute-command": "/home/ubuntu/scripts/check-deploy-status.sh", + "command-working-directory": "/home/ubuntu", + "include-command-output-in-response": true } ] diff --git a/scripts/deploy/check-deploy-status.sh b/scripts/deploy/check-deploy-status.sh new file mode 100644 index 00000000..0ef7d675 --- /dev/null +++ b/scripts/deploy/check-deploy-status.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +LOCK_FILE="/tmp/deploy-application.lock" + +exec 200>"$LOCK_FILE" + +if ! flock -n 200; then + echo '{"status": "running", "message": "배포 스크립트가 현재 실행 중입니다."}' +else + flock -u 200 + echo '{"status": "idle", "message": "현재 진행 중인 배포가 없습니다. 대기 중입니다."}' +fi + +exec 200>&- diff --git a/scripts/deploy/deploy-docker.sh b/scripts/deploy/deploy-docker.sh index fc9b57ce..9b9f3c47 100644 --- a/scripts/deploy/deploy-docker.sh +++ b/scripts/deploy/deploy-docker.sh @@ -1,5 +1,11 @@ #!/bin/bash +echo "스크립트 실행 여부를 확인합니다." +LOCK_FILE="/tmp/deploy-application.lock" +exec 200>"$LOCK_FILE" +flock -n 200 || { echo "⚠️ 이미 배포 스크립트가 실행 중입니다. 중복 실행을 차단합니다."; exit 1; } +echo "스크립트를 실행하고 있지 않습니다. 배포를 시작합니다." + TARGET_ENV=${ENV:-dev} PROJECT_DIR="/home/ubuntu/docker" TARGET_SERVICE="application" From f5220bb5b00bf56ddf1348346c2a463f02d91180 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Thu, 26 Feb 2026 16:39:30 +0900 Subject: [PATCH 06/12] =?UTF-8?q?feat:=20webhook=20SECRET=5FTOKEN=20?= =?UTF-8?q?=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +++ docker/webhook/docker-compose.webhook.yml | 1 + docker/webhook/hooks.json | 22 +++++++++++++++++++++- docker/webhook/webhook.Dockerfile | 2 +- scripts/deploy/check-deploy-status.sh | 5 +++++ scripts/deploy/deploy-docker.sh | 5 +++++ 6 files changed, 36 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 7d690374..72b65d10 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,9 @@ out/ ### VS Code ### .vscode/ +### deploy +/letsencrypt/acme.json + ### Rest Docs /src/main/resources/static/docs/openapi3.yaml diff --git a/docker/webhook/docker-compose.webhook.yml b/docker/webhook/docker-compose.webhook.yml index 62c137b5..30e6d724 100644 --- a/docker/webhook/docker-compose.webhook.yml +++ b/docker/webhook/docker-compose.webhook.yml @@ -8,6 +8,7 @@ services: command: ["-verbose", "-hooks=/etc/webhook/hooks.json", "-hotreload"] environment: - ENV=${ENV:-dev} + - SECRET_TOKEN=${WEBHOOK_KEY:-blank} labels: - "traefik.enable=true" - "traefik.http.routers.webhook.rule=Host(`webhook.${ENV:-dev}.debate-timer.com`)" diff --git a/docker/webhook/hooks.json b/docker/webhook/hooks.json index 76a97e68..c85da652 100644 --- a/docker/webhook/hooks.json +++ b/docker/webhook/hooks.json @@ -3,6 +3,13 @@ "id": "deploy", "execute-command": "/home/ubuntu/scripts/deploy-docker.sh", "command-working-directory": "/home/ubuntu", + "pass-environment-to-command": [ + { + "source": "header", + "name": "X-Deploy-Token", + "envname": "REQUEST_TOKEN" + } + ], "pass-arguments-to-command": [ { "source": "entire-payload" } ] @@ -11,6 +18,19 @@ "id": "status", "execute-command": "/home/ubuntu/scripts/check-deploy-status.sh", "command-working-directory": "/home/ubuntu", - "include-command-output-in-response": true + "include-command-output-in-response": true, + "response-headers": [ + { + "name": "Content-Type", + "value": "application/json" + } + ], + "pass-environment-to-command": [ + { + "source": "header", + "name": "X-Deploy-Token", + "envname": "REQUEST_TOKEN" + } + ] } ] diff --git a/docker/webhook/webhook.Dockerfile b/docker/webhook/webhook.Dockerfile index ca2b8ba1..8e5dbd5e 100644 --- a/docker/webhook/webhook.Dockerfile +++ b/docker/webhook/webhook.Dockerfile @@ -1,4 +1,4 @@ FROM almir/webhook:2.8.3 USER root -RUN apk add --no-cache docker-cli docker-cli-compose curl bash +RUN apk add --no-cache docker-cli docker-cli-compose curl bash util-linux WORKDIR /etc/webhook diff --git a/scripts/deploy/check-deploy-status.sh b/scripts/deploy/check-deploy-status.sh index 0ef7d675..98dc2fa0 100644 --- a/scripts/deploy/check-deploy-status.sh +++ b/scripts/deploy/check-deploy-status.sh @@ -1,5 +1,10 @@ #!/bin/bash +if [ -z "$SECRET_TOKEN" ] || [ "$REQUEST_TOKEN" != "$SECRET_TOKEN" ]; then + echo '{"status": "error", "message": "Unauthorized request. Invalid Token."}' + exit 0 +fi + LOCK_FILE="/tmp/deploy-application.lock" exec 200>"$LOCK_FILE" diff --git a/scripts/deploy/deploy-docker.sh b/scripts/deploy/deploy-docker.sh index 9b9f3c47..4eeec174 100644 --- a/scripts/deploy/deploy-docker.sh +++ b/scripts/deploy/deploy-docker.sh @@ -1,5 +1,10 @@ #!/bin/bash +if [ -z "$SECRET_TOKEN" ] || [ "$REQUEST_TOKEN" != "$SECRET_TOKEN" ]; then + echo "[$(date)] 🚨 보안 경고: 유효하지 않은 배포 요청입니다. (Unauthorized)" + exit 1 +fi + echo "스크립트 실행 여부를 확인합니다." LOCK_FILE="/tmp/deploy-application.lock" exec 200>"$LOCK_FILE" From 36039a75f1ff8bf4fab78c8aa0c39dbf8f500da0 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Fri, 27 Feb 2026 12:46:14 +0900 Subject: [PATCH 07/12] =?UTF-8?q?feat:=20CD=20=EC=A7=84=ED=96=89=20?= =?UTF-8?q?=EC=8B=9C=20git=20update=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/webhook/docker-compose.webhook.yml | 3 +-- docker/webhook/hooks.json | 8 +++--- docker/webhook/webhook.Dockerfile | 2 +- scripts/deploy/deploy-docker.sh | 30 +++++++++++++++++++---- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/docker/webhook/docker-compose.webhook.yml b/docker/webhook/docker-compose.webhook.yml index 30e6d724..88ef841f 100644 --- a/docker/webhook/docker-compose.webhook.yml +++ b/docker/webhook/docker-compose.webhook.yml @@ -20,8 +20,7 @@ services: - /var/run/docker.sock:/var/run/docker.sock - /home/ubuntu/.docker:/root/.docker:ro - ./hooks.json:/etc/webhook/hooks.json - - ../../scripts/deploy:/home/ubuntu/scripts - - ..:/home/ubuntu/docker + - ../..:/home/ubuntu/debate-timer networks: - debate-timer-net depends_on: diff --git a/docker/webhook/hooks.json b/docker/webhook/hooks.json index c85da652..5270c3d6 100644 --- a/docker/webhook/hooks.json +++ b/docker/webhook/hooks.json @@ -1,8 +1,8 @@ [ { "id": "deploy", - "execute-command": "/home/ubuntu/scripts/deploy-docker.sh", - "command-working-directory": "/home/ubuntu", + "execute-command": "/home/ubuntu/debate-timer/scripts/deploy/deploy-docker.sh", + "command-working-directory": "/home/ubuntu/debate-timer", "pass-environment-to-command": [ { "source": "header", @@ -16,8 +16,8 @@ }, { "id": "status", - "execute-command": "/home/ubuntu/scripts/check-deploy-status.sh", - "command-working-directory": "/home/ubuntu", + "execute-command": "/home/ubuntu/debate-timer/scripts/deploy/check-deploy-status.sh", + "command-working-directory": "/home/ubuntu/debate-timer", "include-command-output-in-response": true, "response-headers": [ { diff --git a/docker/webhook/webhook.Dockerfile b/docker/webhook/webhook.Dockerfile index 8e5dbd5e..b3394f49 100644 --- a/docker/webhook/webhook.Dockerfile +++ b/docker/webhook/webhook.Dockerfile @@ -1,4 +1,4 @@ FROM almir/webhook:2.8.3 USER root -RUN apk add --no-cache docker-cli docker-cli-compose curl bash util-linux +RUN apk add --no-cache docker-cli-compose curl bash util-linux git WORKDIR /etc/webhook diff --git a/scripts/deploy/deploy-docker.sh b/scripts/deploy/deploy-docker.sh index 4eeec174..ea2c9d59 100644 --- a/scripts/deploy/deploy-docker.sh +++ b/scripts/deploy/deploy-docker.sh @@ -12,23 +12,43 @@ flock -n 200 || { echo "⚠️ 이미 배포 스크립트가 실행 중입니다 echo "스크립트를 실행하고 있지 않습니다. 배포를 시작합니다." TARGET_ENV=${ENV:-dev} -PROJECT_DIR="/home/ubuntu/docker" +PROJECT_DIR="/home/ubuntu/debate-timer" +DOCKER_DIR="/home/ubuntu/debate-timer/docker" TARGET_SERVICE="application" -cd $PROJECT_DIR || { echo "디렉토리 이동 실패"; exit 1; } +echo "--- Git 저장소 최신화 시작 ---" +cd $PROJECT_DIR || { echo "프로젝트 디렉토리 이동 실패"; exit 1; } +if [ "$TARGET_ENV" = "prod" ]; then + echo "▶ [ENV: prod] main 브랜치로 이동하여 최신 코드를 가져옵니다." + git fetch origin main + git switch main + git reset --hard origin/main # 로컬 변경사항 무시하고 원격과 완벽히 일치시킴 +elif [ "$TARGET_ENV" = "dev" ]; then + echo "▶ [ENV: dev] develop 브랜치로 이동하여 최신 코드를 가져옵니다." + git fetch origin develop + git switch develop + git reset --hard origin/develop +else + CURRENT_BRANCH=$(git branch --show-current) + echo "▶ [ENV: $TARGET_ENV] 현재 브랜치($CURRENT_BRANCH)에서 최신 코드를 가져옵니다." + git fetch origin "$CURRENT_BRANCH" + git reset --hard origin/"$CURRENT_BRANCH" +fi + +cd $DOCKER_DIR || { echo "디렉토리 이동 실패"; exit 1; } echo "--- 중단 배포 시작 ENV: $TARGET_ENV at $(date) ---" export ENV=$TARGET_ENV echo "최근 이미지 가져오는 중 (ENV: $TARGET_ENV)" -docker-compose pull $TARGET_SERVICE +docker compose pull $TARGET_SERVICE if docker ps --format '{{.Names}}' | grep -q "^${TARGET_SERVICE}$"; then echo "기존 $TARGET_SERVICE 중지 및 제거 중..." - docker-compose stop $TARGET_SERVICE + docker compose stop $TARGET_SERVICE fi echo "새 컨테이너 실행 중 - $TARGET_SERVICE..." -docker-compose up -d --no-deps $TARGET_SERVICE +docker compose up -d --no-deps $TARGET_SERVICE echo "헬스 체크 진행 중 - $TARGET_SERVICE" MAX_RETRIES=100 From 43c0efe13a1cbec29d77612f5e26970bd0920094 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Fri, 27 Feb 2026 04:33:25 +0000 Subject: [PATCH 08/12] =?UTF-8?q?fix:=20=ED=8C=8C=EC=9D=BC=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/deploy/check-deploy-status.sh | 0 scripts/deploy/deploy-docker.sh | 0 scripts/init/auto-swap.sh | 0 scripts/init/init-docker.sh | 0 scripts/init/init-letsencrypt.sh | 0 5 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/deploy/check-deploy-status.sh mode change 100644 => 100755 scripts/deploy/deploy-docker.sh mode change 100644 => 100755 scripts/init/auto-swap.sh mode change 100644 => 100755 scripts/init/init-docker.sh mode change 100644 => 100755 scripts/init/init-letsencrypt.sh diff --git a/scripts/deploy/check-deploy-status.sh b/scripts/deploy/check-deploy-status.sh old mode 100644 new mode 100755 diff --git a/scripts/deploy/deploy-docker.sh b/scripts/deploy/deploy-docker.sh old mode 100644 new mode 100755 diff --git a/scripts/init/auto-swap.sh b/scripts/init/auto-swap.sh old mode 100644 new mode 100755 diff --git a/scripts/init/init-docker.sh b/scripts/init/init-docker.sh old mode 100644 new mode 100755 diff --git a/scripts/init/init-letsencrypt.sh b/scripts/init/init-letsencrypt.sh old mode 100644 new mode 100755 From 741cf67c1183cd2306aeba5eb55e2152a94f5ae4 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Fri, 27 Feb 2026 14:08:02 +0900 Subject: [PATCH 09/12] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/application/docker-compose.application.yml | 2 +- docker/datadog/docker-compose.datadog.yml | 2 +- docker/webhook/docker-compose.webhook.yml | 2 +- docker/webhook/hooks.json | 2 ++ scripts/deploy/deploy-docker.sh | 6 +++++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docker/application/docker-compose.application.yml b/docker/application/docker-compose.application.yml index 4efe38ff..72d4e055 100644 --- a/docker/application/docker-compose.application.yml +++ b/docker/application/docker-compose.application.yml @@ -10,7 +10,7 @@ services: - DD_AGENT_HOST=datadog-agent - DD_SERVICE=debate-timer - DD_ENV=${ENV:-dev} - - DD_VERSION=1.0.0 + - DD_VERSION=${APP_VERSION:-1.0.0} - DD_LOGS_INJECTION=true - DD_PROFILING_ENABLED=true - DD_PROFILING_ALLOCATION_ENABLED=true diff --git a/docker/datadog/docker-compose.datadog.yml b/docker/datadog/docker-compose.datadog.yml index f7d82d27..a3823718 100644 --- a/docker/datadog/docker-compose.datadog.yml +++ b/docker/datadog/docker-compose.datadog.yml @@ -3,7 +3,7 @@ services: image: gcr.io/datadoghq/agent:7 container_name: datadog-agent environment: - - DD_API_KEY=${DD_API_KEY:-blank} + - DD_API_KEY=${DD_API_KEY} - DD_SITE=us5.datadoghq.com - DD_HOSTNAME=debate-timer-${ENV:-dev}-server - DD_APM_ENABLED=true diff --git a/docker/webhook/docker-compose.webhook.yml b/docker/webhook/docker-compose.webhook.yml index 88ef841f..c9e4e0a3 100644 --- a/docker/webhook/docker-compose.webhook.yml +++ b/docker/webhook/docker-compose.webhook.yml @@ -8,7 +8,7 @@ services: command: ["-verbose", "-hooks=/etc/webhook/hooks.json", "-hotreload"] environment: - ENV=${ENV:-dev} - - SECRET_TOKEN=${WEBHOOK_KEY:-blank} + - SECRET_TOKEN=${WEBHOOK_KEY} labels: - "traefik.enable=true" - "traefik.http.routers.webhook.rule=Host(`webhook.${ENV:-dev}.debate-timer.com`)" diff --git a/docker/webhook/hooks.json b/docker/webhook/hooks.json index 5270c3d6..db3e8f9d 100644 --- a/docker/webhook/hooks.json +++ b/docker/webhook/hooks.json @@ -1,6 +1,7 @@ [ { "id": "deploy", + "http-methods": ["POST"], "execute-command": "/home/ubuntu/debate-timer/scripts/deploy/deploy-docker.sh", "command-working-directory": "/home/ubuntu/debate-timer", "pass-environment-to-command": [ @@ -16,6 +17,7 @@ }, { "id": "status", + "http-methods": ["GET"], "execute-command": "/home/ubuntu/debate-timer/scripts/deploy/check-deploy-status.sh", "command-working-directory": "/home/ubuntu/debate-timer", "include-command-output-in-response": true, diff --git a/scripts/deploy/deploy-docker.sh b/scripts/deploy/deploy-docker.sh index ea2c9d59..9d7119cb 100755 --- a/scripts/deploy/deploy-docker.sh +++ b/scripts/deploy/deploy-docker.sh @@ -31,6 +31,10 @@ elif [ "$TARGET_ENV" = "dev" ]; then git reset --hard origin/develop else CURRENT_BRANCH=$(git branch --show-current) + if [ -z "$CURRENT_BRANCH" ]; then + echo "❌ 현재 브랜치를 확인할 수 없습니다 (detached HEAD 상태일 수 있음)" + exit 1 + fi echo "▶ [ENV: $TARGET_ENV] 현재 브랜치($CURRENT_BRANCH)에서 최신 코드를 가져옵니다." git fetch origin "$CURRENT_BRANCH" git reset --hard origin/"$CURRENT_BRANCH" @@ -41,7 +45,7 @@ echo "--- 중단 배포 시작 ENV: $TARGET_ENV at $(date) ---" export ENV=$TARGET_ENV echo "최근 이미지 가져오는 중 (ENV: $TARGET_ENV)" -docker compose pull $TARGET_SERVICE +docker compose pull $TARGET_SERVICE || { echo "❌ 이미지 풀 실패"; exit 1; } if docker ps --format '{{.Names}}' | grep -q "^${TARGET_SERVICE}$"; then echo "기존 $TARGET_SERVICE 중지 및 제거 중..." docker compose stop $TARGET_SERVICE From 0fbed91d020b988539902faa3586ca0fd84e8ca1 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Fri, 27 Feb 2026 14:21:58 +0900 Subject: [PATCH 10/12] =?UTF-8?q?fix:=20webhook=EC=9D=98=20git=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/webhook/webhook.Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker/webhook/webhook.Dockerfile b/docker/webhook/webhook.Dockerfile index b3394f49..0453da68 100644 --- a/docker/webhook/webhook.Dockerfile +++ b/docker/webhook/webhook.Dockerfile @@ -1,4 +1,7 @@ FROM almir/webhook:2.8.3 USER root RUN apk add --no-cache docker-cli-compose curl bash util-linux git + WORKDIR /etc/webhook + +RUN git config --global --add safe.directory /home/ubuntu/debate-timer From d86844c76768acb248ab4f70a94d7533b1433114 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Thu, 5 Mar 2026 20:26:56 +0900 Subject: [PATCH 11/12] =?UTF-8?q?fix:=20=EB=AA=85=EB=A0=B9=20=EC=8B=A4?= =?UTF-8?q?=ED=8C=A8=20=EC=8B=9C=20=EC=A6=89=EC=8B=9C=20=EC=A2=85=EB=A3=8C?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=ED=97=AC=EC=8A=A4=20=EC=B2=B4=ED=81=AC=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/deploy/deploy-docker.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/deploy/deploy-docker.sh b/scripts/deploy/deploy-docker.sh index 9d7119cb..746ecf3a 100755 --- a/scripts/deploy/deploy-docker.sh +++ b/scripts/deploy/deploy-docker.sh @@ -21,14 +21,14 @@ cd $PROJECT_DIR || { echo "프로젝트 디렉토리 이동 실패"; exit 1; } if [ "$TARGET_ENV" = "prod" ]; then echo "▶ [ENV: prod] main 브랜치로 이동하여 최신 코드를 가져옵니다." - git fetch origin main - git switch main - git reset --hard origin/main # 로컬 변경사항 무시하고 원격과 완벽히 일치시킴 + git fetch origin main || { echo "❌ git fetch(main) 실패"; exit 1; } + git switch main || { echo "❌ git switch(main) 실패"; exit 1; } + git reset --hard origin/main || { echo "❌ git reset(main) 실패"; exit 1; } elif [ "$TARGET_ENV" = "dev" ]; then echo "▶ [ENV: dev] develop 브랜치로 이동하여 최신 코드를 가져옵니다." - git fetch origin develop - git switch develop - git reset --hard origin/develop + git fetch origin develop || { echo "❌ git fetch(develop) 실패"; exit 1; } + git switch develop || { echo "❌ git switch(develop) 실패"; exit 1; } + git reset --hard origin/develop || { echo "❌ git reset(develop) 실패"; exit 1; } else CURRENT_BRANCH=$(git branch --show-current) if [ -z "$CURRENT_BRANCH" ]; then @@ -36,8 +36,8 @@ else exit 1 fi echo "▶ [ENV: $TARGET_ENV] 현재 브랜치($CURRENT_BRANCH)에서 최신 코드를 가져옵니다." - git fetch origin "$CURRENT_BRANCH" - git reset --hard origin/"$CURRENT_BRANCH" + git fetch origin "$CURRENT_BRANCH" || { echo "❌ git fetch($CURRENT_BRANCH) 실패"; exit 1; } + git reset --hard origin/"$CURRENT_BRANCH" || { echo "❌ git reset($CURRENT_BRANCH) 실패"; exit 1; } fi cd $DOCKER_DIR || { echo "디렉토리 이동 실패"; exit 1; } @@ -52,10 +52,10 @@ if docker ps --format '{{.Names}}' | grep -q "^${TARGET_SERVICE}$"; then fi echo "새 컨테이너 실행 중 - $TARGET_SERVICE..." -docker compose up -d --no-deps $TARGET_SERVICE +docker compose up -d --no-deps $TARGET_SERVICE || { echo "❌ 컨테이너 실행 실패"; exit 1; } echo "헬스 체크 진행 중 - $TARGET_SERVICE" -MAX_RETRIES=100 +MAX_RETRIES=50 SLEEP_SECOND=10 COUNT=0 From aa75b10a34bc32177457f405f7eb864c26362653 Mon Sep 17 00:00:00 2001 From: leegwichan Date: Thu, 5 Mar 2026 20:27:11 +0900 Subject: [PATCH 12/12] =?UTF-8?q?fix:=20restart=20=EC=98=B5=EC=85=98=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 --- docker/application/docker-compose.application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/application/docker-compose.application.yml b/docker/application/docker-compose.application.yml index 72d4e055..2e9ec098 100644 --- a/docker/application/docker-compose.application.yml +++ b/docker/application/docker-compose.application.yml @@ -51,4 +51,4 @@ services: - "com.datadoghq.ad.logs=[{\"source\": \"java\", \"service\": \"debate-timer\"}]" - restart: always + restart: unless-stopped