Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 96 additions & 26 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# CI/CD에 ν•„μš”ν•œ GitHub Secrets (Repo Settings > Secrets and variables > Actions)

name: cicd

on:
Expand All @@ -16,23 +18,32 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Log - Checkout done
run: echo ">>> [CI] Checkout done"

- name: Setup JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"

- name: Log - JDK ready
run: echo ">>> [CI] JDK 17 ready"

- name: Setup Gradle cache
uses: gradle/actions/setup-gradle@v4

- name: Run tests
run: ./gradlew test --no-daemon
run: |
echo ">>> [CI] Running tests..."
./gradlew test --no-daemon
echo ">>> [CI] Tests passed"

docker-build-and-push:
name: Docker Build and Push
runs-on: ubuntu-latest
needs: test
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/production'
if: github.ref == 'refs/heads/production' && github.event_name == 'push'

permissions:
contents: read
Expand All @@ -42,15 +53,24 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Log - Checkout done
run: echo ">>> [Docker] Checkout done"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log - Buildx ready
run: echo ">>> [Docker] Buildx ready"

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Log - Docker Hub login done
run: echo ">>> [Docker] Docker Hub login done"

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
Expand All @@ -69,11 +89,14 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

- name: Log - Image pushed
run: echo ">>> [Docker] Image built and pushed"

deploy:
name: Deploy to GCE
runs-on: ubuntu-latest
needs: docker-build-and-push
if: github.event_name == 'push' && github.ref == 'refs/heads/production'
if: github.ref == 'refs/heads/production' && github.event_name == 'push'

steps:
- name: Deploy over SSH
Expand All @@ -93,15 +116,18 @@ jobs:
SMTP_USERNAME: ${{ secrets.SMTP_USERNAME }}
SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }}
CONTAINER_NAME: dorumdorum-be
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO_FULL_NAME: ${{ github.repository }}
with:
host: ${{ secrets.GCE_HOST }}
username: ${{ secrets.GCE_USER }}
key: ${{ secrets.GCE_SSH_KEY }}
port: ${{ secrets.GCE_SSH_PORT }}
envs: IMAGE,DOCKERHUB_USERNAME,DOCKERHUB_TOKEN,FIREBASE_SERVICE_ACCOUNT_B64,RDB_USERNAME,RDB_URL,RDB_PASSWORD,MONGODB_URI,JWT_KEY,JWT_ACCESS_EXPIRATION,JWT_REFRESH_EXPIRATION,SMTP_USERNAME,SMTP_PASSWORD,CONTAINER_NAME
envs: IMAGE,DOCKERHUB_USERNAME,DOCKERHUB_TOKEN,FIREBASE_SERVICE_ACCOUNT_B64,RDB_USERNAME,RDB_URL,RDB_PASSWORD,MONGODB_URI,JWT_KEY,JWT_ACCESS_EXPIRATION,JWT_REFRESH_EXPIRATION,SMTP_USERNAME,SMTP_PASSWORD,CONTAINER_NAME,GITHUB_TOKEN,REPO_FULL_NAME
script_stop: true
script: |
set -e
echo ">>> [Deploy] SSH 연결됨, ν™˜κ²½ λ³€μˆ˜ μ •κ·œν™” 쀑..."

RDB_USERNAME="$(printf '%s' "$RDB_USERNAME" | tr -d '\r\n')"
RDB_URL="$(printf '%s' "$RDB_URL" | tr -d '\r\n')"
Expand All @@ -116,6 +142,7 @@ jobs:
DEPLOY_PATH="${HOME}/dorumdorum"
mkdir -p "$DEPLOY_PATH"
cd "$DEPLOY_PATH"
echo ">>> [Deploy] DEPLOY_PATH=$DEPLOY_PATH"

# 1) Firebase μ„œλΉ„μŠ€ 계정 파일 생성 (VM에 μ €μž₯)
printf '%s' "$FIREBASE_SERVICE_ACCOUNT_B64" | base64 -d > firebase-service-account.json
Expand All @@ -138,6 +165,7 @@ jobs:
"SMTP_PASSWORD=$SMTP_PASSWORD" \
"FIREBASE_SERVICE_ACCOUNT_PATH=$FIREBASE_SERVICE_ACCOUNT_PATH" > .env
chmod 600 .env
echo ">>> [Deploy] .env, firebase-service-account.json 생성 μ™„λ£Œ"

docker info >/dev/null 2>&1 || {
echo "Docker socket permission denied for current deploy user."
Expand All @@ -146,32 +174,74 @@ jobs:
}

echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
echo ">>> [Deploy] Docker Hub 둜그인 μ™„λ£Œ"

echo ">>> [Deploy] Redis 이미지 pull 쀑..."
docker pull redis:7-alpine
echo ">>> [Deploy] Backend 이미지 pull 쀑..."
docker pull "$IMAGE"

echo ">>> [Deploy] λ„€νŠΈμ›Œν¬ 확인/생성 쀑..."
docker network inspect dorumdorum-net >/dev/null 2>&1 || docker network create dorumdorum-net

docker stop dorumdorum-redis >/dev/null 2>&1 || true
docker rm dorumdorum-redis >/dev/null 2>&1 || true
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
docker rm "$CONTAINER_NAME" >/dev/null 2>&1 || true

docker run -d --name dorumdorum-redis \
--restart unless-stopped \
--network dorumdorum-net \
-v redis-data:/data \
redis:7-alpine redis-server --appendonly yes

