194 lines
4.3 KiB
Markdown
194 lines
4.3 KiB
Markdown
# Deployment and Operations
|
|
|
|
- Related REQ: N/A
|
|
|
|
## 목표
|
|
PortfolioHub를 Linux 환경에서 안정적으로 배포하고 HTTPS 종단, 프로세스 복구, 기본 점검 경로를 표준화한다.
|
|
|
|
## 사전 조건
|
|
|
|
- public IP를 가진 Linux/Ubuntu 서버
|
|
- 해당 IP를 가리키는 도메인 DNS `A` record
|
|
- 방화벽에서 `80`, `443` 포트 개방
|
|
|
|
## 권장 배포 토폴로지
|
|
- App: `uvicorn app.main:app`
|
|
- Reverse proxy/TLS: Caddy
|
|
- Process manager: systemd
|
|
- 선택: Docker Compose + Caddy sidecar
|
|
|
|
## Linux Direct Run 기준
|
|
1. Python 가상환경 생성 후 패키지를 설치한다.
|
|
2. 환경 변수 또는 `.env`를 구성한다.
|
|
3. `uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 2`를 실행한다.
|
|
4. `GET /health`를 확인한다.
|
|
|
|
## Caddy 설치와 구성
|
|
|
|
Ubuntu/Debian 설치 예시:
|
|
|
|
```bash
|
|
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
|
|
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
|
|
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
|
|
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
|
|
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
|
|
sudo apt update
|
|
sudo apt install caddy
|
|
```
|
|
|
|
설치 검증:
|
|
|
|
```bash
|
|
caddy version
|
|
```
|
|
|
|
기본 Caddyfile:
|
|
|
|
```text
|
|
your-domain.com {
|
|
reverse_proxy localhost:8000
|
|
}
|
|
```
|
|
|
|
동작 기준:
|
|
|
|
- TLS 인증서 자동 발급/갱신
|
|
- `80`에서 `443`으로 HTTP redirect
|
|
- 외부 요청을 내부 `uvicorn` 프로세스(`127.0.0.1:8000`)로 전달
|
|
|
|
적용 후 reload:
|
|
|
|
```bash
|
|
sudo systemctl reload caddy
|
|
```
|
|
|
|
## systemd 운영 기준
|
|
- 서비스 계정 권한 최소화
|
|
- `Restart=on-failure`
|
|
- 로그 수집 경로(journalctl 또는 외부 수집기) 확보
|
|
|
|
예시 unit 파일:
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=PortfolioHub API
|
|
After=network.target
|
|
|
|
[Service]
|
|
User=www-data
|
|
WorkingDirectory=/opt/portfoliohub
|
|
EnvironmentFile=/opt/portfoliohub/.env
|
|
ExecStart=/opt/portfoliohub/.venv/bin/uvicorn app.main:app \
|
|
--host 127.0.0.1 --port 8000 --workers 2
|
|
Restart=on-failure
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
등록/기동:
|
|
|
|
```bash
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable portfoliohub
|
|
sudo systemctl start portfoliohub
|
|
```
|
|
|
|
## HTTPS/Caddy 운영 기준
|
|
- 도메인 DNS가 서버 IP를 가리켜야 한다.
|
|
- 포트 `80/443`을 개방한다.
|
|
- Caddyfile에서 앱을 `reverse_proxy`로 연결한다.
|
|
- 브라우저 기반 frontend가 있으면 `PORTFOLIOHUB_ALLOWED_ORIGINS`에 정확한 HTTPS origin을 지정한다.
|
|
|
|
예시:
|
|
|
|
```bash
|
|
PORTFOLIOHUB_ALLOWED_ORIGINS=https://app.example.com,https://www.example.com
|
|
```
|
|
|
|
## Docker Compose 운영 기준
|
|
- 앱 컨테이너는 내부 포트만 expose하고 외부 종단은 Caddy가 담당한다.
|
|
- `caddy_data`, `caddy_config` 볼륨을 유지해 인증서 상태를 보존한다.
|
|
- 배포 후 `docker compose ps`, `curl /health`로 기본 상태를 확인한다.
|
|
|
|
예시 compose:
|
|
|
|
```yaml
|
|
services:
|
|
app:
|
|
build: .
|
|
expose:
|
|
- "8000"
|
|
environment:
|
|
- PORTFOLIOHUB_ALLOWED_ORIGINS=https://your-domain.com
|
|
restart: unless-stopped
|
|
|
|
caddy:
|
|
image: caddy:2-alpine
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
- caddy_data:/data
|
|
- caddy_config:/config
|
|
depends_on:
|
|
- app
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
caddy_data:
|
|
caddy_config:
|
|
```
|
|
|
|
compose 네트워크 안에서는 `reverse_proxy app:8000`을 사용한다.
|
|
|
|
기동:
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
## 방화벽 설정
|
|
|
|
UFW:
|
|
|
|
```bash
|
|
sudo ufw allow 80/tcp
|
|
sudo ufw allow 443/tcp
|
|
sudo ufw reload
|
|
```
|
|
|
|
firewalld:
|
|
|
|
```bash
|
|
sudo firewall-cmd --permanent --add-service=http
|
|
sudo firewall-cmd --permanent --add-service=https
|
|
sudo firewall-cmd --reload
|
|
```
|
|
|
|
## 배포 검증
|
|
|
|
HTTPS health check:
|
|
|
|
```bash
|
|
curl https://your-domain.com/health
|
|
```
|
|
|
|
운영 상태 확인:
|
|
|
|
```bash
|
|
sudo systemctl status caddy
|
|
sudo journalctl -u caddy -f
|
|
```
|
|
|
|
## Validation Notes
|
|
- HTTPS 엔드포인트에서 `/health`, `/docs` 접근이 가능해야 한다.
|
|
- DB 사용 배포에서는 마이그레이션 적용 후 앱을 기동한다.
|
|
- CORS 오리진 설정과 실제 프론트엔드 도메인이 일치해야 한다.
|
|
|
|
## Open Implementation Points
|
|
- blue/green 또는 rolling update 같은 무중단 배포 전략 도입 여부를 확정한다.
|
|
- Loki/metrics 통합 운영 절차를 별도 런북으로 분리할지 결정한다.
|