Ports fixed v0.4
This commit is contained in:
parent
4ae59afd98
commit
f7b7a27e53
3 changed files with 59 additions and 58 deletions
78
COOLIFY.md
78
COOLIFY.md
|
|
@ -1,19 +1,41 @@
|
||||||
# Coolify & PostgreSQL Deployment Guide
|
# Coolify Deployment & "No Available Server" Troubleshooting Guide
|
||||||
|
|
||||||
This application consists of:
|
This application consists of:
|
||||||
1. **Server Side**: Node.js + Express backend (`server.ts`) serving REST APIs, managing authentication, ledger reconciliation, audit logs, FX rates, SMTP dispatching, and financial reports.
|
1. **Server Side**: Node.js + Express backend (`server.ts`) serving REST APIs, managing authentication, ledger reconciliation, audit logs, FX rates, SMTP dispatching, and financial reports.
|
||||||
2. **Database**: PostgreSQL (via `pg` connection pool) with automatic JSON fallback backup.
|
2. **Database**: PostgreSQL (via `pg` connection pool) with automatic JSON fallback backup.
|
||||||
3. **Frontend**: React SPA served directly via Express in production.
|
3. **Frontend**: React SPA served directly via Express in production on port `3000`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Quick Coolify Deployment Options
|
## 🔧 Resolving "No Available Server" in Coolify
|
||||||
|
|
||||||
### Option A: Docker Compose Deployment (Application + PostgreSQL in One Stack)
|
If Coolify displays **"No available server"** or Traefik returns a **503 / 502 error**, follow these exact fixes:
|
||||||
|
|
||||||
|
### 1. Fix Health Check Path & IPv4 Resolution (Included in codebase)
|
||||||
|
- **Cause**: Alpine Linux `wget` resolves `localhost` to IPv6 (`::1`), while Node Express binds to IPv4 (`0.0.0.0`). When `wget` fails, Docker marks the container `unhealthy`, causing Coolify Traefik to drop the container.
|
||||||
|
- **Fix**: The updated `Dockerfile` and `docker-compose.yml` use native Node.js HTTP checks against `http://127.0.0.1:3000/api/health`:
|
||||||
|
```bash
|
||||||
|
node -e "require('http').get('http://127.0.0.1:3000/api/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
|
||||||
|
```
|
||||||
|
- **Coolify UI Setting**: Under your resource in Coolify -> **Health Check**:
|
||||||
|
- **Path**: `/api/health`
|
||||||
|
- **Port**: `3000`
|
||||||
|
|
||||||
|
### 2. Configure Exposed Port in Coolify UI
|
||||||
|
- **In Coolify Dashboard**:
|
||||||
|
- Open your deployed application/stack.
|
||||||
|
- Go to **Settings** -> **Exposed Port** (or **Port**).
|
||||||
|
- Ensure the port is set to `3000`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Deployment Methods in Coolify
|
||||||
|
|
||||||
|
### Option A: Docker Compose Deployment (App + Dedicated PostgreSQL)
|
||||||
|
|
||||||
1. **In Coolify Dashboard**:
|
1. **In Coolify Dashboard**:
|
||||||
- Click **+ Add Resource** -> **Docker Compose**.
|
- Click **+ Add Resource** -> **Docker Compose**.
|
||||||
- Point to your Git Repository or paste the contents of `docker-compose.yml`.
|
- Point to your Git Repository or paste `docker-compose.yml`.
|
||||||
2. **Environment Variables**:
|
2. **Environment Variables**:
|
||||||
Add the following in Coolify:
|
Add the following in Coolify:
|
||||||
```env
|
```env
|
||||||
|
|
@ -21,7 +43,7 @@ This application consists of:
|
||||||
PORT=3000
|
PORT=3000
|
||||||
POSTGRES_PASSWORD=your_custom_secure_password
|
POSTGRES_PASSWORD=your_custom_secure_password
|
||||||
|
|
||||||
# SMTP Email Dispatch Settings
|
# SMTP Email Settings (Optional)
|
||||||
SMTP_HOST=smtp.your-server.com
|
SMTP_HOST=smtp.your-server.com
|
||||||
SMTP_PORT=587
|
SMTP_PORT=587
|
||||||
SMTP_USER=alerts@networkbank.com
|
SMTP_USER=alerts@networkbank.com
|
||||||
|
|
@ -29,42 +51,24 @@ This application consists of:
|
||||||
SMTP_FROM="Balance Sheet Portal <noreply@networkbank.com>"
|
SMTP_FROM="Balance Sheet Portal <noreply@networkbank.com>"
|
||||||
SMTP_USE_TLS=true
|
SMTP_USE_TLS=true
|
||||||
```
|
```
|
||||||
3. **Deploy**:
|
3. **Health Check Endpoint**: Set path to `/api/health` on port `3000`.
|
||||||
- Coolify will build the app container and spin up a dedicated `postgres:16-alpine` database container with health checks and persistent volume storage (`balance_sheet_postgres_data`). The application uses `expose: "3000"` to avoid host port binding conflicts while allowing Coolify's reverse proxy (Traefik/Nginx) to route external web traffic.
|
4. **Deploy**: Coolify builds the app and provisions `postgres:16-alpine`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Option B: Coolify Managed PostgreSQL + Standalone App Container
|
### Option B: Standalone Application Container (Using Coolify Managed PostgreSQL)
|
||||||
|
|
||||||
If you prefer using Coolify's built-in managed PostgreSQL database resource:
|
1. **Create PostgreSQL Resource**:
|
||||||
|
|
||||||
1. **Create Database in Coolify**:
|
|
||||||
- Click **+ Add Resource** -> **PostgreSQL**.
|
- Click **+ Add Resource** -> **PostgreSQL**.
|
||||||
- Coolify will provide an internal database connection URL (e.g., `postgresql://postgres:pass@coolify-postgres-host:5432/balance_sheet_db`).
|
- Note the database internal connection string (e.g. `postgresql://postgres:pass@postgres-host:5432/balance_sheet_db`).
|
||||||
2. **Deploy App Service**:
|
2. **Create Dockerfile Application**:
|
||||||
- Add your Git repo as a **Dockerfile** application.
|
- Add Git Repository as a **Dockerfile Application**.
|
||||||
- Set environment variable in Coolify UI:
|
- Set Environment Variables:
|
||||||
```env
|
```env
|
||||||
DATABASE_URL=postgresql://postgres:pass@coolify-postgres-host:5432/balance_sheet_db
|
NODE_ENV=production
|
||||||
PORT=3000
|
PORT=3000
|
||||||
|
DATABASE_URL=postgresql://postgres:pass@postgres-host:5432/balance_sheet_db
|
||||||
# SMTP Email Settings
|
|
||||||
SMTP_HOST=smtp.your-server.com
|
|
||||||
SMTP_PORT=587
|
|
||||||
SMTP_USER=alerts@networkbank.com
|
|
||||||
SMTP_PASS=your_smtp_password
|
|
||||||
```
|
```
|
||||||
3. **Deploy**:
|
- In Settings -> **Exposed Port**: Set to `3000`.
|
||||||
- The Express server will automatically connect to the PostgreSQL database, create the necessary table structures on boot, and store all portal state in PostgreSQL.
|
- In Health Check: Set path to `/api/health`.
|
||||||
|
3. **Deploy**: Express connects directly to PostgreSQL and initializes required tables automatically.
|
||||||
---
|
|
||||||
|
|
||||||
## 2. Server-Side Architecture & Configuration
|
|
||||||
|
|
||||||
- **Internal Container Port**: Application listens on `3000` inside the container (`EXPOSE 3000`).
|
|
||||||
- **Conflict Prevention**: Uses Docker Compose `expose` (`3000` for app, `5432` for postgres) instead of direct host port bindings to eliminate host interface port allocation conflicts.
|
|
||||||
- **SMTP Environment Overrides**: SMTP configuration (`SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `SMTP_FROM`, `SMTP_USE_TLS`) is fully managed via environment variables.
|
|
||||||
- **Automatic Table Creation**: On server boot, the backend runs `initPgDatabase()` to verify/create `app_portal_state`.
|
|
||||||
- **Automatic State Recovery**: If PostgreSQL contains existing data, portal state is loaded directly from PostgreSQL.
|
|
||||||
- **Resilient Fallback**: If `DATABASE_URL` is omitted, the app gracefully operates using persistent JSON storage (`/app/data/portal-data.json`).
|
|
||||||
- **Health Check**: Express exposes `GET /api/health` for Docker container monitoring.
|
|
||||||
|
|
|
||||||
25
README.md
25
README.md
|
|
@ -9,7 +9,7 @@ A full-stack enterprise web application built for multi-branch balance sheet con
|
||||||
- **Multi-Branch Operations**: Head Office Admin, Branch Users, Maker-Checker authorization matrix.
|
- **Multi-Branch Operations**: Head Office Admin, Branch Users, Maker-Checker authorization matrix.
|
||||||
- **Server-Side Architecture**: Express backend (`server.ts`) handling state management, calculations, audit logging, and email dispatches.
|
- **Server-Side Architecture**: Express backend (`server.ts`) handling state management, calculations, audit logging, and email dispatches.
|
||||||
- **PostgreSQL & Fallback Storage**: Connects to PostgreSQL via `pg` connection pool with automatic fallback to JSON data persistence (`/app/data/portal-data.json`).
|
- **PostgreSQL & Fallback Storage**: Connects to PostgreSQL via `pg` connection pool with automatic fallback to JSON data persistence (`/app/data/portal-data.json`).
|
||||||
- **Containerized Deployment**: Ready for Docker, Docker Compose, and **Coolify** self-hosting.
|
- **Containerized Deployment**: Built for Docker, Docker Compose, and **Coolify** self-hosting.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -17,22 +17,22 @@ A full-stack enterprise web application built for multi-branch balance sheet con
|
||||||
|
|
||||||
| File | Description |
|
| File | Description |
|
||||||
| :--- | :--- |
|
| :--- | :--- |
|
||||||
| `Dockerfile` & `dockerfile` | Multi-stage production container build (Vite client + Express CJS server, exposing port 3000). |
|
| `Dockerfile` & `dockerfile` | Multi-stage production container build (Vite client + Express CJS server, exposing port 3000 with IPv4 health check). |
|
||||||
| `docker-compose.yml` | Full-stack orchestration using `expose: "3000"` and `expose: "5432"` to prevent host port binding conflicts. |
|
| `docker-compose.yml` | Full-stack orchestration (App container on port 3000 + PostgreSQL container on port 5432). |
|
||||||
| `.dockerignore` | Defines context exclusions for slim Docker image builds. |
|
| `.dockerignore` | Context exclusions for slim Docker image builds. |
|
||||||
| `.env.example` | Template environment variables (`DATABASE_URL`, `PORT`, `DATA_PATH`, `SMTP_*`). |
|
| `.env.example` | Template environment variables (`DATABASE_URL`, `PORT`, `DATA_PATH`, `SMTP_*`). |
|
||||||
| `COOLIFY.md` | Complete deployment guide for Coolify platform & managed databases. |
|
| `COOLIFY.md` | Deployment & "No Available Server" troubleshooting guide for Coolify platform & Traefik proxies. |
|
||||||
| `server.ts` | Express server entry point with PostgreSQL initialization, environment SMTP dispatching, and REST API routes. |
|
| `server.ts` | Express server entry point with PostgreSQL initialization, environment SMTP dispatching, and REST API routes. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ Local Development & Running via Docker
|
## 🛠️ Local Development & Running via Docker
|
||||||
|
|
||||||
### 1. Run via Docker Compose (With PostgreSQL & Exposed Port 3000)
|
### 1. Run via Docker Compose
|
||||||
```bash
|
```bash
|
||||||
docker-compose up --build -d
|
docker-compose up --build -d
|
||||||
```
|
```
|
||||||
The application container exposes port `3000` internally via Docker network `expose` configuration, avoiding host port allocation conflicts. Reverse proxies (Coolify, Traefik, Nginx) or container networks route directly to port `3000`.
|
The application container exposes port `3000` (`http://localhost:3000`), with an automated health check on `/api/health`.
|
||||||
|
|
||||||
### 2. Run via Docker CLI
|
### 2. Run via Docker CLI
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -40,17 +40,8 @@ docker build -t balance-sheet-portal .
|
||||||
docker run -p 3000:3000 -v portal_data:/app/data balance-sheet-portal
|
docker run -p 3000:3000 -v portal_data:/app/data balance-sheet-portal
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Native Node.js Development
|
|
||||||
```bash
|
|
||||||
# Install dependencies
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# Start development server (Express + Vite hot reload)
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ☁️ Deployment on Coolify
|
## ☁️ Deployment on Coolify
|
||||||
|
|
||||||
Refer to [`COOLIFY.md`](./COOLIFY.md) for step-by-step instructions on deploying via Docker Compose or Coolify Managed PostgreSQL.
|
Refer to [`COOLIFY.md`](./COOLIFY.md) for step-by-step instructions on deploying via Docker Compose or Coolify Managed PostgreSQL, and resolving Traefik "No available server" status.
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_db_data:/var/lib/postgresql/data
|
- postgres_db_data:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U postgres -d balance_sheet_db"]
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||||
interval: 10s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|
||||||
|
|
@ -31,10 +31,16 @@ services:
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
expose:
|
expose:
|
||||||
- "3000"
|
- "3000"
|
||||||
|
labels:
|
||||||
|
- "coolify.managed=true"
|
||||||
|
- "coolify.port=3000"
|
||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
|
- PORT=3000
|
||||||
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres_secure_pass_2026}@postgres:5432/balance_sheet_db
|
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD:-postgres_secure_pass_2026}@postgres:5432/balance_sheet_db
|
||||||
- DATA_PATH=/app/data/portal-data.json
|
- DATA_PATH=/app/data/portal-data.json
|
||||||
- SMTP_HOST=${SMTP_HOST:-}
|
- SMTP_HOST=${SMTP_HOST:-}
|
||||||
|
|
@ -46,8 +52,8 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- portal_data:/app/data
|
- portal_data:/app/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
|
test: ["CMD", "node", "-e", "require('http').get('http://127.0.0.1:3000/api/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"]
|
||||||
interval: 30s
|
interval: 15s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 10s
|
start_period: 10s
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue