Skip to content

Commit b65c609

Browse files
authored
Merge pull request #331 from Pseudo-Lab/feat/platform
feat(platform): setup devfactory homepage and workflow
2 parents d83769e + 7aece22 commit b65c609

27 files changed

+4061
-7
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: 🚀 DevFactory Homepage Deploy
2+
run-name: 🚀 Deploying to Production by @${{ github.actor }}
3+
4+
on:
5+
push:
6+
branches:
7+
- main
8+
paths:
9+
- 'platform/**'
10+
- '.github/workflows/devfactory-homepage.yml'
11+
workflow_dispatch:
12+
13+
# 같은 브랜치 동시 실행 시 이전 잡 취소(경쟁 배포 방지)
14+
concurrency:
15+
group: DevFactory-homepage-${{ github.ref }}
16+
cancel-in-progress: true
17+
18+
jobs:
19+
deploy-prod:
20+
if: github.ref_name == 'main'
21+
name: 🚀 Deploy DF-platform (Production)
22+
runs-on: oracle
23+
environment: platform
24+
defaults:
25+
run:
26+
working-directory: ./platform
27+
steps:
28+
- uses: actions/checkout@v4
29+
30+
- name: Write .env (prod)
31+
run: |
32+
cat > .env <<'EOF'
33+
APP_HOST=${{ vars.APP_HOST }}
34+
DATABASE_URL=${{ secrets.DATABASE_URL }}
35+
EOF
36+
37+
- name: Build & up (prod)
38+
run: |
39+
set -euxo pipefail
40+
docker compose -p df-platform-main config -q
41+
docker compose -p df-platform-main down --remove-orphans
42+
docker compose -p df-platform-main up -d --build --remove-orphans
43+
docker image prune -f --filter "label=org.pseudolab.project=devfactory-platform"

