Skip to content

Commit 71e4ea5

Browse files
authored
Merge pull request #469 from boostcampwm-2024/chore/self-hosted-runner
📦 chore: self hosted runner 적용 및 프로덕션 서버 디렉토리 구조 변경
2 parents c130865 + e82464c commit 71e4ea5

File tree

12 files changed

+293
-145
lines changed

12 files changed

+293
-145
lines changed

.github/workflows/deploy_client.yml

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,35 @@ on:
88
- "client/**"
99
workflow_dispatch: # 수동 실행을 허용하는 이벤트
1010

11+
env:
12+
DIST_TARGET: /var/dist
13+
1114
jobs:
12-
deployment:
13-
runs-on: ubuntu-latest
15+
deploy:
16+
runs-on: [self-hosted, prod]
1417
steps:
15-
# public 서버로 ssh 접속
16-
- name: ssh connection
17-
uses: appleboy/[email protected]
18+
- name: 코드 체크아웃
19+
uses: actions/checkout@v4
20+
21+
- name: Node.js 설정
22+
uses: actions/setup-node@v4
1823
with:
19-
host: ${{ secrets.CLOUD_PUBLIC_INSTANCE_HOST }}
20-
username: ${{ secrets.CLOUD_PUBLIC_INSTANCE_USERNAME }}
21-
key: ${{ secrets.CLOUD_PUBLIC_INSTANCE_SSH_KEY }}
22-
port: ${{ secrets.CLOUD_PUBLIC_INSTANCE_PORT }}
23-
script: |
24-
export NVM_DIR=~/.nvm
25-
source ~/.nvm/nvm.sh
24+
node-version: "22"
25+
cache: "npm"
26+
cache-dependency-path: client/package-lock.json
27+
28+
- name: 의존성 설치
29+
working-directory: ./client
30+
run: npm ci
2631

27-
cd /var/web05-Denamu
28-
git pull origin main
29-
cd client/
32+
- name: 클라이언트 빌드
33+
working-directory: ./client
34+
run: npm run build
3035

