Compare commits
2 Commits
967f2aaec7
...
954387a8cf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
954387a8cf | ||
|
|
4419dbd0a6 |
14
Dockerfile
14
Dockerfile
@@ -63,12 +63,13 @@ RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \
|
|||||||
COPY --chown=root:root . .
|
COPY --chown=root:root . .
|
||||||
|
|
||||||
# Build and export Reflex app for production
|
# Build and export Reflex app for production
|
||||||
|
# Note: API_URL will be updated at runtime from environment variable
|
||||||
# Export creates .web directory with frontend static files
|
# Export creates .web directory with frontend static files
|
||||||
# bun is now pre-installed, so reflex export won't try to download it
|
# bun is now pre-installed, so reflex export won't try to download it
|
||||||
RUN python -m reflex export --no-zip
|
RUN python -m reflex export --no-zip
|
||||||
|
|
||||||
# Aggressive cleanup to reduce layer size
|
# Aggressive cleanup to reduce layer size
|
||||||
# NOTE: Keep .web directory - it contains frontend static files needed for --backend-only mode
|
# NOTE: Keep .web directory - it contains frontend static files
|
||||||
RUN set -ex && \
|
RUN set -ex && \
|
||||||
# Remove Python cache
|
# Remove Python cache
|
||||||
find /build -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true && \
|
find /build -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true && \
|
||||||
@@ -128,6 +129,10 @@ COPY --from=builder /root/.local /home/peikarband/.local
|
|||||||
# Copy application code from builder
|
# Copy application code from builder
|
||||||
COPY --from=builder /build /app
|
COPY --from=builder /build /app
|
||||||
|
|
||||||
|
# Copy and set up runtime script
|
||||||
|
COPY --chown=peikarband:peikarband scripts/update-env-json.sh /app/scripts/update-env-json.sh
|
||||||
|
RUN chmod +x /app/scripts/update-env-json.sh
|
||||||
|
|
||||||
# Fix ownership
|
# Fix ownership
|
||||||
RUN chown -R peikarband:peikarband /home/peikarband/.local /app
|
RUN chown -R peikarband:peikarband /home/peikarband/.local /app
|
||||||
|
|
||||||
@@ -159,8 +164,9 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
|||||||
CMD curl -f -s -o /dev/null -w "%{http_code}" http://localhost:8000/ping | grep -q "200" || exit 1
|
CMD curl -f -s -o /dev/null -w "%{http_code}" http://localhost:8000/ping | grep -q "200" || exit 1
|
||||||
|
|
||||||
# Use tini as init system for proper signal handling
|
# Use tini as init system for proper signal handling
|
||||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
# Update .web/env.json from API_URL env var, then run the app
|
||||||
|
ENTRYPOINT ["/usr/bin/tini", "--", "/app/scripts/update-env-json.sh"]
|
||||||
|
|
||||||
# Run application
|
# Run application (both frontend and backend)
|
||||||
CMD ["python", "-m", "reflex", "run", "--env", "prod", "--backend-only"]
|
CMD ["python", "-m", "reflex", "run", "--env", "prod"]
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
{{- if .Values.ingress.enabled -}}
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
# Frontend Ingress (peikarband.ir -> port 3000)
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "peikarband.fullname" . }}
|
name: {{ include "peikarband.fullname" . }}-frontend
|
||||||
labels:
|
labels:
|
||||||
{{- include "peikarband.labels" . | nindent 4 }}
|
{{- include "peikarband.labels" . | nindent 4 }}
|
||||||
{{- with .Values.ingress.annotations }}
|
{{- with .Values.ingress.annotations }}
|
||||||
@@ -35,8 +36,50 @@ spec:
|
|||||||
service:
|
service:
|
||||||
name: {{ include "peikarband.fullname" $ }}
|
name: {{ include "peikarband.fullname" $ }}
|
||||||
port:
|
port:
|
||||||
number: {{ $.Values.service.backend.port }}
|
number: {{ $.Values.service.frontend.port }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.ingress.apiEnabled -}}
|
||||||
|
# Backend API Ingress (api.peikarband.ir -> port 8000)
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "peikarband.fullname" . }}-api
|
||||||
|
labels:
|
||||||
|
{{- include "peikarband.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.ingress.apiAnnotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.apiTls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.apiTls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.apiHosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
pathType: {{ .pathType }}
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "peikarband.fullname" $ }}
|
||||||
|
port:
|
||||||
|
number: {{ $.Values.service.backend.port }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ appSecrets:
|
|||||||
|
|
||||||
# Reflex configuration for production
|
# Reflex configuration for production
|
||||||
reflex:
|
reflex:
|
||||||
apiUrl: "https://peikarband.ir" # Production API URL
|
apiUrl: "https://api.peikarband.ir" # Production API URL (backend)
|
||||||
|
|
||||||
podAnnotations:
|
podAnnotations:
|
||||||
prometheus.io/scrape: "true"
|
prometheus.io/scrape: "true"
|
||||||
@@ -73,6 +73,22 @@ ingress:
|
|||||||
- peikarband.ir
|
- peikarband.ir
|
||||||
- www.peikarband.ir
|
- www.peikarband.ir
|
||||||
|
|
||||||
|
# Backend API Ingress (api.peikarband.ir -> port 8000)
|
||||||
|
apiEnabled: true
|
||||||
|
apiAnnotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: "websecure"
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
apiHosts:
|
||||||
|
- host: api.peikarband.ir
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
apiTls:
|
||||||
|
- secretName: peikarband-api-tls
|
||||||
|
hosts:
|
||||||
|
- api.peikarband.ir
|
||||||
|
|
||||||
postgresql:
|
postgresql:
|
||||||
enabled: false # Using SQLite for now
|
enabled: false # Using SQLite for now
|
||||||
external:
|
external:
|
||||||
|
|||||||
@@ -82,6 +82,15 @@ ingress:
|
|||||||
- peikarband.ir
|
- peikarband.ir
|
||||||
- www.peikarband.ir
|
- www.peikarband.ir
|
||||||
|
|
||||||
|
# Backend API Ingress (api.peikarband.ir -> port 8000)
|
||||||
|
apiEnabled: false # Enable in production values
|
||||||
|
apiAnnotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: "websecure"
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
apiHosts: []
|
||||||
|
apiTls: []
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpu: 1000m
|
cpu: 1000m
|
||||||
|
|||||||
69
scripts/update-env-json.sh
Executable file
69
scripts/update-env-json.sh
Executable file
@@ -0,0 +1,69 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Update .web/env.json with API_URL from environment variable at runtime
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
API_URL="${API_URL:-http://localhost:8000}"
|
||||||
|
|
||||||
|
# Extract protocol, host, and port from API_URL
|
||||||
|
if [[ "$API_URL" =~ ^(https?://)([^:/]+)(:([0-9]+))? ]]; then
|
||||||
|
PROTOCOL="${BASH_REMATCH[1]}"
|
||||||
|
HOST="${BASH_REMATCH[2]}"
|
||||||
|
PORT="${BASH_REMATCH[4]:-8000}"
|
||||||
|
|
||||||
|
# Remove trailing slash
|
||||||
|
API_URL="${API_URL%/}"
|
||||||
|
|
||||||
|
# Update .web/env.json
|
||||||
|
if [ -f "/app/.web/env.json" ]; then
|
||||||
|
# Use Python to properly update JSON
|
||||||
|
python3 <<EOF
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
api_url = os.environ.get('API_URL', 'http://localhost:8000')
|
||||||
|
api_url = api_url.rstrip('/')
|
||||||
|
|
||||||
|
# Determine protocol and host
|
||||||
|
if api_url.startswith('https://'):
|
||||||
|
ws_protocol = 'wss://'
|
||||||
|
http_protocol = 'https://'
|
||||||
|
elif api_url.startswith('http://'):
|
||||||
|
ws_protocol = 'ws://'
|
||||||
|
http_protocol = 'http://'
|
||||||
|
else:
|
||||||
|
ws_protocol = 'ws://'
|
||||||
|
http_protocol = 'http://'
|
||||||
|
api_url = f'http://{api_url}'
|
||||||
|
|
||||||
|
# Remove protocol prefix for host extraction
|
||||||
|
host = api_url.replace('https://', '').replace('http://', '').split('/')[0]
|
||||||
|
|
||||||
|
# Read existing env.json
|
||||||
|
with open('/app/.web/env.json', 'r') as f:
|
||||||
|
env_data = json.load(f)
|
||||||
|
|
||||||
|
# Update URLs
|
||||||
|
env_data['PING'] = f'{http_protocol}{host}/ping'
|
||||||
|
env_data['EVENT'] = f'{ws_protocol}{host}/_event'
|
||||||
|
env_data['UPLOAD'] = f'{http_protocol}{host}/_upload'
|
||||||
|
env_data['AUTH_CODESPACE'] = f'{http_protocol}{host}/auth-codespace'
|
||||||
|
env_data['HEALTH'] = f'{http_protocol}{host}/_health'
|
||||||
|
env_data['ALL_ROUTES'] = f'{http_protocol}{host}/_all_routes'
|
||||||
|
|
||||||
|
# Write back
|
||||||
|
with open('/app/.web/env.json', 'w') as f:
|
||||||
|
json.dump(env_data, f)
|
||||||
|
|
||||||
|
print(f"Updated .web/env.json with API_URL: {api_url}")
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
echo "Warning: /app/.web/env.json not found"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Warning: Invalid API_URL format: $API_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Execute the original command
|
||||||
|
exec "$@"
|
||||||
|
|
||||||
Reference in New Issue
Block a user