README.en.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Highlight activities of DevFactory 🤗
6565
<tr>
6666
<td align="center" width="200" valign="top">
6767
<b>Soohyun Kim</b><br>
68-
<img src="docs/imgs/members/soohyun.png" height="180px"><br>
68+
<img src="platform/frontend/public/members/soohyun.png" height="180px"><br>
6969
<img src="https://img.shields.io/badge/-Builder-3776AB">
7070
<img src="https://img.shields.io/badge/-TPM-94A3B8">
7171
<img src="https://img.shields.io/badge/-INFRA-94A3B8"><br>
@@ -76,7 +76,7 @@ Highlight activities of DevFactory 🤗
7676
</td>
7777
<td align="center" width="200" valign="top">
7878
<b>Yesin Kim</b><br>
79-
<img src="docs/imgs/members/yesin.jpg" height="180px"><br>
79+
<img src="platform/frontend/public/members/yesin.jpg" height="180px"><br>
8080
<img src="https://img.shields.io/badge/-Builder-3776AB">
8181
<img src="https://img.shields.io/badge/-BE-0891B2"><br>
8282
<img src="https://img.shields.io/badge/-10th-DAA520">
@@ -86,7 +86,7 @@ Highlight activities of DevFactory 🤗
8686
</td>
8787
<td align="center" width="200" valign="top">
8888
<b>Seungkyu Kim</b><br>
89-
<img src="docs/imgs/members/seungkyu.jpg" height="180px"><br>
89+
<img src="platform/frontend/public/members/seungkyu.jpg" height="180px"><br>
9090
<img src="https://img.shields.io/badge/-Builder-3776AB">
9191
<img src="https://img.shields.io/badge/-FE-60A5FA"><br>
9292
<img src="https://img.shields.io/badge/-10th-DAA520">

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
## 🌟 프로젝트
3434
DevFactory의 주요 활동 내역입니다 🤗
3535
* **🐳 기술 튜토리얼 (Tutorials)**
36-
* Docker, Git, LLM 등 실습 중심의 콘텐츠와 오프라인 워크숍을 운영합니다.
36+
* Docker, Git, LLM 등 실습 중심의 온라인 콘텐츠와 오프라인 워크숍을 운영합니다.
3737
* [🔗 튜토리얼 보기](https://pseudo-lab.github.io/DevFactory/intro.html)
3838

3939
* **🎮 네트워킹 프로그램 (BINGO)**
@@ -60,7 +60,7 @@ DevFactory의 주요 활동 내역입니다 🤗
6060
<tr>
6161
<td align="center" width="200" valign="top">
6262
<b>김수현</b><br>
63-
<img src="docs/imgs/members/soohyun.png" height="180px"><br>
63+
<img src="platform/frontend/public/members/soohyun.png" height="180px"><br>
6464
<img src="https://img.shields.io/badge/-Builder-3776AB">
6565
<img src="https://img.shields.io/badge/-TPM-94A3B8">
6666
<img src="https://img.shields.io/badge/-INFRA-94A3B8"><br>
@@ -71,7 +71,7 @@ DevFactory의 주요 활동 내역입니다 🤗
7171
</td>
7272
<td align="center" width="200" valign="top">
7373
<b>김예신</b><br>
74-
<img src="docs/imgs/members/yesin.jpg" height="180px"><br>
74+
<img src="platform/frontend/public/members/yesin.jpg" height="180px"><br>
7575
<img src="https://img.shields.io/badge/-Builder-3776AB">
7676
<img src="https://img.shields.io/badge/-BE-0891B2"><br>
7777
<img src="https://img.shields.io/badge/-10th-DAA520">
@@ -81,7 +81,7 @@ DevFactory의 주요 활동 내역입니다 🤗
8181
</td>
8282
<td align="center" width="200" valign="top">
8383
<b>김승규</b><br>
84-
<img src="docs/imgs/members/seungkyu.jpg" height="180px"><br>
84+
<img src="platform/frontend/public/members/seungkyu.jpg" height="180px"><br>
8585
<img src="https://img.shields.io/badge/-Builder-3776AB">
8686
<img src="https://img.shields.io/badge/-FE-60A5FA"><br>
8787
<img src="https://img.shields.io/badge/-10th-DAA520">

platform/.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Domain Setting
2+
APP_HOST=your-domain.com
3+
4+
# Database Setting
5+
DATABASE_URL=postgresql://user:pass@devfactory-postgres:5432/dbname

platform/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.env
2+
node_modules/
3+
dist/
4+
build/
5+
.DS_Store

platform/PLATFORM.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# DevFactory Unified Platform
2+
3+
소개 페이지와 백엔드 API가 통합된 DevFactory의 메인 플랫폼 관리 가이드입니다.
4+
본 설정은 **Traefik 역방향 프록시**를 사용하는 서버 환경을 전제로 합니다.
5+
6+
### 1. Production Build
7+
로컬 또는 서버에서 프론트엔드 에셋을 빌드합니다.
8+
```bash
9+
cd platform/frontend
10+
npm install
11+
npm run build
12+
```
13+
결과물은 `platform/frontend/dist` 디렉토리에 생성됩니다.
14+
15+
### 2. Deployment Options
16+
17+
#### Option A: Static Hosting (GitHub Pages / Vercel)
18+
단순 웹 페이지(Frontend)만 배포하고 싶은 경우에 사용합니다.
19+
1. `platform/frontend`에서 `npm run build`를 실행합니다.
20+
2. `dist` 폴더 내의 파일들을 배포 서비스에 업로드합니다.
21+
> **참고**: 이 방식으로는 자체 DB 방문자 추적 기능을 사용할 수 없습니다.
22+
23+
#### Option B: Unified Platform (Full-Stack / Docker)
24+
방문자 추적 기능을 포함한 전체 플랫폼 배포 방식입니다. **(권장)**
25+
26+
### 3. Environment Setup
27+
`platform` 디렉토리 루트에 `.env` 파일을 생성하고 서버 환경에 맞게 정보를 입력합니다.
28+
```bash
29+
# .env 파일 예시
30+
APP_HOST=intro.pseudolab-devfactory.com
31+
32+
# Database
33+
DATABASE_URL=postgresql://user:pass@devfactory-postgres:5432/dbname
34+
```
35+
36+
### 3. Traefik 기반 배포
37+
Docker Compose를 사용하여 서비스를 실행합니다.
38+
```bash
39+
cd platform
40+
# 전체 서비스 빌드 및 실행
41+
docker-compose up -d --build
42+
```
43+
44+
#### 배포 확인
45+
- **Frontend (Web)**: `https://<APP_HOST>`
46+
- **Backend (API)**: `https://<APP_HOST>/api/health`
47+
48+
### 4. Database Schema
49+
사용 중인 `logging.access_log` 테이블의 구조는 다음과 같아야 합니다.
50+
```sql
51+
CREATE TABLE logging.access_log (
52+
id SERIAL PRIMARY KEY,
53+
ts TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
54+
path TEXT NOT NULL,
55+
method TEXT NOT NULL,
56+
status INTEGER NOT NULL,
57+
latency_ms INTEGER,
58+
ip_hash TEXT,
59+
user_agent TEXT,
60+
referrer TEXT
61+
);
62+
```
63+
64+
### 5. Verification
65+
- Traefik 대시보드에서 `df-platform` 관련 라우터가 활성화되었는지 확인하세요.
66+
- 브라우저에서 사이트 접속 시 HTTPS 상시 연결 및 방문 기록 적재 여부를 확인하세요.

platform/docker-compose.dev.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
services:
2+
# Development Overrides with Traefik Support
3+
frontend:
4+
build:
5+
context: ./frontend
6+
target: build-stage
7+
image: devfactory-frontend:dev
8+
command: npm run dev -- --host 0.0.0.0
9+
volumes:
10+
- ./frontend:/app
11+
- /app/node_modules
12+
labels:
13+
- traefik.enable=true
14+
- traefik.docker.network=traefik
15+
- traefik.http.routers.df-platform-web.rule=Host(`${APP_HOST}`)
16+
- traefik.http.routers.df-platform-web.entrypoints=websecure
17+
- traefik.http.routers.df-platform-web.tls=true
18+
- traefik.http.routers.df-platform-web.tls.certresolver=le
19+
- traefik.http.services.df-platform-web.loadbalancer.server.port=5173
20+
# HTTP → HTTPS redirect (re-adding to ensure full functionality)
21+
- traefik.http.routers.df-platform-web-http.rule=Host(`${APP_HOST}`)
22+
- traefik.http.routers.df-platform-web-http.entrypoints=web
23+
- traefik.http.routers.df-platform-web-http.middlewares=redirect-to-https@file
24+
- traefik.http.routers.df-platform-web-http.service=df-platform-web
25+
26+
server:
27+
command: npm run dev
28+
volumes:
29+
- ./server:/app
30+
- /app/node_modules
31+
labels:
32+
- traefik.enable=true
33+
- traefik.docker.network=traefik
34+
- traefik.http.routers.df-platform-api.rule=Host(`${APP_HOST}`) && PathPrefix(`/api`)
35+
- traefik.http.routers.df-platform-api.entrypoints=websecure
36+
- traefik.http.routers.df-platform-api.tls=true
37+
- traefik.http.routers.df-platform-api.tls.certresolver=le
38+
- traefik.http.services.df-platform-api.loadbalancer.server.port=3000
39+
# HTTP → HTTPS redirect
40+
- traefik.http.routers.df-platform-api-http.rule=Host(`${APP_HOST}`) && PathPrefix(`/api`)
41+
- traefik.http.routers.df-platform-api-http.entrypoints=web
42+
- traefik.http.routers.df-platform-api-http.middlewares=redirect-to-https@file
43+
- traefik.http.routers.df-platform-api-http.service=df-platform-api

platform/docker-compose.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
services:
2+
# Frontend static server (Nginx)
3+
frontend:
4+
build:
5+
context: ./frontend
6+
labels:
7+
- "org.pseudolab.project=devfactory-platform"
8+
container_name: devfactory-frontend
9+
restart: unless-stopped
10+
networks:
11+
- traefik
12+
- internal
13+
labels:
14+
- traefik.enable=true
15+
- traefik.docker.network=traefik
16+
# --- Traefik Router (frontend) ---
17+
- traefik.http.routers.df-platform-web.rule=Host(`${APP_HOST}`)
18+
- traefik.http.routers.df-platform-web.entrypoints=websecure
19+
- traefik.http.routers.df-platform-web.tls=true
20+
- traefik.http.routers.df-platform-web.tls.certresolver=le
21+
- traefik.http.services.df-platform-web.loadbalancer.server.port=80
22+
# HTTP → HTTPS redirect
23+
- traefik.http.routers.df-platform-web-http.rule=Host(`${APP_HOST}`)
24+
- traefik.http.routers.df-platform-web-http.entrypoints=web
25+
- traefik.http.routers.df-platform-web-http.middlewares=redirect-to-https@file
26+
- traefik.http.routers.df-platform-web-http.service=df-platform-web
27+
28+
# Backend API server
29+
server:
30+
build:
31+
context: ./server
32+
labels:
33+
- "org.pseudolab.project=devfactory-platform"
34+
container_name: devfactory-api
35+
restart: unless-stopped
36+
environment:
37+
- DATABASE_URL=${DATABASE_URL}
38+
- PORT=3000
39+
networks:
40+
- traefik
41+
- internal
42+
labels:
43+
- traefik.enable=true
44+
- traefik.docker.network=traefik
45+
# --- Traefik Router (backend) ---
46+
- traefik.http.routers.df-platform-api.rule=Host(`${APP_HOST}`) && PathPrefix(`/api`)
47+
- traefik.http.routers.df-platform-api.entrypoints=websecure
48+
- traefik.http.routers.df-platform-api.tls=true
49+
- traefik.http.routers.df-platform-api.tls.certresolver=le
50+
- traefik.http.services.df-platform-api.loadbalancer.server.port=3000
51+
# HTTP → HTTPS redirect
52+
- traefik.http.routers.df-platform-api-http.rule=Host(`${APP_HOST}`) && PathPrefix(`/api`)
53+
- traefik.http.routers.df-platform-api-http.entrypoints=web
54+
- traefik.http.routers.df-platform-api-http.middlewares=redirect-to-https@file
55+
- traefik.http.routers.df-platform-api-http.service=df-platform-api
56+
57+
networks:
58+
traefik:
59+
external: true
60+
internal:
61+
driver: bridge

platform/frontend/Dockerfile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Stage 1: Build stage
2+
FROM node:20-alpine as build-stage
3+
4+
WORKDIR /app
5+
6+
# Copy package files and install dependencies
7+
COPY package*.json ./
8+
RUN npm install
9+
10+
# Copy project files and build
11+
COPY . .
12+
RUN npm run build
13+
14+
# Stage 2: Serve stage
15+
FROM nginx:stable-alpine as production-stage
16+
17+
# Copy built assets from build-stage to nginx
18+
COPY --from=build-stage /app/dist /usr/share/nginx/html
19+
20+
# Expose port 80
21+
EXPOSE 80
22+
23+
CMD ["nginx", "-g", "daemon off;"]

0 commit comments

Comments
 (0)