프로젝트 기본 구성: Next.js + PostgreSQL + Gitea Actions 배포

- Next.js 15 (App Router, TypeScript, Tailwind), pg 커넥션 풀
- /api/health DB 헬스체크, standalone Dockerfile
- Gitea Actions: 빌드 → 컨테이너 교체 → Traefik(jskim.vexplor.com) 라우팅
- 로컬 개발용 SSH DB 터널 스크립트 (scripts/db-tunnel.sh)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
이 커밋은 다음에 포함됨:
kjs
2026-08-12 17:01:55 +09:00
co-authored by Claude Fable 5
커밋 f695b583e4
24개의 변경된 파일과 7365개의 추가작업 그리고 0개의 파일을 삭제
+62
파일 보기
@@ -0,0 +1,62 @@
# Gitea Actions — 빌드 & 배포
#
# 동작:
# 1. main 브랜치 push 시 자동 실행
# 2. 러너가 호스트 docker 데몬으로 이미지 빌드 (레지스트리 불필요)
# 3. 같은 호스트에서 컨테이너 교체 → Traefik이 jskim.vexplor.com HTTPS 라우팅
#
# DATABASE_URL은 서버의 /home/three/jskim/.env (chmod 600)에서 읽는다.
# 저장소에는 어떤 비밀값도 커밋하지 않는다.
name: build-and-deploy
on:
push:
branches:
- main
workflow_dispatch:
env:
IMAGE: harbor.wace.me/dev-pilots/jskim:latest
CONTAINER_NAME: jskim
DOMAIN: jskim.vexplor.com
HOST_ENV_DIR: /home/three/jskim
jobs:
deploy:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: docker CLI 준비
run: command -v docker || (apt-get update -qq && apt-get install -y -qq docker.io)
- name: 이미지 빌드
run: docker build -t "$IMAGE" .
- name: 컨테이너 교체
run: |
# 호스트의 env 파일을 호스트 docker 데몬 경유로 읽는다 (러너 컨테이너에는 미마운트)
DATABASE_URL=$(docker run --rm -v "$HOST_ENV_DIR":/cfg:ro alpine sh -c 'grep "^DATABASE_URL=" /cfg/.env | cut -d= -f2-')
if [ -z "$DATABASE_URL" ]; then echo "호스트 $HOST_ENV_DIR/.env 에 DATABASE_URL 없음"; exit 1; fi
docker rm -f "$CONTAINER_NAME" 2>/dev/null || true
docker run -d \
--name "$CONTAINER_NAME" \
--restart always \
--network web \
-e TZ=Asia/Seoul \
-e DATABASE_URL="$DATABASE_URL" \
--label "traefik.enable=true" \
--label "traefik.docker.network=web" \
--label "traefik.http.routers.jskim.rule=Host(\`$DOMAIN\`)" \
--label "traefik.http.routers.jskim.entrypoints=websecure" \
--label "traefik.http.routers.jskim.tls.certresolver=le" \
--label "traefik.http.services.jskim.loadbalancer.server.port=3000" \
"$IMAGE"
docker network connect pgnet "$CONTAINER_NAME"
- name: 헬스체크
run: |
sleep 10
docker exec "$CONTAINER_NAME" wget -qO- http://localhost:3000/api/health || (docker logs --tail 50 "$CONTAINER_NAME"; exit 1)