31-
npm ci
32-
npm run build
36+
- name: 빌드 결과물 배포
37+
run: |
38+
sudo mkdir -p "$DIST_TARGET"
39+
sudo rm -rf "$DIST_TARGET"/*
40+
sudo cp -r ./client/dist/* "$DIST_TARGET"/
41+
sudo chown -R www-data:www-data "$DIST_TARGET"
42+
echo "✅ FE 빌드 결과물이 $DIST_TARGET 에 배포되었습니다."
Lines changed: 79 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,87 @@
1-
name: Feed-Crawler-Deployment
1+
name: Feed-Crawler Deployment
22

33
on:
44
push:
5-
branches:
6-
- main
7-
paths:
8-
- "feed-crawler/**"
9-
workflow_dispatch: # 수동 실행을 허용하는 이벤트
5+
branches: [main]
6+
paths: ["feed-crawler/**", "docker-compose/**"]
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
packages: write
12+
13+
env:
14+
IMAGE_NAME: ghcr.io/${{ github.repository }}/feed-crawler
15+
IMAGE_TAG: sha-${{ github.sha }}
16+
SERVICE: feed-crawler
17+
ENV_DIR: /var/prod_config/feed-crawler
18+
ENV_FILE: /var/prod_config/feed-crawler/.env.prod
19+
COMPOSE_FILE: docker-compose/docker-compose.prod.yml
1020

1121
jobs:
12-
deployment:
22+
build-and-push:
1323
runs-on: ubuntu-latest
1424
steps:
15-
# public 서버로 ssh 접속
16-
- name: ssh connection
17-
uses: appleboy/[email protected]
25+
- uses: actions/checkout@v4
26+
27+
- uses: docker/setup-buildx-action@v3
28+
29+
- name: GHCR 로그인
30+
uses: docker/login-action@v3
31+
with:
32+
registry: ghcr.io
33+
username: ${{ github.actor }}
34+
password: ${{ secrets.GHCR_GITHUB_TOKEN }}
35+
36+
- name: Docker 이미지 Build 및 Push
37+
uses: docker/build-push-action@v6
38+
with:
39+
context: ./feed-crawler
40+
file: ./feed-crawler/docker/Dockerfile.prod
41+
push: true
42+
tags: |
43+
${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
44+
${{ env.IMAGE_NAME }}:latest
45+
cache-from: type=gha
46+
cache-to: type=gha,mode=max
47+
48+
deploy:
49+
runs-on: [self-hosted, prod]
50+
needs: build-and-push # Build 및 Push가 끝나면 시작
51+
steps:
52+
- name: 코드 체크아웃
53+
uses: actions/checkout@v4
54+
55+
- name: GHCR 로그인 (prod)
56+
uses: docker/login-action@v3
1857
with:
19-
host: ${{ secrets.CLOUD_PUBLIC_INSTANCE_HOST }}
20-
username: ${{ secrets.CLOUD_PUBLIC_INSTANCE_USERNAME }}
21-
key: ${{ secrets.CLOUD_PUBLIC_INSTANCE_SSH_KEY }}
22-
port: ${{ secrets.CLOUD_PUBLIC_INSTANCE_PORT }}
23-
script: |
24-
cd /var/web05-Denamu
25-
git pull origin main
26-
cd /var/web05-Denamu/feed-crawler/
27-
28-
mkdir -p env
29-
echo "DB_PORT=${{ secrets.FEED_CRAWLER_DB_PORT }}" > env/.env.prod
30-
echo "DB_HOST=${{ secrets.FEED_CRAWLER_DB_HOST }}" >> env/.env.prod
31-
echo "DB_NAME=${{ secrets.FEED_CRAWLER_DB_NAME }}" >> env/.env.prod
32-
echo "DB_USER=${{ secrets.FEED_CRAWLER_DB_USER }}" >> env/.env.prod
33-
echo "DB_PASS=${{ secrets.FEED_CRAWLER_DB_PASSWORD }}" >> env/.env.prod
34-
echo "TIME_INTERVAL=${{ vars.FEED_CRAWLER_TIME_INTERVAL }}" >> env/.env.prod
35-
echo "REDIS_HOST=${{secrets.REDIS_HOST }}" >> env/.env.prod
36-
echo "REDIS_PORT=${{secrets.REDIS_PORT}}" >> env/.env.prod
37-
echo "REDIS_USERNAME=${{secrets.REDIS_USERNAME}}" >> env/.env.prod
38-
echo "REDIS_PASSWORD=${{secrets.REDIS_PASSWORD}}" >> env/.env.prod
39-
echo "AI_API_KEY=${{secrets.AI_API_KEY}}" >> env/.env.prod
40-
echo "AI_RATE_LIMIT_COUNT=${{ vars.AI_RATE_LIMIT_COUNT }}" >> env/.env.prod
41-
42-
cd /var/web05-Denamu
43-
docker-compose -f docker-compose/docker-compose.prod.yml up --build --no-deps --force-recreate -d feed-crawler
44-
docker image prune -f
45-
docker builder prune -f
58+
registry: ghcr.io
59+
username: ${{ github.actor }}
60+
password: ${{ secrets.GHCR_GITHUB_TOKEN }}
61+
62+
- name: 환경변수 최신화
63+
run: |
64+
sudo mkdir -p "$ENV_DIR"
65+
sudo install -m 600 /dev/null "$ENV_FILE"
66+
{
67+
echo "DB_PORT=${{ secrets.FEED_CRAWLER_DB_PORT }}"
68+
echo "DB_HOST=${{ secrets.FEED_CRAWLER_DB_HOST }}"
69+
echo "DB_NAME=${{ secrets.FEED_CRAWLER_DB_NAME }}"
70+
echo "DB_USER=${{ secrets.FEED_CRAWLER_DB_USER }}"
71+
echo "DB_PASS=${{ secrets.FEED_CRAWLER_DB_PASSWORD }}"
72+
echo "TIME_INTERVAL=${{ vars.FEED_CRAWLER_TIME_INTERVAL }}"
73+
echo "REDIS_HOST=${{ secrets.REDIS_HOST }}"
74+
echo "REDIS_PORT=${{ secrets.REDIS_PORT }}"
75+
echo "REDIS_USERNAME=${{ secrets.REDIS_USERNAME }}"
76+
echo "REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}"
77+
echo "AI_API_KEY=${{ secrets.AI_API_KEY }}"
78+
echo "AI_RATE_LIMIT_COUNT=${{ vars.AI_RATE_LIMIT_COUNT }}"
79+
} | sudo tee "$ENV_FILE" >/dev/null
80+
81+
- name: Docker 이미지 Pull & 서비스 재시작
82+
run: |
83+
docker pull "${IMAGE_NAME}:${IMAGE_TAG}" || true
84+
docker pull "${IMAGE_NAME}:latest" || true
85+
docker compose -f "$COMPOSE_FILE" pull "$SERVICE"
86+
docker compose -f "$COMPOSE_FILE" up -d --no-deps --force-recreate "$SERVICE"
87+
docker image prune -f || true

.github/workflows/deploy_infra.yml

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,18 @@ on:
88
- docker-compose/docker-compose.prod*.yml
99
workflow_dispatch:
1010

11+
env:
12+
COMPOSE_FILE: docker-compose/docker-compose.prod.yml
13+
1114
jobs:
1215
deployment:
13-
runs-on: ubuntu-latest
16+
runs-on: [self-hosted, prod]
1417
steps:
15-
# public 서버로 ssh 접속
16-
- name: ssh connection
17-
uses: appleboy/[email protected]
18-
with:
19-
host: ${{ secrets.CLOUD_PUBLIC_INSTANCE_HOST }}
20-
username: ${{ secrets.CLOUD_PUBLIC_INSTANCE_USERNAME }}
21-
key: ${{ secrets.CLOUD_PUBLIC_INSTANCE_SSH_KEY }}
22-
port: ${{ secrets.CLOUD_PUBLIC_INSTANCE_PORT }}
23-
script: |
24-
cd /var/web05-Denamu
25-
git pull origin main
26-
docker-compose -f docker-compose/docker-compose.prod.yml down
27-
docker-compose -f docker-compose/docker-compose.prod.yml up -d
18+
- name: 코드 체크아웃
19+
uses: actions/checkout@v4
20+
21+
- name: 인프라 서비스 재시작
22+
run: |
23+
docker compose -f "$COMPOSE_FILE" down
24+
docker compose -f "$COMPOSE_FILE" up -d
25+
docker image prune -f || true

.github/workflows/deploy_server.yml

Lines changed: 87 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,53 +2,95 @@ name: BE Deployment
22

33
on:
44
push:
5-
branches:
6-
- main
7-
paths:
8-
- "server/**"
9-
workflow_dispatch: # 수동 실행을 허용하는 이벤트
5+
branches: [main]
6+
paths: ["server/**", "docker-compose/**"]
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
packages: write
12+
13+
env:
14+
IMAGE_NAME: ghcr.io/${{ github.repository }}/server
15+
IMAGE_TAG: sha-${{ github.sha }}
16+
SERVICE: app
17+
ENV_DIR: /var/prod_config/server
18+
ENV_FILE: /var/prod_config/server/.env.prod
19+
COMPOSE_FILE: docker-compose/docker-compose.prod.yml
1020

1121
jobs:
12-
deployment:
22+
build-and-push:
1323
runs-on: ubuntu-latest
1424
steps:
15-
# public 서버로 ssh 접속
16-
- name: ssh connection
17-
uses: appleboy/[email protected]
25+
- uses: actions/checkout@v4
26+
27+
- uses: docker/setup-buildx-action@v3
28+
29+
- name: GHCR 로그인
30+
uses: docker/login-action@v3
31+
with:
32+
registry: ghcr.io
33+
username: ${{ github.actor }}
34+
password: ${{ secrets.GHCR_GITHUB_TOKEN }}
35+
36+
- name: Docker 이미지 Build 및 Push
37+
uses: docker/build-push-action@v6
38+
with:
39+
context: ./server
40+
file: ./server/docker/Dockerfile.prod
41+
push: true
42+
tags: |
43+
${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
44+
${{ env.IMAGE_NAME }}:latest
45+
cache-from: type=gha
46+
cache-to: type=gha,mode=max
47+
48+
deploy:
49+
runs-on: [self-hosted, prod]
50+
needs: build-and-push # Build 및 Push가 끝나면 시작
51+
steps:
52+
- name: 코드 체크아웃
53+
uses: actions/checkout@v4
54+
55+
- name: GHCR 로그인 (prod)
56+
uses: docker/login-action@v3
1857
with:
19-
host: ${{ secrets.CLOUD_PUBLIC_INSTANCE_HOST }}
20-
username: ${{ secrets.CLOUD_PUBLIC_INSTANCE_USERNAME }}
21-
key: ${{ secrets.CLOUD_PUBLIC_INSTANCE_SSH_KEY }}
22-
port: ${{ secrets.CLOUD_PUBLIC_INSTANCE_PORT }}
23-
script: |
24-
cd /var/web05-Denamu
25-
git pull origin main
26-
cd /var/web05-Denamu/server
27-
28-
mkdir -p env
29-
echo "PORT=${{ secrets.PRODUCT_PORT }}" > env/.env.prod
30-
echo "DB_TYPE=mysql" >> env/.env.prod
31-
echo "DB_DATABASE=${{ secrets.PRODUCT_DB_DATABASE }}" >> env/.env.prod
32-
echo "DB_HOST=${{ secrets.PRODUCT_DB_HOST }}" >> env/.env.prod
33-
echo "DB_PORT=${{ secrets.PRODUCT_DB_PORT }}" >> env/.env.prod
34-
echo "DB_USERNAME=${{ secrets.PRODUCT_DB_USERNAME }}" >> env/.env.prod
35-
echo "DB_PASSWORD=${{ secrets.PRODUCT_DB_PASSWORD }}" >> env/.env.prod
36-
echo "REDIS_HOST=${{secrets.REDIS_HOST }}" >> env/.env.prod
37-
echo "REDIS_PORT=${{secrets.REDIS_PORT}}" >> env/.env.prod
38-
echo "REDIS_USERNAME=${{secrets.REDIS_USERNAME}}" >> env/.env.prod
39-
echo "REDIS_PASSWORD=${{secrets.REDIS_PASSWORD}}" >> env/.env.prod
40-
echo "EMAIL_USER=${{secrets.EMAIL_USER}}" >> env/.env.prod
41-
echo "EMAIL_PASSWORD=${{secrets.EMAIL_PASSWORD}}" >> env/.env.prod
42-
echo "JWT_ACCESS_SECRET=${{secrets.JWT_ACCESS_SECRET}}" >> env/.env.prod
43-
echo "JWT_REFRESH_SECRET=${{secrets.JWT_REFRESH_SECRET}}" >> env/.env.prod
44-
echo "REFRESH_TOKEN_EXPIRE=${{secrets.REFRESH_TOKEN_EXPIRE}}" >> env/.env.prod
45-
echo "ACCESS_TOKEN_EXPIRE=${{secrets.ACCESS_TOKEN_EXPIRE}}" >> env/.env.prod
46-
echo "GOOGLE_CLIENT_ID=${{secrets.GOOGLE_CLIENT_ID}}" >> env/.env.prod
47-
echo "GOOGLE_CLIENT_SECRET=${{secrets.GOOGLE_CLIENT_SECRET}}" >> env/.env.prod
48-
echo "GITHUB_CLIENT_ID=${{secrets.GIT_CLIENT_ID}}" >> env/.env.prod
49-
echo "GITHUB_CLIENT_SECRET=${{secrets.GIT_CLIENT_SECRET}}" >> env/.env.prod
50-
51-
cd /var/web05-Denamu
52-
docker-compose -f docker-compose/docker-compose.prod.yml up --build --no-deps --force-recreate -d app
53-
docker image prune -f
54-
docker builder prune -f
58+
registry: ghcr.io
59+
username: ${{ github.actor }}
60+
password: ${{ secrets.GHCR_GITHUB_TOKEN }}
61+
62+
- name: 환경변수 최신화
63+
run: |
64+
sudo mkdir -p "$ENV_DIR"
65+
sudo install -m 600 /dev/null "$ENV_FILE"
66+
{
67+
echo "PORT=${{ secrets.PRODUCT_PORT }}"
68+
echo "DB_TYPE=mysql"
69+
echo "DB_DATABASE=${{ secrets.PRODUCT_DB_DATABASE }}"
70+
echo "DB_HOST=${{ secrets.PRODUCT_DB_HOST }}"
71+
echo "DB_PORT=${{ secrets.PRODUCT_DB_PORT }}"
72+
echo "DB_USERNAME=${{ secrets.PRODUCT_DB_USERNAME }}"
73+
echo "DB_PASSWORD=${{ secrets.PRODUCT_DB_PASSWORD }}"
74+
echo "REDIS_HOST=${{ secrets.REDIS_HOST }}"
75+
echo "REDIS_PORT=${{ secrets.REDIS_PORT }}"
76+
echo "REDIS_USERNAME=${{ secrets.REDIS_USERNAME }}"
77+
echo "REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}"
78+
echo "EMAIL_USER=${{ secrets.EMAIL_USER }}"
79+
echo "EMAIL_PASSWORD=${{ secrets.EMAIL_PASSWORD }}"
80+
echo "JWT_ACCESS_SECRET=${{ secrets.JWT_ACCESS_SECRET }}"
81+
echo "JWT_REFRESH_SECRET=${{ secrets.JWT_REFRESH_SECRET }}"
82+
echo "REFRESH_TOKEN_EXPIRE=${{ secrets.REFRESH_TOKEN_EXPIRE }}"
83+
echo "ACCESS_TOKEN_EXPIRE=${{ secrets.ACCESS_TOKEN_EXPIRE }}"
84+
echo "GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }}"
85+
echo "GOOGLE_CLIENT_SECRET=${{ secrets.GOOGLE_CLIENT_SECRET }}"
86+
echo "GITHUB_CLIENT_ID=${{ secrets.GIT_CLIENT_ID }}"
87+
echo "GITHUB_CLIENT_SECRET=${{ secrets.GIT_CLIENT_SECRET }}"
88+
} | sudo tee "$ENV_FILE" >/dev/null
89+
90+
- name: Docker 이미지 Pull & 서비스 재시작
91+
run: |
92+
docker pull "${IMAGE_NAME}:${IMAGE_TAG}" || true
93+
docker pull "${IMAGE_NAME}:latest" || true
94+
docker compose -f "$COMPOSE_FILE" pull "$SERVICE"
95+
docker compose -f "$COMPOSE_FILE" up -d --no-deps --force-recreate "$SERVICE"
96+
docker image prune -f || true

0 commit comments

Comments
 (0)