- Dockerfile: Expo web export → nginx multi-stage 빌드 - nginx.conf: SPA fallback, gzip, health endpoint - K8s manifests: namespace, deployment (2 replicas), service, ingress - Traefik IngressRoute (선택적) 포함 - Gitea Actions workflow: push 시 빌드→Gitea Registry push→rollout restart - DEPLOY.md: 초기 설정 가이드 (kubeconfig, secrets, DNS) Domain: insurance.junggomoa.com Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
node_modules
|
||||||
|
.expo
|
||||||
|
.expo-shared
|
||||||
|
dist
|
||||||
|
web-build
|
||||||
|
.git
|
||||||
|
.gitea
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
|
.env*
|
||||||
|
README.md
|
||||||
|
DEPLOY.md
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
name: Build & Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: git.junggomoa.com
|
||||||
|
IMAGE_NAME: chpark/insurance
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set short SHA
|
||||||
|
run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Log in to Gitea Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.SHORT_SHA }}
|
||||||
|
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
|
||||||
|
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
|
||||||
|
|
||||||
|
- name: Set up kubectl
|
||||||
|
uses: azure/setup-kubectl@v4
|
||||||
|
with:
|
||||||
|
version: "v1.29.0"
|
||||||
|
|
||||||
|
- name: Configure kubeconfig
|
||||||
|
run: |
|
||||||
|
mkdir -p $HOME/.kube
|
||||||
|
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config
|
||||||
|
chmod 600 $HOME/.kube/config
|
||||||
|
|
||||||
|
- name: Ensure namespace & registry secret
|
||||||
|
run: |
|
||||||
|
kubectl apply -f deploy/k8s/namespace.yaml
|
||||||
|
kubectl -n insurance create secret docker-registry gitea-registry \
|
||||||
|
--docker-server=${{ env.REGISTRY }} \
|
||||||
|
--docker-username=${{ secrets.REGISTRY_USER }} \
|
||||||
|
--docker-password=${{ secrets.REGISTRY_TOKEN }} \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
- name: Apply manifests
|
||||||
|
run: |
|
||||||
|
kubectl apply -f deploy/k8s/deployment.yaml
|
||||||
|
kubectl apply -f deploy/k8s/service.yaml
|
||||||
|
if [ "${{ secrets.INGRESS_MODE }}" = "ingressroute" ]; then
|
||||||
|
kubectl apply -f deploy/k8s/ingressroute-traefik.yaml
|
||||||
|
else
|
||||||
|
kubectl apply -f deploy/k8s/ingress.yaml
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Update deployment image & restart
|
||||||
|
run: |
|
||||||
|
kubectl -n insurance set image deployment/insurance-web \
|
||||||
|
web=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.SHORT_SHA }}
|
||||||
|
kubectl -n insurance rollout status deployment/insurance-web --timeout=180s
|
||||||
|
|
||||||
|
- name: Show deployment info
|
||||||
|
run: |
|
||||||
|
kubectl -n insurance get deployment,svc,ingress
|
||||||
|
echo ""
|
||||||
|
echo "🚀 Deployed: https://insurance.junggomoa.com"
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
# 🚀 배포 가이드
|
||||||
|
|
||||||
|
## 자동 배포 파이프라인
|
||||||
|
|
||||||
|
```
|
||||||
|
git push → Gitea Actions → Docker 빌드 → Container Registry → Kubernetes rollout
|
||||||
|
↓
|
||||||
|
insurance.junggomoa.com
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 한 번만 해야 하는 초기 설정
|
||||||
|
|
||||||
|
### 1단계 — Gitea 측 설정 (웹 UI)
|
||||||
|
|
||||||
|
#### ① Gitea Actions Runner 활성화
|
||||||
|
1. [https://git.junggomoa.com/chpark/insurance](https://git.junggomoa.com/chpark/insurance) → **Settings**
|
||||||
|
2. 좌측 **Actions** 메뉴 → **Enable Actions** 체크
|
||||||
|
3. 조직/인스턴스 관리자가 **Runner**를 하나 등록해둬야 합니다
|
||||||
|
- Runner 없다면 관리자에게 요청
|
||||||
|
- 또는 Kubernetes에 `act-runner` Helm 차트로 직접 설치 (아래 스크립트 참고)
|
||||||
|
|
||||||
|
#### ② Container Registry 접근 토큰 발급
|
||||||
|
1. Gitea → 우측 상단 프로필 → **Settings** → **Applications**
|
||||||
|
2. **Generate New Token** → 권한 `write:package`, `read:package` 체크
|
||||||
|
3. 발급된 토큰 복사 (한 번만 보임)
|
||||||
|
|
||||||
|
#### ③ Repository Secrets 등록
|
||||||
|
Repo → **Settings** → **Secrets and Variables** → **Actions** → **Add Secret**:
|
||||||
|
|
||||||
|
| Name | Value | 설명 |
|
||||||
|
|---|---|---|
|
||||||
|
| `REGISTRY_USER` | `chpark` | Gitea 사용자명 |
|
||||||
|
| `REGISTRY_TOKEN` | (위에서 발급한 토큰) | Container Registry 인증 |
|
||||||
|
| `KUBE_CONFIG` | (아래 2단계에서 생성) | base64 인코딩된 kubeconfig |
|
||||||
|
| `INGRESS_MODE` | `ingress` 또는 `ingressroute` | Traefik 설치 방식 (아래 확인) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2단계 — Kubernetes 측 설정 (서버 SSH 1회)
|
||||||
|
|
||||||
|
SSH 접속:
|
||||||
|
```bash
|
||||||
|
ssh chpark@183.99.177.40
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ① Traefik 설치 방식 확인
|
||||||
|
```bash
|
||||||
|
kubectl api-resources | grep -i traefik
|
||||||
|
```
|
||||||
|
- 결과에 `ingressroutes.traefik.io` 나오면 → `INGRESS_MODE=ingressroute`
|
||||||
|
- 아무것도 안 나오면 → `INGRESS_MODE=ingress` (표준 Ingress 사용)
|
||||||
|
|
||||||
|
#### ② CI용 kubeconfig 생성 (서비스 어카운트 방식, 권장)
|
||||||
|
```bash
|
||||||
|
# 네임스페이스·서비스어카운트 선생성
|
||||||
|
kubectl create namespace insurance 2>/dev/null || true
|
||||||
|
kubectl -n insurance create serviceaccount gitea-deployer
|
||||||
|
kubectl create clusterrolebinding gitea-deployer \
|
||||||
|
--clusterrole=cluster-admin \
|
||||||
|
--serviceaccount=insurance:gitea-deployer
|
||||||
|
|
||||||
|
# 토큰 생성 (24시간 기본, 필요 시 --duration=8760h 로 1년)
|
||||||
|
TOKEN=$(kubectl -n insurance create token gitea-deployer --duration=8760h)
|
||||||
|
|
||||||
|
# 현재 API 서버 주소
|
||||||
|
SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
|
||||||
|
CA=$(kubectl -n insurance get secret \
|
||||||
|
$(kubectl -n insurance get sa gitea-deployer -o jsonpath='{.secrets[0].name}' 2>/dev/null || echo "") \
|
||||||
|
-o jsonpath='{.data.ca\.crt}' 2>/dev/null || \
|
||||||
|
kubectl config view --minify --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
|
||||||
|
|
||||||
|
# kubeconfig 생성
|
||||||
|
cat <<EOF > /tmp/gitea-kubeconfig
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Config
|
||||||
|
clusters:
|
||||||
|
- cluster:
|
||||||
|
server: ${SERVER}
|
||||||
|
certificate-authority-data: ${CA}
|
||||||
|
name: cluster
|
||||||
|
contexts:
|
||||||
|
- context:
|
||||||
|
cluster: cluster
|
||||||
|
user: gitea-deployer
|
||||||
|
namespace: insurance
|
||||||
|
name: default
|
||||||
|
current-context: default
|
||||||
|
users:
|
||||||
|
- name: gitea-deployer
|
||||||
|
user:
|
||||||
|
token: ${TOKEN}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# base64 인코딩 → Gitea secret에 넣을 값
|
||||||
|
base64 -w0 /tmp/gitea-kubeconfig
|
||||||
|
```
|
||||||
|
출력된 긴 문자열을 복사해서 Gitea의 `KUBE_CONFIG` secret에 붙여넣으세요.
|
||||||
|
|
||||||
|
#### ③ DNS 확인
|
||||||
|
`insurance.junggomoa.com` 이 k8s 클러스터의 Traefik LoadBalancer IP 로 등록돼 있어야 합니다.
|
||||||
|
```bash
|
||||||
|
dig insurance.junggomoa.com +short
|
||||||
|
```
|
||||||
|
IP가 안 나오거나 잘못됐다면 DNS 관리자에게 추가 요청:
|
||||||
|
- `insurance.junggomoa.com A <클러스터 LB IP>`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ 이후부터 — 자동 배포
|
||||||
|
|
||||||
|
코드 수정 후:
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "수정 내용"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
Gitea Actions 탭에서 진행 상황 확인:
|
||||||
|
- [https://git.junggomoa.com/chpark/insurance/actions](https://git.junggomoa.com/chpark/insurance/actions)
|
||||||
|
|
||||||
|
**약 3~5분 후** `https://insurance.junggomoa.com` 에 새 버전 반영됩니다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 수동 1회 배포 (CI 세팅 전 테스트용)
|
||||||
|
|
||||||
|
SSH 접속 후:
|
||||||
|
```bash
|
||||||
|
# 코드 받기
|
||||||
|
git clone https://git.junggomoa.com/chpark/insurance.git
|
||||||
|
cd insurance
|
||||||
|
|
||||||
|
# 도커 이미지 빌드
|
||||||
|
docker build -t git.junggomoa.com/chpark/insurance:latest .
|
||||||
|
|
||||||
|
# 레지스트리 로그인 & push
|
||||||
|
docker login git.junggomoa.com -u chpark -p <토큰>
|
||||||
|
docker push git.junggomoa.com/chpark/insurance:latest
|
||||||
|
|
||||||
|
# K8s 시크릿 & 매니페스트 적용
|
||||||
|
kubectl apply -f deploy/k8s/namespace.yaml
|
||||||
|
kubectl -n insurance create secret docker-registry gitea-registry \
|
||||||
|
--docker-server=git.junggomoa.com \
|
||||||
|
--docker-username=chpark \
|
||||||
|
--docker-password=<토큰>
|
||||||
|
kubectl apply -f deploy/k8s/deployment.yaml
|
||||||
|
kubectl apply -f deploy/k8s/service.yaml
|
||||||
|
kubectl apply -f deploy/k8s/ingress.yaml # 또는 ingressroute-traefik.yaml
|
||||||
|
|
||||||
|
# 상태 확인
|
||||||
|
kubectl -n insurance get all
|
||||||
|
kubectl -n insurance get ingress
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 트러블슈팅
|
||||||
|
|
||||||
|
| 증상 | 원인 | 해결 |
|
||||||
|
|---|---|---|
|
||||||
|
| `ImagePullBackOff` | Registry 인증 실패 | `gitea-registry` secret 재생성 |
|
||||||
|
| `404 page not found` (Traefik) | Ingress host 불일치 | `insurance.junggomoa.com` 철자 확인 |
|
||||||
|
| TLS 인증서 없음 | cert-manager 미설정 | 관리자에게 와일드카드 인증서 요청 또는 cert-manager 설치 |
|
||||||
|
| Actions 실패: `no runner` | Runner 미등록 | 조직에 act-runner 등록 필요 |
|
||||||
|
|
||||||
|
로그 확인:
|
||||||
|
```bash
|
||||||
|
kubectl -n insurance logs -l app.kubernetes.io/name=insurance-web --tail=100
|
||||||
|
kubectl -n insurance describe deployment insurance-web
|
||||||
|
kubectl -n insurance describe ingress insurance-web
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 배포 관련 파일
|
||||||
|
|
||||||
|
```
|
||||||
|
Dockerfile # Multi-stage 빌드 (Expo → nginx)
|
||||||
|
.dockerignore
|
||||||
|
.gitea/workflows/deploy.yml # CI/CD 파이프라인
|
||||||
|
deploy/
|
||||||
|
├── nginx.conf # SPA fallback + gzip + health
|
||||||
|
└── k8s/
|
||||||
|
├── namespace.yaml
|
||||||
|
├── deployment.yaml # 2 replicas, rolling update
|
||||||
|
├── service.yaml # ClusterIP :80
|
||||||
|
├── ingress.yaml # 표준 Ingress (Traefik ingressClass)
|
||||||
|
└── ingressroute-traefik.yaml # Traefik CRD 버전 (선택)
|
||||||
|
```
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
FROM node:20-alpine AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --legacy-peer-deps --no-audit --no-fund
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npx expo export --platform web
|
||||||
|
|
||||||
|
FROM nginx:1.27-alpine AS runner
|
||||||
|
RUN rm -rf /usr/share/nginx/html/*
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
COPY deploy/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
|
||||||
|
CMD wget -q --spider http://localhost:80/ || exit 1
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: insurance-web
|
||||||
|
namespace: insurance
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: insurance-web
|
||||||
|
app.kubernetes.io/component: frontend
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
revisionHistoryLimit: 3
|
||||||
|
strategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 1
|
||||||
|
maxUnavailable: 0
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: insurance-web
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: insurance-web
|
||||||
|
annotations:
|
||||||
|
kubectl.kubernetes.io/restartedAt: "placeholder-will-be-patched-by-ci"
|
||||||
|
spec:
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: gitea-registry
|
||||||
|
containers:
|
||||||
|
- name: web
|
||||||
|
image: git.junggomoa.com/chpark/insurance:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
protocol: TCP
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 3
|
||||||
|
periodSeconds: 5
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 20
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 300m
|
||||||
|
memory: 256Mi
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
runAsNonRoot: false
|
||||||
|
capabilities:
|
||||||
|
drop: ["ALL"]
|
||||||
|
add: ["CHOWN", "SETGID", "SETUID", "NET_BIND_SERVICE"]
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: insurance-web
|
||||||
|
namespace: insurance
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- insurance.junggomoa.com
|
||||||
|
secretName: insurance-tls
|
||||||
|
rules:
|
||||||
|
- host: insurance.junggomoa.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: insurance-web
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: insurance-web
|
||||||
|
namespace: insurance
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: Host(`insurance.junggomoa.com`)
|
||||||
|
kind: Rule
|
||||||
|
services:
|
||||||
|
- name: insurance-web
|
||||||
|
port: 80
|
||||||
|
tls:
|
||||||
|
secretName: insurance-tls
|
||||||
|
---
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: insurance-web-http
|
||||||
|
namespace: insurance
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
routes:
|
||||||
|
- match: Host(`insurance.junggomoa.com`)
|
||||||
|
kind: Rule
|
||||||
|
middlewares:
|
||||||
|
- name: insurance-redirect-https
|
||||||
|
services:
|
||||||
|
- name: insurance-web
|
||||||
|
port: 80
|
||||||
|
---
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: insurance-redirect-https
|
||||||
|
namespace: insurance
|
||||||
|
spec:
|
||||||
|
redirectScheme:
|
||||||
|
scheme: https
|
||||||
|
permanent: true
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: insurance
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: insurance
|
||||||
|
app.kubernetes.io/managed-by: gitea-actions
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: insurance-web
|
||||||
|
namespace: insurance
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: insurance-web
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: insurance-web
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types
|
||||||
|
text/plain
|
||||||
|
text/css
|
||||||
|
text/javascript
|
||||||
|
text/xml
|
||||||
|
application/json
|
||||||
|
application/javascript
|
||||||
|
application/xml+rss
|
||||||
|
application/atom+xml
|
||||||
|
image/svg+xml;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /index.html {
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /health {
|
||||||
|
access_log off;
|
||||||
|
return 200 "ok\n";
|
||||||
|
add_header Content-Type text/plain;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user