목표
온프레미스(H200) 서버에 Next.js · FastAPI · PostgreSQL · Redis · Nginx를 Docker Compose로 올리고, GitHub Actions로 push 한 번에 배포되는 환경을 만든다.
기술 스택
| 레이어 | 기술 | 비고 |
|---|---|---|
| OS | Ubuntu Server 22.04 LTS | NVIDIA Driver |
| Frontend | Next.js 14 (standalone) | Node 18-alpine |
| Backend | FastAPI · Python 3.11 | Gunicorn + Uvicorn |
| Database | PostgreSQL (pgvector) | AsyncPG 드라이버 |
| Cache | Redis 7-alpine | - |
| Gateway | Nginx (alpine) | Reverse Proxy |
| CI/CD | GitHub Actions | Self-hosted Runner / SSH |
포트 은폐 — 단일 진입점
- DB(5432) · Redis(6379) · API(8000) · Front(3000)는 Host 포트를 절대 바인딩하지 않는다
- 오직 Nginx만 80 · 443을 외부에 노출 — 모든 트래픽의 단일 진입점
- 컨테이너 간 통신은 localhost가 아닌 Docker 서비스명(postgres, redis, fastapi)으로
- DATABASE_URL은 .env 의존을 빼고 compose environment에 주입 — postgresql+asyncpg://user:pass@postgres:5432/db
컨테이너 포트 매핑
| 서비스 | 매핑 | 노출 범위 |
|---|---|---|
| Nginx | 80:80 · 443:443 | 공개 진입점 |
| pgAdmin | 8097:80 | 관리 전용 |
| Postgres | 127.0.0.1:<port>:5432 | 로컬 SSH 터널만 |
| Redis | (Host 포트 없음) | 내부 네트워크만 |
| FastAPI | (Host 포트 없음) | 내부 네트워크만 |
| Frontend | (Host 포트 없음) | 내부 네트워크만 |
기동 순서 제어 (Crash Loop 방지)
FastAPI가 DB보다 먼저 떠서 죽는 문제를 entrypoint로 해결한다 — 마이그레이션(alembic) 성공 후 앱을 띄우고, depends_on: condition: service_healthy 로 DB·Redis healthcheck 통과 후에만 시작한다.
entrypoint: ["sh", "-c", "python -m alembic upgrade head && exec gunicorn ..."]
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthyNginx 도메인 분기 & 보안 마감
- server_name 으로 api / web 트래픽을 각 내부 컨테이너로 proxy_pass
- GitHub Actions deploy.yml — push 시 self-hosted runner가 서버에서 배포
- SSH Key·서버 IP는 GitHub Secrets로 암호화 (.env는 절대 커밋 금지)
- docker compose up -d --build --force-recreate 로 레거시 메타데이터 충돌 방지
- Certbot(Let's Encrypt)로 HTTPS, 80 → 443 강제 리다이렉트
▍
결과 — git push 한 번으로 전 서비스 갱신, Front·Back·DB·Redis·Nginx 전부 Up 유지. Swagger UI까지 HTTPS 정상 접속.