From a1f223348f22e483b41a7764cbb3d9f8c495ed91 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 01:24:31 +0900 Subject: [PATCH 01/14] =?UTF-8?q?chore:=20=EC=9D=B8=EC=8A=A4=ED=84=B4?= =?UTF-8?q?=EC=8A=A4=20=EB=B6=84=EB=A6=AC=20=EB=8C=80=EC=8B=A0=20=EB=8B=A8?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B8=EC=8A=A4=ED=84=B4=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- terraform/compute.tf | 49 +------------------------------------------- terraform/dns.tf | 12 ++--------- terraform/network.tf | 13 +++--------- terraform/outputs.tf | 7 +------ 4 files changed, 7 insertions(+), 74 deletions(-) diff --git a/terraform/compute.tf b/terraform/compute.tf index 7cace9f5..d10c794f 100644 --- a/terraform/compute.tf +++ b/terraform/compute.tf @@ -3,11 +3,6 @@ resource "google_compute_address" "prod" { region = "asia-northeast3" } -resource "google_compute_address" "staging" { - name = "cockple-staging-ip" - region = "us-central1" -} - resource "google_compute_instance" "prod" { name = "cockple-prod" machine_type = "e2-medium" # 4GB RAM @@ -18,7 +13,7 @@ resource "google_compute_instance" "prod" { boot_disk { initialize_params { image = "ubuntu-os-cloud/ubuntu-2204-lts" - size = 20 + size = 30 } } @@ -33,48 +28,6 @@ resource "google_compute_instance" "prod" { ssh-keys = "ubuntu:${var.ssh_public_key}" } - service_account { - email = google_service_account.cockple_app.email - scopes = ["cloud-platform"] # GCS 등 GCP 서비스 접근 - } - - metadata_startup_script = <<-EOF - #!/bin/bash - apt-get update -y - apt-get install -y docker.io - curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose - chmod +x /usr/local/bin/docker-compose - systemctl enable docker - systemctl start docker - usermod -aG docker ubuntu - EOF -} - -resource "google_compute_instance" "staging" { - name = "cockple-staging" - machine_type = "e2-micro" # 1GB RAM, 무료 티어 - zone = "us-central1-a" - tags = ["cockple-staging"] - allow_stopping_for_update = true - - boot_disk { - initialize_params { - image = "ubuntu-os-cloud/ubuntu-2204-lts" - size = 30 # 무료 티어 최대 - } - } - - network_interface { - subnetwork = google_compute_subnetwork.staging.id - access_config { - nat_ip = google_compute_address.staging.address - } - } - - metadata = { - ssh-keys = "ubuntu:${var.ssh_public_key}" - } - service_account { email = google_service_account.cockple_app.email scopes = ["cloud-platform"] diff --git a/terraform/dns.tf b/terraform/dns.tf index 95d6a4f7..55143ad9 100644 --- a/terraform/dns.tf +++ b/terraform/dns.tf @@ -6,7 +6,7 @@ resource "cloudflare_record" "prod" { proxied = true } -resource "cloudflare_record" "prod_ssh" { +resource "cloudflare_record" "ssh" { zone_id = var.cloudflare_zone_id name = "ssh" content = google_compute_address.prod.address @@ -17,15 +17,7 @@ resource "cloudflare_record" "prod_ssh" { resource "cloudflare_record" "staging" { zone_id = var.cloudflare_zone_id name = "staging" - content = google_compute_address.staging.address + content = google_compute_address.prod.address type = "A" proxied = true } - -resource "cloudflare_record" "staging_ssh" { - zone_id = var.cloudflare_zone_id - name = "ssh-staging" - content = google_compute_address.staging.address - type = "A" - proxied = false -} diff --git a/terraform/network.tf b/terraform/network.tf index d65214f4..2eeadd24 100644 --- a/terraform/network.tf +++ b/terraform/network.tf @@ -10,13 +10,6 @@ resource "google_compute_subnetwork" "prod" { network = google_compute_network.cockple_vpc.id } -resource "google_compute_subnetwork" "staging" { - name = "cockple-subnet-staging" - ip_cidr_range = "10.0.2.0/24" - region = "us-central1" - network = google_compute_network.cockple_vpc.id -} - # Cloudflare IP 대역에서만 80 포트 허용 (origin IP 보호) resource "google_compute_firewall" "allow_http_cloudflare" { name = "cockple-allow-http-cloudflare" @@ -45,7 +38,7 @@ resource "google_compute_firewall" "allow_http_cloudflare" { "131.0.72.0/22", ] - target_tags = ["cockple-prod", "cockple-staging"] + target_tags = ["cockple-prod"] } resource "google_compute_firewall" "allow_ssh" { @@ -58,5 +51,5 @@ resource "google_compute_firewall" "allow_ssh" { } source_ranges = ["0.0.0.0/0"] - target_tags = ["cockple-prod", "cockple-staging"] -} \ No newline at end of file + target_tags = ["cockple-prod"] +} diff --git a/terraform/outputs.tf b/terraform/outputs.tf index aeb7a1a9..717c5af4 100644 --- a/terraform/outputs.tf +++ b/terraform/outputs.tf @@ -1,13 +1,8 @@ output "prod_ip" { - description = "Prod 서버 공인 IP" + description = "서버 공인 IP (prod + staging 공용)" value = google_compute_address.prod.address } -output "staging_ip" { - description = "Staging 서버 공인 IP" - value = google_compute_address.staging.address -} - output "gcs_bucket_name" { description = "GCS 버킷 이름" value = google_storage_bucket.cockple_assets.name From e716cc776c73cb9e10e5b7d33804fbb35b02a9ec Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 01:51:07 +0900 Subject: [PATCH 02/14] =?UTF-8?q?chore:=20=EB=B0=B0=ED=8F=AC=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EB=B3=84=EB=8F=84=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 51 ++++------------------------------------ scripts/deploy.sh | 40 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 46 deletions(-) create mode 100644 scripts/deploy.sh diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index c663c3ae..5982b796 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -23,25 +23,9 @@ jobs: id: vars run: | if [ "${{ github.ref_name }}" == "main" ]; then - echo "APP_SECRET=APPLICATION" >> $GITHUB_OUTPUT echo "DOCKER_TAG=latest" >> $GITHUB_OUTPUT - echo "COMPOSE_FILE=docker-compose.prod.yml" >> $GITHUB_OUTPUT else - echo "APP_SECRET=APPLICATION_STAGING" >> $GITHUB_OUTPUT echo "DOCKER_TAG=staging" >> $GITHUB_OUTPUT - echo "COMPOSE_FILE=docker-compose.staging.yml" >> $GITHUB_OUTPUT - fi - - - name: Remove existing application.yml - run: rm -f src/main/resources/application.yml - - - name: Make application.yml - run: | - mkdir -p src/main/resources - if [ "${{ github.ref_name }}" == "main" ]; then - echo "${{ secrets.APPLICATION }}" > src/main/resources/application.yml - else - echo "${{ secrets.APPLICATION_STAGING }}" > src/main/resources/application.yml fi - name: Build with Gradle @@ -55,39 +39,14 @@ jobs: docker build -f Dockerfile -t ${{ secrets.DOCKER_REPO }}:${{ steps.vars.outputs.DOCKER_TAG }} . docker push ${{ secrets.DOCKER_REPO }}:${{ steps.vars.outputs.DOCKER_TAG }} - - name: Deploy_EC2 + - name: Deploy uses: appleboy/ssh-action@master - id: deploy with: host: ${{ secrets.HOST }} username: ubuntu key: ${{ secrets.KEY }} script: | - cd /home/ubuntu/home/monitor - echo "=== 배포 전 상태 ===" - sudo docker ps - sudo docker image prune -f - sudo docker pull ${{ secrets.DOCKER_REPO }}:${{ steps.vars.outputs.DOCKER_TAG }} - - if [ "${{ github.ref_name }}" == "main" ]; then - sudo docker stop cockple-app || true - sudo docker rm -f cockple-app || true - if ! sudo docker ps | grep -q cockple-redis; then - echo "Redis(prod)가 죽었음, 재시작 중..." - sudo docker compose -f docker-compose.prod.yml up -d redis - sleep 10 - fi - sudo docker compose -f docker-compose.prod.yml up -d cockple-app - else - sudo docker stop cockple-app-staging || true - sudo docker rm -f cockple-app-staging || true - if ! sudo docker ps | grep -q cockple-redis-staging; then - echo "Redis(staging)가 죽었음, 재시작 중..." - sudo docker compose -f docker-compose.staging.yml up -d redis-staging - sleep 10 - fi - sudo docker compose -f docker-compose.staging.yml up -d cockple-app-staging - fi - - echo "=== 배포 후 상태 ===" - sudo docker ps \ No newline at end of file + chmod +x /home/ubuntu/cockple/scripts/deploy.sh + bash /home/ubuntu/cockple/scripts/deploy.sh \ + ${{ secrets.DOCKER_REPO }} \ + ${{ github.ref_name }} diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100644 index 00000000..556a604c --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +DOCKER_REPO=$1 +BRANCH=$2 + +cd /home/ubuntu/cockple + +if [ "$BRANCH" == "main" ]; then + SERVICE="cockple-app" + TAG="latest" +else + SERVICE="cockple-app-staging" + TAG="staging" +fi + +echo "=== 배포 전 상태 ===" +sudo docker ps + +sudo docker image prune -f +sudo docker pull $DOCKER_REPO:$TAG + +sudo docker stop $SERVICE || true +sudo docker rm -f $SERVICE || true + +if ! sudo docker ps | grep -q cockple-mysql; then + echo "MySQL이 죽었음, 재시작 중..." + sudo docker compose up -d mysql + sleep 15 +fi + +if ! sudo docker ps | grep -q cockple-redis; then + echo "Redis가 죽었음, 재시작 중..." + sudo docker compose up -d redis + sleep 5 +fi + +sudo docker compose up -d $SERVICE + +echo "=== 배포 후 상태 ===" +sudo docker ps From 6856fe5c6f4e78f79589a22b4ad9b763d298b5c1 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:02:05 +0900 Subject: [PATCH 03/14] =?UTF-8?q?chore:=20application.yml=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=ED=95=A9=20staging=EA=B3=BC=20prod=EB=A5=BC=20Docker?= =?UTF-8?q?=EB=A1=9C=20=EB=9D=84=EC=9A=B0=EB=AF=80=EB=A1=9C=20url=EC=9D=B4?= =?UTF-8?q?=20=EA=B3=B5=EA=B0=9C=EB=90=98=EC=96=B4=EB=8F=84=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=20=EB=B6=88=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-prod.yml | 12 ++++++++++++ src/main/resources/application-staging.yml | 12 ++++++++++++ src/main/resources/application.yml | 11 +++++------ 3 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 src/main/resources/application-prod.yml create mode 100644 src/main/resources/application-staging.yml diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 00000000..6a100ef4 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,12 @@ +spring: + datasource: + url: jdbc:mysql://cockple-mysql:3306/cockple?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul + + jpa: + hibernate: + ddl-auto: validate + + data: + redis: + host: cockple-redis + database: 0 diff --git a/src/main/resources/application-staging.yml b/src/main/resources/application-staging.yml new file mode 100644 index 00000000..42edab0c --- /dev/null +++ b/src/main/resources/application-staging.yml @@ -0,0 +1,12 @@ +spring: + datasource: + url: jdbc:mysql://cockple-mysql:3306/cockple_staging?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul + + jpa: + hibernate: + ddl-auto: update + + data: + redis: + host: cockple-redis + database: 1 diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index fb6831ad..1016c81c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -11,25 +11,23 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: ${SPRING_DATASOURCE_URL} - username: ${SPRING_DATASOURCE_USERNAME} - password: ${SPRING_DATASOURCE_PASSWORD} + username: ${DB_USERNAME} + password: ${DB_PASSWORD} sql: init: mode: never jpa: + show_sql: false hibernate: ddl-auto: update - show_sql: false properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect format_sql: false use_sql_comments: false default_batch_fetch_size: 1000 - show_sql: false - servlet: multipart: @@ -40,6 +38,7 @@ spring: redis: host: localhost port: 6379 + database: 0 lettuce: pool: max-active: 8 @@ -52,6 +51,7 @@ spring: write-dates-as-timestamps: false deserialization: fail-on-unknown-properties: false + cache: type: redis @@ -85,4 +85,3 @@ jwt: logging: level: org.hibernate.SQL: WARN - From 3996208d45f05e86805a3a8f8242cf6b795dc473 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:03:44 +0900 Subject: [PATCH 04/14] =?UTF-8?q?chore:=20Cloudflare=EC=97=90=EC=84=9C=20S?= =?UTF-8?q?SL=20=EC=9D=B8=EC=A6=9D=EC=9D=84=20=EC=A7=84=ED=96=89=ED=95=98?= =?UTF-8?q?=EA=B3=A0,=20Nginx=EC=97=90=EC=84=9C=20=EC=BB=A8=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=84=88=EB=A1=9C=20=EB=B6=84=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nginx/conf.d/prod.conf | 12 ++++++++++++ nginx/conf.d/staging.conf | 12 ++++++++++++ nginx/nginx.conf | 25 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 nginx/conf.d/prod.conf create mode 100644 nginx/conf.d/staging.conf create mode 100644 nginx/nginx.conf diff --git a/nginx/conf.d/prod.conf b/nginx/conf.d/prod.conf new file mode 100644 index 00000000..4f812314 --- /dev/null +++ b/nginx/conf.d/prod.conf @@ -0,0 +1,12 @@ +server { + listen 80; + server_name cockple.shop; + + location / { + proxy_pass http://cockple-app:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/nginx/conf.d/staging.conf b/nginx/conf.d/staging.conf new file mode 100644 index 00000000..7fd60692 --- /dev/null +++ b/nginx/conf.d/staging.conf @@ -0,0 +1,12 @@ +server { + listen 80; + server_name staging.cockple.shop; + + location / { + proxy_pass http://cockple-app-staging:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 00000000..2ce913f6 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,25 @@ +user nginx; +worker_processes auto; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + client_max_body_size 30M; + + include /etc/nginx/conf.d/*.conf; +} From 298cfa1a915e75b57edff57b76689ac81704b85c Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:04:06 +0900 Subject: [PATCH 05/14] =?UTF-8?q?chore:=20docker=20compose=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 123 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..6ba624ae --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,123 @@ +name: cockple + +services: + mysql: + image: mysql:8.0 + container_name: cockple-mysql + restart: always + ports: + - "3306:3306" + environment: + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + MYSQL_USER: ${DB_USERNAME} + MYSQL_PASSWORD: ${DB_PASSWORD} + TZ: Asia/Seoul + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + - --innodb-buffer-pool-size=256M + volumes: + - mysql-data:/var/lib/mysql + - ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 10s + timeout: 5s + retries: 5 + mem_limit: 512m + memswap_limit: 768m + + redis: + image: redis:7-alpine + container_name: cockple-redis + restart: always + command: + - redis-server + - --appendonly + - "yes" + - --maxmemory + - 200mb + - --maxmemory-policy + - allkeys-lru + volumes: + - redis-data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 3s + retries: 5 + mem_limit: 256m + memswap_limit: 384m + + cockple-app: + container_name: cockple-app + image: kanghana1/cockple:latest + restart: always + environment: + JAVA_TOOL_OPTIONS: "-Xms768m -Xmx768m" + SPRING_PROFILES_ACTIVE: prod + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + S3_BUCKET: ${S3_BUCKET} + S3_ACCESS_KEY: ${S3_ACCESS_KEY} + S3_SECRET_KEY: ${S3_SECRET_KEY} + KAKAO_CLIENT_ID: ${KAKAO_CLIENT_ID} + KAKAO_CLIENT_SECRET: ${KAKAO_CLIENT_SECRET} + KAKAO_REDIRECT_URI: ${KAKAO_REDIRECT_URI_PROD} + KAKAO_ADMIN_KEY: ${KAKAO_ADMIN_KEY} + JWT_SECRET_KEY: ${JWT_SECRET_KEY} + depends_on: + mysql: + condition: service_healthy + redis: + condition: service_healthy + mem_limit: 1200m + memswap_limit: 1536m + + cockple-app-staging: + container_name: cockple-app-staging + image: kanghana1/cockple:staging + restart: always + environment: + JAVA_TOOL_OPTIONS: "-Xms128m -Xmx512m" + SPRING_PROFILES_ACTIVE: staging + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + S3_BUCKET: ${S3_BUCKET} + S3_ACCESS_KEY: ${S3_ACCESS_KEY} + S3_SECRET_KEY: ${S3_SECRET_KEY} + KAKAO_CLIENT_ID: ${KAKAO_CLIENT_ID} + KAKAO_CLIENT_SECRET: ${KAKAO_CLIENT_SECRET} + KAKAO_REDIRECT_URI: ${KAKAO_REDIRECT_URI_STAGING} + KAKAO_ADMIN_KEY: ${KAKAO_ADMIN_KEY} + JWT_SECRET_KEY: ${JWT_SECRET_KEY} + depends_on: + mysql: + condition: service_healthy + redis: + condition: service_healthy + mem_limit: 1024m + memswap_limit: 1280m + + nginx: + image: nginx:stable-alpine + container_name: cockple-nginx + restart: always + ports: + - "80:80" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./nginx/conf.d:/etc/nginx/conf.d:ro + depends_on: + - cockple-app + - cockple-app-staging + mem_limit: 64m + memswap_limit: 128m + +volumes: + mysql-data: + redis-data: + +networks: + default: + name: cockple_network From bf329bd1e740cd7c15caf2a377d70a4d81895453 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:04:52 +0900 Subject: [PATCH 06/14] =?UTF-8?q?improve:=20redis=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=9D=B8=EB=8D=B1=EC=8A=A4=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=B4=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/umc/cockple/demo/global/config/RedisConfig.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/umc/cockple/demo/global/config/RedisConfig.java b/src/main/java/umc/cockple/demo/global/config/RedisConfig.java index 1efe480a..d8de2b9e 100644 --- a/src/main/java/umc/cockple/demo/global/config/RedisConfig.java +++ b/src/main/java/umc/cockple/demo/global/config/RedisConfig.java @@ -32,9 +32,13 @@ public class RedisConfig { @Value("${spring.data.redis.port}") private int redisPort; + @Value("${spring.data.redis.database:0}") + private int redisDatabase; + @Bean public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisHost, redisPort); + configuration.setDatabase(redisDatabase); return new LettuceConnectionFactory(configuration); } From 7bf0b38e567568ce83698f5229f71a0a61b28d1b Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:05:13 +0900 Subject: [PATCH 07/14] =?UTF-8?q?chore:=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=B2=A0=EC=9D=B4=EC=8A=A4=20=EC=83=9D=EC=84=B1=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- init-db.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 init-db.sql diff --git a/init-db.sql b/init-db.sql new file mode 100644 index 00000000..a50a51c5 --- /dev/null +++ b/init-db.sql @@ -0,0 +1,2 @@ +CREATE DATABASE IF NOT EXISTS cockple CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +CREATE DATABASE IF NOT EXISTS cockple_staging CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; From 449892871d06de08a5deb2945728a6830b2508c4 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:06:12 +0900 Subject: [PATCH 08/14] =?UTF-8?q?chore:=20jre=EB=A7=8C=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EB=8F=84=20jar=20=ED=8C=8C=EC=9D=BC=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=EC=9D=B4=20=EA=B0=80=EB=8A=A5=ED=95=98=EB=AF=80?= =?UTF-8?q?=EB=A1=9C=20jre=EB=A1=9C=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=ED=81=AC=EA=B8=B0=EB=A5=BC=20=EC=A4=84=EC=9D=B4=EA=B3=A0,=20CM?= =?UTF-8?q?D=20=EB=8C=80=EC=8B=A0=20ENTRYPOINT=EB=A1=9C=20JAVA=5FOPTION?= =?UTF-8?q?=EC=9D=B4=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 99a04c76..36c0d42a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM eclipse-temurin:17-jdk-jammy +FROM eclipse-temurin:17-jre-jammy COPY build/libs/cockple.demo-0.0.1-SNAPSHOT.jar app.jar -CMD ["java", "-Dspring.profiles.active=dev", "-jar", "app.jar"] \ No newline at end of file +ENTRYPOINT ["java", "-jar", "app.jar"] From 11467e58f56eedbe6a30e1a644d7cec63ff80134 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:06:49 +0900 Subject: [PATCH 09/14] =?UTF-8?q?chore:=20cd=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=EC=97=90=EC=84=9C=20=EC=B4=88=EA=B8=B0=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EB=93=A4=EC=9D=84=20scp=EB=A1=9C=20=EB=B3=B5=EC=82=AC?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EC=9E=90=EB=8F=99=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 5982b796..cd8fa2d9 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -39,6 +39,15 @@ jobs: docker build -f Dockerfile -t ${{ secrets.DOCKER_REPO }}:${{ steps.vars.outputs.DOCKER_TAG }} . docker push ${{ secrets.DOCKER_REPO }}:${{ steps.vars.outputs.DOCKER_TAG }} + - name: Copy files to server + uses: appleboy/scp-action@master + with: + host: ${{ secrets.HOST }} + username: ubuntu + key: ${{ secrets.KEY }} + source: "docker-compose.yml,init-db.sql,nginx/,scripts/" + target: /home/ubuntu/cockple + - name: Deploy uses: appleboy/ssh-action@master with: From 9b174b87832cf98912f0a000f1499cc3254aed04 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:10:19 +0900 Subject: [PATCH 10/14] =?UTF-8?q?chore:=20DB=20=EC=82=AC=EC=9A=A9=20?= =?UTF-8?q?=EC=8B=9C=20=EB=B3=84=EB=8F=84=EC=9D=98=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=8C=80=EC=8B=A0=20root=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd.yml | 16 ++++++++++++++++ docker-compose.yml | 6 +----- src/main/resources/application.yml | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index cd8fa2d9..7f8f4449 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -54,8 +54,24 @@ jobs: host: ${{ secrets.HOST }} username: ubuntu key: ${{ secrets.KEY }} + envs: >- + DB_PASSWORD, + S3_BUCKET,S3_ACCESS_KEY,S3_SECRET_KEY, + KAKAO_CLIENT_ID,KAKAO_CLIENT_SECRET,KAKAO_REDIRECT_URI_PROD,KAKAO_REDIRECT_URI_STAGING,KAKAO_ADMIN_KEY, + JWT_SECRET_KEY script: | chmod +x /home/ubuntu/cockple/scripts/deploy.sh bash /home/ubuntu/cockple/scripts/deploy.sh \ ${{ secrets.DOCKER_REPO }} \ ${{ github.ref_name }} + env: + DB_PASSWORD: ${{ secrets.DB_PASSWORD }} + S3_BUCKET: ${{ secrets.S3_BUCKET }} + S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }} + S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }} + KAKAO_CLIENT_ID: ${{ secrets.KAKAO_CLIENT_ID }} + KAKAO_CLIENT_SECRET: ${{ secrets.KAKAO_CLIENT_SECRET }} + KAKAO_REDIRECT_URI_PROD: ${{ secrets.KAKAO_REDIRECT_URI_PROD }} + KAKAO_REDIRECT_URI_STAGING: ${{ secrets.KAKAO_REDIRECT_URI_STAGING }} + KAKAO_ADMIN_KEY: ${{ secrets.KAKAO_ADMIN_KEY }} + JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }} diff --git a/docker-compose.yml b/docker-compose.yml index 6ba624ae..09d702bd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,9 +8,7 @@ services: ports: - "3306:3306" environment: - MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} - MYSQL_USER: ${DB_USERNAME} - MYSQL_PASSWORD: ${DB_PASSWORD} + MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} TZ: Asia/Seoul command: - --character-set-server=utf8mb4 @@ -56,7 +54,6 @@ services: environment: JAVA_TOOL_OPTIONS: "-Xms768m -Xmx768m" SPRING_PROFILES_ACTIVE: prod - DB_USERNAME: ${DB_USERNAME} DB_PASSWORD: ${DB_PASSWORD} S3_BUCKET: ${S3_BUCKET} S3_ACCESS_KEY: ${S3_ACCESS_KEY} @@ -81,7 +78,6 @@ services: environment: JAVA_TOOL_OPTIONS: "-Xms128m -Xmx512m" SPRING_PROFILES_ACTIVE: staging - DB_USERNAME: ${DB_USERNAME} DB_PASSWORD: ${DB_PASSWORD} S3_BUCKET: ${S3_BUCKET} S3_ACCESS_KEY: ${S3_ACCESS_KEY} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1016c81c..24bf7dc8 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -11,7 +11,7 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: ${SPRING_DATASOURCE_URL} - username: ${DB_USERNAME} + username: root password: ${DB_PASSWORD} sql: From 9778b33c0d3b2fe26c401ba2190d4a69fc886b8a Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:19:57 +0900 Subject: [PATCH 11/14] =?UTF-8?q?deploy.sh=EC=97=90=EC=84=9C=20env=20?= =?UTF-8?q?=EA=B0=92=20=EB=B0=9B=EC=95=84=EC=84=9C=20.env=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/deploy.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 556a604c..b6ae1028 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -13,6 +13,19 @@ else TAG="staging" fi +cat > .env << EOF +DB_PASSWORD=${DB_PASSWORD} +S3_BUCKET=${S3_BUCKET} +S3_ACCESS_KEY=${S3_ACCESS_KEY} +S3_SECRET_KEY=${S3_SECRET_KEY} +KAKAO_CLIENT_ID=${KAKAO_CLIENT_ID} +KAKAO_CLIENT_SECRET=${KAKAO_CLIENT_SECRET} +KAKAO_REDIRECT_URI_PROD=${KAKAO_REDIRECT_URI_PROD} +KAKAO_REDIRECT_URI_STAGING=${KAKAO_REDIRECT_URI_STAGING} +KAKAO_ADMIN_KEY=${KAKAO_ADMIN_KEY} +JWT_SECRET_KEY=${JWT_SECRET_KEY} +EOF + echo "=== 배포 전 상태 ===" sudo docker ps From ab46eddea36a480a3756308158df188ed8a9d3b4 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:23:44 +0900 Subject: [PATCH 12/14] =?UTF-8?q?chore:=20=EB=A1=9C=EC=BB=AC=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=8C=8C=EC=9D=BC=EC=9D=80=20=EB=B3=84=EB=8F=84?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-local.yml | 12 ++++++++++++ src/main/resources/application.yml | 2 -- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/application-local.yml diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml new file mode 100644 index 00000000..873cc611 --- /dev/null +++ b/src/main/resources/application-local.yml @@ -0,0 +1,12 @@ +spring: + datasource: + url: jdbc:mysql://localhost:3306/cockple?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul + + data: + redis: + host: localhost + database: 0 + + jpa: + hibernate: + ddl-auto: update diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 24bf7dc8..d5793df7 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -10,7 +10,6 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: ${SPRING_DATASOURCE_URL} username: root password: ${DB_PASSWORD} @@ -36,7 +35,6 @@ spring: data: redis: - host: localhost port: 6379 database: 0 lettuce: From 892cd255ecdd638969cfc5054af7aee41c2ff546 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:24:14 +0900 Subject: [PATCH 13/14] =?UTF-8?q?docs:=20DB=20=EB=B0=8F=20redis=20?= =?UTF-8?q?=ED=84=B0=EB=84=90=EB=A7=81=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/tunnel.bat | 20 ++++++++++++++++++++ scripts/tunnel.sh | 24 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 scripts/tunnel.bat create mode 100644 scripts/tunnel.sh diff --git a/scripts/tunnel.bat b/scripts/tunnel.bat new file mode 100644 index 00000000..fec35329 --- /dev/null +++ b/scripts/tunnel.bat @@ -0,0 +1,20 @@ +@echo off +:: 사용법: scripts\tunnel.bat [GCP_IP] +:: 예시: scripts\tunnel.bat 34.64.xxx.xxx + +set GCP_IP=%1 + +if "%GCP_IP%"=="" ( + set /p GCP_IP=GCP IP 입력: +) + +echo 터널링 시작: %GCP_IP% +echo MySQL -^> localhost:3306 -^> cockple-mysql:3306 +echo Redis -^> localhost:6379 -^> cockple-redis:6379 +echo 종료: Ctrl+C + +ssh -N ^ + -L 3306:localhost:3306 ^ + -L 6379:localhost:6379 ^ + -i %USERPROFILE%\.ssh\cockple ^ + ubuntu@%GCP_IP% diff --git a/scripts/tunnel.sh b/scripts/tunnel.sh new file mode 100644 index 00000000..92895996 --- /dev/null +++ b/scripts/tunnel.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# GCP 서버를 통해 Docker MySQL/Redis 터널링 +# 사용법: ./scripts/tunnel.sh [GCP_IP] +# 예시: ./scripts/tunnel.sh 34.64.xxx.xxx + +GCP_IP=${1:-$(cat .tunnel-ip 2>/dev/null)} + +if [ -z "$GCP_IP" ]; then + echo "GCP IP를 인자로 전달하거나 .tunnel-ip 파일에 저장하세요." + echo "사용법: ./scripts/tunnel.sh [GCP_IP]" + exit 1 +fi + +echo "터널링 시작: $GCP_IP" +echo " MySQL → localhost:3306 → cockple-mysql:3306" +echo " Redis → localhost:6379 → cockple-redis:6379" +echo "종료: Ctrl+C" + +ssh -N \ + -L 3306:localhost:3306 \ + -L 6379:localhost:6379 \ + -i ~/.ssh/cockple \ + ubuntu@$GCP_IP From 1d32663db1617ed2b5b5f400353ef81dcbae7388 Mon Sep 17 00:00:00 2001 From: dmori Date: Wed, 25 Feb 2026 02:34:08 +0900 Subject: [PATCH 14/14] =?UTF-8?q?chore:=20nginx,=20mysql,=20redis=EB=8F=84?= =?UTF-8?q?=20deploy.sh=EB=A1=9C=20=EC=9E=90=EB=8F=99=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=98=AC=EB=A6=AC=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/deploy.sh | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index b6ae1028..132b5a13 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -29,24 +29,13 @@ EOF echo "=== 배포 전 상태 ===" sudo docker ps +sudo docker compose up -d mysql redis nginx sudo docker image prune -f sudo docker pull $DOCKER_REPO:$TAG sudo docker stop $SERVICE || true sudo docker rm -f $SERVICE || true -if ! sudo docker ps | grep -q cockple-mysql; then - echo "MySQL이 죽었음, 재시작 중..." - sudo docker compose up -d mysql - sleep 15 -fi - -if ! sudo docker ps | grep -q cockple-redis; then - echo "Redis가 죽었음, 재시작 중..." - sudo docker compose up -d redis - sleep 5 -fi - sudo docker compose up -d $SERVICE echo "=== 배포 후 상태 ==="