프로젝트 기본 구성: 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>
이 커밋은 다음에 포함됨:
@@ -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)
|
||||
새 이슈에서 참조
사용자 차단