# 4) μ»¨ν…Œμ΄λ„ˆ μ‹€ν–‰: .env둜 FIREBASE_SERVICE_ACCOUNT_PATHκΉŒμ§€ μ£Όμž…λ¨
docker run -d --name "$CONTAINER_NAME" \
--restart unless-stopped \
--network dorumdorum-net \
-p 8080:8080 \
--env-file .env \
-e REDIS_HOST=dorumdorum-redis \
-e REDIS_PORT=6379 \
-v "$DEPLOY_PATH/firebase-service-account.json:/app/firebase-service-account.json:ro" \
"$IMAGE"

# 톡합 docker-compose 파일 및 μ„€μ • νŒŒμΌλ“€ μ€€λΉ„
COMPOSE_PATH="${HOME}/dorumdorum-compose"
mkdir -p "$COMPOSE_PATH"
cd "$COMPOSE_PATH"
echo ">>> [Deploy] COMPOSE_PATH=$COMPOSE_PATH, Git clone 쀑..."
rm -rf temp_repo

# Gitμ—μ„œ production 브랜치둜 docker-compose.yml, monitoring κ°€μ Έμ˜€κΈ°
git clone --depth 1 -b production "https://x-access-token:${GITHUB_TOKEN}@github.com/${REPO_FULL_NAME}.git" temp_repo
echo ">>> [Deploy] Clone μ™„λ£Œ, docker-compose.yml Β· monitoring 볡사 쀑..."

if [ -f "temp_repo/docker-compose.yml" ]; then
cp temp_repo/docker-compose.yml .
echo ">>> [Deploy] docker-compose.yml 볡사 μ™„λ£Œ"
else
echo "ERROR: docker-compose.yml not found in temp_repo/"
ls -la temp_repo/ || true
exit 1
fi

if [ -d "temp_repo/monitoring" ]; then
mkdir -p monitoring
cp -r temp_repo/monitoring/* monitoring/
echo ">>> [Deploy] monitoring μ„€μ • 파일 볡사 μ™„λ£Œ"
else
echo "WARNING: monitoring directory not found, creating empty structure"
mkdir -p monitoring/prometheus monitoring/grafana/provisioning/dashboards/json monitoring/grafana/provisioning/datasources
fi

rm -rf temp_repo
echo ">>> [Deploy] temp_repo μ‚­μ œ, compose 파일 확인 쀑..."

# docker-compose.yml 파일 쑴재 확인
if [ ! -f "docker-compose.yml" ]; then
echo "ERROR: docker-compose.yml not found after copy"
ls -la
exit 1
fi

# .env 파일과 firebase-service-account.json 볡사
cp "$DEPLOY_PATH/.env" .
cp "$DEPLOY_PATH/firebase-service-account.json" .
echo ">>> [Deploy] .env, firebase-service-account.json 볡사 μ™„λ£Œ"

# docker-compose둜 λͺ¨λ“  μ„œλΉ„μŠ€ μ‹€ν–‰
export BACKEND_IMAGE="$IMAGE"
export CONTAINER_NAME="$CONTAINER_NAME"
echo ">>> [Deploy] κΈ°μ‘΄ μ»¨ν…Œμ΄λ„ˆ 정리 (down + μ΄λ¦„μœΌλ‘œ κ°•μ œ 제거)..."
docker-compose -f docker-compose.yml down --remove-orphans >/dev/null 2>&1 || true
docker rm -f dorumdorum-redis dorumdorum-be dorumdorum-prometheus dorumdorum-grafana 2>/dev/null || true
echo ">>> [Deploy] docker-compose up -d μ‹€ν–‰ 쀑..."
docker-compose -f docker-compose.yml up -d

echo ">>> [Deploy] 였래된 이미지 정리 쀑..."
docker image prune -af --filter "until=168h"

echo ">>> [Deploy] 배포 μ™„λ£Œ"
echo "- Backend: http://localhost:8080"
echo "- Redis: localhost:6379"
echo "- Prometheus: http://localhost:9090"
echo "- Grafana: http://localhost:3000 (admin/admin)"
28 changes: 0 additions & 28 deletions be.env.example

This file was deleted.

77 changes: 77 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
services:
redis:
image: redis:7-alpine
container_name: dorumdorum-redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
restart: unless-stopped
networks:
- dorumdorum-net

backend:
image: ${BACKEND_IMAGE:-koungq/dorumdorum-be:latest}
container_name: ${CONTAINER_NAME:-dorumdorum-be}
ports:
- "8080:8080"
env_file:
- .env
environment:
- REDIS_HOST=redis
- REDIS_PORT=6379
volumes:
- ./firebase-service-account.json:/app/firebase-service-account.json:ro
depends_on:
- redis
restart: unless-stopped
networks:
- dorumdorum-net

prometheus:
image: prom/prometheus:v2.52.0
container_name: dorumdorum-prometheus
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus/prometheus.prod.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--web.enable-lifecycle"
extra_hosts:
- "host.docker.internal:host-gateway"
restart: unless-stopped
networks:
- dorumdorum-net

grafana:
image: grafana/grafana:11.2.0
container_name: dorumdorum-grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_USERS_ALLOW_SIGN_UP=false
- GF_SERVER_ROOT_URL=http://localhost:3000
- GF_INSTALL_PLUGINS=grafana-piechart-panel
volumes:
- ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro
- grafana_data:/var/lib/grafana
depends_on:
- prometheus
restart: unless-stopped
networks:
- dorumdorum-net

volumes:
redis_data:
prometheus_data:
grafana_data:

networks:
dorumdorum-net:
external: true
12 changes: 12 additions & 0 deletions monitoring/grafana/provisioning/dashboards/dashboards.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: 1
providers:
- name: "dorumdorum"
orgId: 1
folder: "Dorumdorum"
folderUid: "dorumdorum"
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: true
options:
path: /etc/grafana/provisioning/dashboards/json
Loading