Update health check endpoints and refine TypeScript configuration
- Changed health check endpoint from `/api/health` to `/_health` in Dockerfile and docker-compose.yml for consistency. - Removed the now obsolete health check route file from the API. - Updated TypeScript configuration to exclude the `.next` directory, improving build performance and clarity. - Enhanced documentation in proxy.ts to reflect the updated health check endpoint.
This commit is contained in:
parent
2266167467
commit
3d56f2895f
@ -98,7 +98,7 @@ ENV NODE_ENV=production \
|
||||
|
||||
# Health check for container orchestration
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
||||
CMD node -e "fetch('http://localhost:3000/api/health').then(r=>r.ok||process.exit(1)).catch(()=>process.exit(1))"
|
||||
CMD node -e "fetch('http://localhost:3000/_health').then(r=>r.ok||process.exit(1)).catch(()=>process.exit(1))"
|
||||
|
||||
ENTRYPOINT ["dumb-init", "--"]
|
||||
CMD ["node", "apps/portal/server.js"]
|
||||
|
||||
@ -84,10 +84,10 @@ export const config = {
|
||||
* - _next/static (static files)
|
||||
* - _next/image (image optimization files)
|
||||
* - favicon.ico, sitemap.xml, robots.txt (metadata files)
|
||||
* - api/health (health check endpoint)
|
||||
* - _health (health check endpoint)
|
||||
*/
|
||||
{
|
||||
source: "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|api/health).*)",
|
||||
source: "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|_health).*)",
|
||||
missing: [
|
||||
{ type: "header", key: "next-router-prefetch" },
|
||||
{ type: "header", key: "purpose", value: "prefetch" },
|
||||
|
||||
@ -9,6 +9,6 @@
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules", ".next"]
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ docker images | grep portal
|
||||
2. Name: `customer-portal`
|
||||
3. Paste contents of `docker-compose.yml`
|
||||
4. Scroll down to **Environment Variables**
|
||||
5. Copy variables from `stack.env.example` and fill in your production values
|
||||
5. Copy variables from `env.example` and fill in your production values
|
||||
|
||||
### 3. Generate Secrets
|
||||
|
||||
@ -65,11 +65,11 @@ This setup uses `network_mode: bridge` with Docker `links` to avoid the iptables
|
||||
|
||||
### Service URLs (internal)
|
||||
|
||||
| Service | Internal URL |
|
||||
|----------|-------------------------|
|
||||
| Backend | http://backend:4000 |
|
||||
| Service | Internal URL |
|
||||
| -------- | -------------------------- |
|
||||
| Backend | http://backend:4000 |
|
||||
| Database | postgresql://database:5432 |
|
||||
| Redis | redis://cache:6379 |
|
||||
| Redis | redis://cache:6379 |
|
||||
|
||||
### Nginx/Plesk Proxy
|
||||
|
||||
@ -83,6 +83,7 @@ Configure your domain to proxy to:
|
||||
## Updating the Stack
|
||||
|
||||
1. Load new images:
|
||||
|
||||
```bash
|
||||
docker load < portal-frontend-latest.tar
|
||||
docker load < portal-backend-latest.tar
|
||||
|
||||
@ -25,7 +25,13 @@ services:
|
||||
links:
|
||||
- backend
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "fetch('http://localhost:3000/api/health').then(r=>r.ok||process.exit(1)).catch(()=>process.exit(1))"]
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"node",
|
||||
"-e",
|
||||
"fetch('http://localhost:3000/_health').then(r=>r.ok||process.exit(1)).catch(()=>process.exit(1))",
|
||||
]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
start_period: 40s
|
||||
@ -46,36 +52,40 @@ services:
|
||||
- APP_BASE_URL=${APP_BASE_URL}
|
||||
- BFF_PORT=4000
|
||||
- PORT=4000
|
||||
|
||||
|
||||
# Database - use "database" as host (via links)
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER:-portal}:${POSTGRES_PASSWORD}@database:5432/${POSTGRES_DB:-portal_prod}?schema=public
|
||||
|
||||
|
||||
# Redis - use "cache" as host (via links)
|
||||
- REDIS_URL=redis://cache:6379/0
|
||||
|
||||
|
||||
# Security
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
- JWT_EXPIRES_IN=${JWT_EXPIRES_IN:-7d}
|
||||
- JWT_SECRET_PREVIOUS=${JWT_SECRET_PREVIOUS}
|
||||
- JWT_ISSUER=${JWT_ISSUER}
|
||||
- JWT_AUDIENCE=${JWT_AUDIENCE}
|
||||
- BCRYPT_ROUNDS=${BCRYPT_ROUNDS:-12}
|
||||
- CORS_ORIGIN=${CORS_ORIGIN}
|
||||
- TRUST_PROXY=true
|
||||
- CSRF_SECRET_KEY=${CSRF_SECRET_KEY}
|
||||
|
||||
|
||||
# Auth
|
||||
- AUTH_ALLOW_REDIS_TOKEN_FAILOPEN=${AUTH_ALLOW_REDIS_TOKEN_FAILOPEN:-false}
|
||||
- AUTH_REQUIRE_REDIS_FOR_TOKENS=${AUTH_REQUIRE_REDIS_FOR_TOKENS:-false}
|
||||
- AUTH_BLACKLIST_FAIL_CLOSED=${AUTH_BLACKLIST_FAIL_CLOSED:-false}
|
||||
- AUTH_MAINTENANCE_MODE=${AUTH_MAINTENANCE_MODE:-false}
|
||||
|
||||
|
||||
# Rate Limiting
|
||||
- RATE_LIMIT_TTL=${RATE_LIMIT_TTL:-60}
|
||||
- RATE_LIMIT_LIMIT=${RATE_LIMIT_LIMIT:-100}
|
||||
- EXPOSE_VALIDATION_ERRORS=false
|
||||
|
||||
|
||||
# WHMCS
|
||||
- WHMCS_BASE_URL=${WHMCS_BASE_URL}
|
||||
- WHMCS_API_IDENTIFIER=${WHMCS_API_IDENTIFIER}
|
||||
- WHMCS_API_SECRET=${WHMCS_API_SECRET}
|
||||
|
||||
|
||||
# Salesforce
|
||||
- SF_LOGIN_URL=${SF_LOGIN_URL}
|
||||
- SF_CLIENT_ID=${SF_CLIENT_ID}
|
||||
@ -83,25 +93,25 @@ services:
|
||||
- SF_EVENTS_ENABLED=${SF_EVENTS_ENABLED:-true}
|
||||
- SF_PRIVATE_KEY_BASE64=${SF_PRIVATE_KEY_BASE64}
|
||||
- SF_PRIVATE_KEY_PATH=/app/secrets/sf-private.key
|
||||
|
||||
|
||||
# Freebit
|
||||
- FREEBIT_BASE_URL=${FREEBIT_BASE_URL:-https://i1.mvno.net/emptool/api}
|
||||
- FREEBIT_OEM_ID=${FREEBIT_OEM_ID:-PASI}
|
||||
- FREEBIT_OEM_KEY=${FREEBIT_OEM_KEY}
|
||||
|
||||
|
||||
# Email
|
||||
- EMAIL_ENABLED=${EMAIL_ENABLED:-true}
|
||||
- EMAIL_FROM=${EMAIL_FROM:-no-reply@asolutions.jp}
|
||||
- EMAIL_FROM_NAME=${EMAIL_FROM_NAME:-Assist Solutions}
|
||||
- SENDGRID_API_KEY=${SENDGRID_API_KEY}
|
||||
|
||||
|
||||
# Portal
|
||||
- PORTAL_PRICEBOOK_ID=${PORTAL_PRICEBOOK_ID}
|
||||
- PORTAL_PRICEBOOK_NAME=${PORTAL_PRICEBOOK_NAME:-Portal}
|
||||
|
||||
|
||||
# Logging
|
||||
- LOG_LEVEL=${LOG_LEVEL:-info}
|
||||
|
||||
|
||||
# Enable automatic database migrations on startup
|
||||
- RUN_MIGRATIONS=true
|
||||
restart: unless-stopped
|
||||
@ -117,7 +127,13 @@ services:
|
||||
# - Database migration when RUN_MIGRATIONS=true
|
||||
# - Waiting for dependencies (nc checks in entrypoint)
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "fetch('http://localhost:4000/health').then(r=>r.ok||process.exit(1)).catch(()=>process.exit(1))"]
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"node",
|
||||
"-e",
|
||||
"fetch('http://localhost:4000/health').then(r=>r.ok||process.exit(1)).catch(()=>process.exit(1))",
|
||||
]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
start_period: 60s
|
||||
@ -151,7 +167,19 @@ services:
|
||||
cache:
|
||||
image: redis:7-alpine
|
||||
container_name: portal-cache
|
||||
command: ["redis-server", "--save", "60", "1", "--loglevel", "warning", "--maxmemory", "256mb", "--maxmemory-policy", "noeviction"]
|
||||
command:
|
||||
[
|
||||
"redis-server",
|
||||
"--save",
|
||||
"60",
|
||||
"1",
|
||||
"--loglevel",
|
||||
"warning",
|
||||
"--maxmemory",
|
||||
"256mb",
|
||||
"--maxmemory-policy",
|
||||
"noeviction",
|
||||
]
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
restart: unless-stopped
|
||||
|
||||
@ -33,13 +33,17 @@ POSTGRES_PASSWORD=<GENERATE_WITH_openssl_rand_base64_24>
|
||||
# -----------------------------------------------------------------------------
|
||||
# Generate with: openssl rand -base64 32
|
||||
JWT_SECRET=<GENERATE_WITH_openssl_rand_base64_32>
|
||||
JWT_SECRET_PREVIOUS=
|
||||
JWT_EXPIRES_IN=7d
|
||||
JWT_ISSUER=customer-portal
|
||||
JWT_AUDIENCE=portal
|
||||
BCRYPT_ROUNDS=12
|
||||
CSRF_SECRET_KEY=<GENERATE_WITH_openssl_rand_base64_32>
|
||||
|
||||
# Auth Settings
|
||||
AUTH_ALLOW_REDIS_TOKEN_FAILOPEN=false
|
||||
AUTH_REQUIRE_REDIS_FOR_TOKENS=false
|
||||
AUTH_BLACKLIST_FAIL_CLOSED=false
|
||||
AUTH_MAINTENANCE_MODE=false
|
||||
|
||||
# Rate Limiting
|
||||
|
||||
@ -34,6 +34,8 @@ echo ""
|
||||
# Look for image files
|
||||
FRONTEND_TAR="${IMAGES_DIR}/portal-frontend-${TAG}.tar"
|
||||
BACKEND_TAR="${IMAGES_DIR}/portal-backend-${TAG}.tar"
|
||||
FRONTEND_TARGZ="${IMAGES_DIR}/portal-frontend-${TAG}.tar.gz"
|
||||
BACKEND_TARGZ="${IMAGES_DIR}/portal-backend-${TAG}.tar.gz"
|
||||
|
||||
# Also check alternative naming
|
||||
if [[ ! -f "$FRONTEND_TAR" ]]; then
|
||||
@ -43,20 +45,33 @@ if [[ ! -f "$BACKEND_TAR" ]]; then
|
||||
BACKEND_TAR="${IMAGES_DIR}/portal-backend.${TAG}.tar"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$FRONTEND_TARGZ" ]]; then
|
||||
FRONTEND_TARGZ="${IMAGES_DIR}/portal-frontend.${TAG}.tar.gz"
|
||||
fi
|
||||
if [[ ! -f "$BACKEND_TARGZ" ]]; then
|
||||
BACKEND_TARGZ="${IMAGES_DIR}/portal-backend.${TAG}.tar.gz"
|
||||
fi
|
||||
|
||||
# Load frontend
|
||||
if [[ -f "$FRONTEND_TAR" ]]; then
|
||||
if [[ -f "$FRONTEND_TARGZ" ]]; then
|
||||
log "Loading frontend image from: $FRONTEND_TARGZ"
|
||||
gunzip -c "$FRONTEND_TARGZ" | docker load
|
||||
elif [[ -f "$FRONTEND_TAR" ]]; then
|
||||
log "Loading frontend image from: $FRONTEND_TAR"
|
||||
docker load -i "$FRONTEND_TAR"
|
||||
else
|
||||
warn "Frontend tarball not found: $FRONTEND_TAR"
|
||||
warn "Frontend tarball not found: $FRONTEND_TAR or $FRONTEND_TARGZ"
|
||||
fi
|
||||
|
||||
# Load backend
|
||||
if [[ -f "$BACKEND_TAR" ]]; then
|
||||
if [[ -f "$BACKEND_TARGZ" ]]; then
|
||||
log "Loading backend image from: $BACKEND_TARGZ"
|
||||
gunzip -c "$BACKEND_TARGZ" | docker load
|
||||
elif [[ -f "$BACKEND_TAR" ]]; then
|
||||
log "Loading backend image from: $BACKEND_TAR"
|
||||
docker load -i "$BACKEND_TAR"
|
||||
else
|
||||
warn "Backend tarball not found: $BACKEND_TAR"
|
||||
warn "Backend tarball not found: $BACKEND_TAR or $BACKEND_TARGZ"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
@ -16,7 +16,7 @@ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
# Default paths (override via env vars)
|
||||
REPO_PATH="${REPO_PATH:-/var/www/vhosts/yourdomain.com/git/customer-portal}"
|
||||
COMPOSE_FILE="${COMPOSE_FILE:-$PROJECT_ROOT/docker/portainer/docker-compose.yml}"
|
||||
COMPOSE_FILE="${COMPOSE_FILE:-$PROJECT_ROOT/docker/Prod - Portainer/docker-compose.yml}"
|
||||
ENV_FILE="${ENV_FILE:-$PROJECT_ROOT/.env}"
|
||||
|
||||
# Image settings
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user