176 lines
5.9 KiB
Markdown
176 lines
5.9 KiB
Markdown
# GymFlow Deployment Guide (NAS / Existing Container)
|
|
|
|
This guide explains how to deploy GymFlow to your Ugreen NAS by integrating it into your existing `nodejs-apps` container.
|
|
|
|
## 1. Preparation (Build)
|
|
|
|
You need to build the application on your local machine before transferring it to the NAS.
|
|
|
|
### Build Frontend
|
|
Run the following in the project root:
|
|
```bash
|
|
npm install
|
|
npm install
|
|
npm run build
|
|
```
|
|
> [!IMPORTANT]
|
|
> If you encounter a `TypeError: Missing parameter name` in your logs, ensure you have rebuilt the app with the latest changes (`app.get('*all', ...)`).
|
|
This creates a `dist` folder with the compiled frontend.
|
|
|
|
### Build Backend
|
|
1. Update your `server/package.json` to have these scripts for production:
|
|
```json
|
|
"scripts": {
|
|
"start": "node dist/index.js",
|
|
"start:prod": "node dist/index.js",
|
|
...
|
|
}
|
|
```
|
|
2. Run the following locally:
|
|
```bash
|
|
cd server
|
|
npm install
|
|
npm run build
|
|
cd ..
|
|
```
|
|
|
|
## 2. Transfer Files
|
|
|
|
Copy the entire `gymflow` folder to your NAS.
|
|
Destination: `nodejs_data/gymflow` (inside the folder mounted to `/usr/src/app`).
|
|
|
|
Ensure the following files/folders are present on the NAS:
|
|
- `gymflow/dist/` (Frontend assets)
|
|
- `gymflow/server/dist/` (Backend code)
|
|
- `gymflow/server/package.json`
|
|
- `gymflow/server/prisma/` (Schema for database)
|
|
- `gymflow/ecosystem.config.cjs` (PM2 config)
|
|
|
|
*Note: You do not need to copy `node_modules`. We will install production dependencies on the NAS to ensure compatibility.*
|
|
|
|
Update your `docker-compose.yml` to use a custom Dockerfile (to support building native modules like `better-sqlite3`) and map the new port.
|
|
|
|
### 2a. Use Custom Dockerfile
|
|
The standard `node:lts-slim` image lacks Python and build tools. Use the provided [Dockerfile.node-apps](file:///d:/Coding/gymflow/Dockerfile.node-apps):
|
|
|
|
1. Copy `Dockerfile.node-apps` to your NAS alongside `docker-compose.yml`.
|
|
2. Modify `docker-compose.yml`:
|
|
```yaml
|
|
services:
|
|
nodejs-apps:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile.node-apps
|
|
container_name: node-apps
|
|
# image: node:lts-slim <-- Comment this out
|
|
...
|
|
```
|
|
|
|
### 3. Integration
|
|
|
|
### Update `command`
|
|
Add the following to your existing command string. We added `npx prisma generate` explicitly to ensure the Linux client is built correctly, and we ensure `DATABASE_URL` is consistent:
|
|
|
|
```bash
|
|
... && cd ../gymflow/server && npm install --omit=dev && APP_MODE=prod DATABASE_URL=file:./prod.db npx prisma generate && APP_MODE=prod DATABASE_URL=file:./prod.db npx prisma db push && cd .. && pm2 start ecosystem.config.cjs && ...
|
|
```
|
|
*Note: We assume `gymflow` is a sibling of `ag-beats` etc.*
|
|
|
|
**Full Command Example:**
|
|
```yaml
|
|
command: /bin/sh -c "npm install -g pm2 && cd ag-beats && npm install && cd ../ball-shooting && npm install && cd ../gymflow/server && npm install --omit=dev && APP_MODE=prod DATABASE_URL=file:./prod.db npx prisma generate && APP_MODE=prod DATABASE_URL=file:./prod.db npx prisma db push && cd .. && pm2 start ecosystem.config.cjs && cd ../ag-beats && pm2 start ecosystem.config.js && cd ../ball-shooting && pm2 start npm --name ag-ball -- start && pm2 logs --raw"
|
|
```
|
|
|
|
> [!IMPORTANT]
|
|
> Since we updated the `Dockerfile.node-apps` to include `openssl` (required by Prisma), you **must** rebuild the image:
|
|
> `docker-compose up -d --build nodejs-apps`
|
|
|
|
### Update `ports`
|
|
Add the GymFlow port (3003 inside container, mapped to your choice, e.g., 3033):
|
|
```yaml
|
|
ports:
|
|
- "3030:3000"
|
|
- "3031:3001"
|
|
- "3032:3002"
|
|
- "3033:3003" # GymFlow
|
|
```
|
|
|
|
## 4. Unified Ecosystem Config
|
|
Your common `ecosystem.config.js` should look like this to ensure GymFlow has the correct production environment:
|
|
|
|
```javascript
|
|
module.exports = {
|
|
apps: [
|
|
{
|
|
name: "ag-home",
|
|
script: "server.js",
|
|
cwd: "/usr/src/app",
|
|
exec_mode: "fork",
|
|
},
|
|
{
|
|
name: "ag-beats",
|
|
script: "npm",
|
|
args: "start",
|
|
cwd: "/usr/src/app/ag-beats",
|
|
},
|
|
{
|
|
name: "ag-ball",
|
|
script: "npm",
|
|
args: "start",
|
|
cwd: "/usr/src/app/ball-shooting",
|
|
},
|
|
{
|
|
name: "gymflow",
|
|
script: "dist/index.js",
|
|
cwd: "/usr/src/app/gymflow/server",
|
|
env: {
|
|
NODE_ENV: "production",
|
|
APP_MODE: "prod",
|
|
PORT: 3003,
|
|
DATABASE_URL: "file:./prod.db",
|
|
DATABASE_URL_PROD: "file:./prod.db"
|
|
}
|
|
}
|
|
]
|
|
};
|
|
```
|
|
|
|
## 5. Nginx Proxy Manager
|
|
|
|
Point your domain (e.g., `gym.yourdomain.com`) to the NAS IP and the mapped port (`3033`).
|
|
- Scheme: `http`
|
|
- Forward Hostname / IP: `[NAS_IP]`
|
|
- Forward Port: `3033`
|
|
- Websockets Support: Enable (if needed for future features).
|
|
|
|
## 6. Troubleshooting
|
|
|
|
### "Readonly Database" Error
|
|
If you see an error like `Invalid prisma.userProfile.upsert() invocation: attempt to write a readonly database`:
|
|
|
|
1. **Verify Permissions:** Run the diagnostic script inside your container:
|
|
```bash
|
|
docker exec -it node-apps node /usr/src/app/gymflow/server/check_db_perms.js
|
|
```
|
|
2. **Fix Permissions:** If the checks fail, run these commands on your NAS inside the `gymflow/server` directory:
|
|
```bash
|
|
sudo chmod 777 .
|
|
sudo chmod 666 prod.db
|
|
```
|
|
*Note: SQLite needs write access to the directory itself to create temporary journaling files (`-wal`, `-shm`).*
|
|
|
|
3. **Check Docker User:** Alternatively, ensure your Docker container is running as a user who owns these files (e.g., set `user: "1000:1000"` in `docker-compose.yml` if your NAS user has that ID).
|
|
|
|
### "Invalid ELF Header" Error
|
|
If you see an error like `invalid ELF header` for `better-sqlite3.node`:
|
|
This happens because the `node_modules` contains Windows binaries (from your local machine) instead of Linux binaries.
|
|
|
|
1. **Fix Inside Container:** Run the following command to force a rebuild of native modules for Linux:
|
|
```bash
|
|
docker exec -it node-apps /bin/sh -c "cd /usr/src/app/gymflow/server && npm rebuild better-sqlite3"
|
|
```
|
|
2. **Restart Container:** After rebuilding, restart the container:
|
|
```bash
|
|
docker-compose restart nodejs-apps
|
|
```
|