#배포 가이드
버전: 0.33.0 최종 업데이트: 2026-03-15 적용 대상: ranvier, ranvier-runtime, ranvier-http 카테고리: Operations
이 가이드는 Ranvier 애플리케이션의 컨테이너화된 배포를 다룹니다 — 빌드 전략, Docker 다단계 빌드, Kubernetes 매니페스트, 리버스 프록시, 환경 설정을 포함합니다.
#1. 빌드 전략
Ranvier 애플리케이션은 프로덕션 환경을 위해 완전한 정적 musl 바이너리로 컴파일됩니다. 이를 통해 OS 수준의 종속성이 제거되고 FROM scratch 런타임 이미지를 사용할 수 있습니다.
| 빌드 모드 | 타겟 | 사용 사례 |
|---|---|---|
| 네이티브 디버그 | 호스트 타겟 | 로컬 반복 개발 |
| 네이티브 릴리스 | 호스트 타겟 | 로컬 통합 테스트 |
| musl 릴리스 | x86_64-unknown-linux-musl |
컨테이너 / 프로덕션 |
# musl 타겟 추가 (Linux)
rustup target add x86_64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-muslWindows/macOS에서는 musl 컴파일을 위해 Docker 빌더 스테이지를 사용하세요 (§2 참조).
#2. Docker 다단계 빌드
# ---- Builder ----
FROM clux/muslrust:stable AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
# 종속성 캐싱: 먼저 더미 바이너리를 빌드
RUN mkdir -p src && echo 'fn main(){}' > src/main.rs
RUN cargo build --release --target x86_64-unknown-linux-musl && \
rm -rf src target/x86_64-unknown-linux-musl/release/deps/my_app*
COPY src ./src
RUN cargo build --release --target x86_64-unknown-linux-musl
# ---- Runtime ----
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/my-app /app
EXPOSE 3000
ENTRYPOINT ["/app"]주요 결정 사항:
| 선택 | 근거 |
|---|---|
clux/muslrust:stable |
전체 Rust + musl 툴체인 |
FROM scratch |
OS 표면적 제로, 최소 용량 |
rustls 전용 |
OpenSSL 종속성 없음 — scratch에서 작동 |
| CA 인증서 복사 | 아웃바운드 HTTPS 연결에 필요 |
#3. Kubernetes 매니페스트
#Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: ranvier-app
spec:
replicas: 2
selector:
matchLabels:
app: ranvier-app
template:
metadata:
labels:
app: ranvier-app
spec:
containers:
- name: app
image: my-registry/ranvier-app:latest
ports:
- containerPort: 3000
env:
- name: RUST_LOG
value: "info"
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: ranvier-secrets
key: jwt-secret
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi#Service
apiVersion: v1
kind: Service
metadata:
name: ranvier-app
spec:
selector:
app: ranvier-app
ports:
- port: 80
targetPort: 3000
type: ClusterIP#HPA (Horizontal Pod Autoscaler)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ranvier-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ranvier-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70#4. 헬스 체크 엔드포인트
use ranvier::prelude::*;
#[transition]
async fn health_check(
_state: (),
_resources: &(),
_bus: &mut Bus,
) -> Outcome<String, String> {
Outcome::Next(r#"{"status":"ok"}"#.to_string())
}
// Axon 설정에 마운트
let health = Axon::simple::<String>("health")
.then(health_check);
Ranvier::http()
.bind("0.0.0.0:3000")
.route("/health", health)
.route("/api/hello", hello_axon)
.run(())
.await?;#5. 리버스 프록시 (Nginx)
Nginx는 정적 프론트엔드 에셋을 제공하고 API 호출을 Ranvier 백엔드로 프록시합니다:
server {
listen 80;
# 정적 SPA
root /usr/share/nginx/html;
location / { try_files $uri $uri/ /index.html; }
# API 프록시 → Ranvier 백엔드
location /api/ {
proxy_pass http://backend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Ranvier::http()는 Ingress Builder이며 웹 서버가 아닙니다. Nginx를 엣지로 사용하면 Ranvier 애플리케이션의 순수 API 레이어 역할이 유지됩니다.
#6. Compose 토폴로지
┌─────────────────┐
│ Browser :8080 │
└────────┬────────┘
│
┌──────▼──────┐
│ proxy │ nginx:alpine — :80
└──┬───────┬──┘
│ │
┌────▼───┐ ┌─▼────────┐
│frontend│ │ backend │ Ranvier — :3000
│(static)│ └──────┬────┘
└────────┘ │
┌──────▼──────┐
│ db │ postgres:16-alpine — :5432
└──────────────┘| 설정 | 개발 | 프로덕션 |
|---|---|---|
| DB 포트 노출 | 예 (5432) | 아니오 |
| RUST_LOG | debug |
info |
| 재시작 정책 | 없음 | unless-stopped |
| JWT_SECRET | 테스트 값 | env/secret |
#7. 환경 변수
| 변수 | 필수 | 기본값 | 설명 |
|---|---|---|---|
JWT_SECRET |
예 (인증 사용 시) | — | JWT 서명 시크릿 (절대 하드코딩 금지) |
DATABASE_URL |
예 (영속성 사용 시) | — | postgres://user:pass@host:5432/db |
RUST_LOG |
아니오 | info |
로그 필터 (debug, info, warn, error) |
OTEL_EXPORTER_OTLP_ENDPOINT |
아니오 | — | OTLP 수집기 엔드포인트 |
PORT |
아니오 | 3000 |
HTTP 바인딩 포트 |
- 항상
.env.example을 기준 소스로 사용하세요 .env를 절대 버전 관리에 커밋하지 마세요- 프로덕션 환경에서는 Kubernetes Secrets 또는 vault를 사용하세요
#8. 릴리스 빌드 최적화
# Cargo.toml
[profile.release]
lto = true
strip = true
codegen-units = 1
opt-level = 3cargo build --release --target x86_64-unknown-linux-musl#9. CI 파이프라인 (musl 빌드)
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with: { targets: x86_64-unknown-linux-musl }
- uses: Swatinem/rust-cache@v2
- run: cargo check --workspace
- run: cargo test --workspace
- run: cargo clippy --workspace -- -D warnings
- run: cargo build --release --target x86_64-unknown-linux-musl#10. 배포 체크리스트
#필수 항목
-
--release프로파일에 LTO, strip, codegen-units=1 설정 - Docker 다단계 빌드 (builder → scratch)
- 헬스 체크 엔드포인트 (
/health) 설정 - 환경 변수 문서화 및 주입
- 시크릿을 버전 관리에 커밋하지 않음
- 프로덕션 환경에
RUST_LOG=info설정
#권장 항목
- Kubernetes readiness/liveness 프로브 설정
- CPU 기반 자동 스케일링을 위한 HPA
- 관측성을 위한 OpenTelemetry 익스포터
- 정적 에셋 + API 라우팅을 위한 Nginx 리버스 프록시
- musl 빌드 검증을 포함한 CI 파이프라인
#관련 문서
- 프로덕션 준비 체크리스트 — 배포 전 체크리스트
- 성능 튜닝 — 프로파일링, 커넥션 풀, 비동기 최적화
- 보안 강화 — 인증, CORS, 에러 마스킹
- OTel 운영 플레이북 — 관측성 설정