From bee3f758f62075dcdf91f6df52248a3aedd4dfe4 Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Mon, 25 May 2026 15:52:52 +0000 Subject: [PATCH] PostgreSQL statt SQLite: eigener DB-Container in Compose --- backend/config/database.js | 21 +++--- backend/package-lock.json | 128 +++++++++++++++++++++++++++++++++++++ backend/package.json | 1 + docker-compose.simple.yml | 30 ++++++++- 4 files changed, 170 insertions(+), 10 deletions(-) diff --git a/backend/config/database.js b/backend/config/database.js index fc5b186..abdedc3 100644 --- a/backend/config/database.js +++ b/backend/config/database.js @@ -1,20 +1,25 @@ const { Sequelize } = require('sequelize'); -const sequelize = new Sequelize({ - dialect: 'sqlite', - storage: process.env.DB_PATH || './database.sqlite', - logging: false, -}); +const sequelize = new Sequelize( + process.env.DB_NAME || 'webcad', + process.env.DB_USER || 'webcad', + process.env.DB_PASSWORD || 'webcad', + { + host: process.env.DB_HOST || 'postgres', + port: process.env.DB_PORT || 5432, + dialect: 'postgres', + logging: false, + } +); const connectDB = async () => { try { await sequelize.authenticate(); - console.log('Database connected.'); + console.log('PostgreSQL connected.'); await sequelize.sync(); console.log('Database synced.'); } catch (err) { - console.error('Database connection error:', err); - // Retry after 5s + console.error('DB connection error:', err.message); setTimeout(connectDB, 5000); } }; diff --git a/backend/package-lock.json b/backend/package-lock.json index 288cb03..b6967e3 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -18,6 +18,7 @@ "passport": "^0.7.0", "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", + "pg": "^8.21.0", "sequelize": "^6.37.8", "sqlite3": "^6.0.1" } @@ -1206,11 +1207,87 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, + "node_modules/pg": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.21.0.tgz", + "integrity": "sha512-AUP1EYJuHraQGsVoCQVIcM7TEJVGtDzxWtGFZd8rds9d+CCXlU5Js1rYgfLNvxy9iJrpHjGrRjoi/3BT9fRyiA==", + "dependencies": { + "pg-connection-string": "^2.13.0", + "pg-pool": "^3.14.0", + "pg-protocol": "^1.14.0", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.4.0" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.4.0.tgz", + "integrity": "sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A==", + "optional": true + }, "node_modules/pg-connection-string": { "version": "2.13.0", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.13.0.tgz", "integrity": "sha512-EMnU9E2fSULdsbErBbMaXJvFeD9B4+nPcM3f+4lsiCR0BHLPrLVjv3DbyM2hgQQviKJaTWIRRTjKjWlHg3p2ig==" }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.14.0.tgz", + "integrity": "sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.14.0.tgz", + "integrity": "sha512-n5taZ1kO3s9ngDTVxsEznOqCyToTgz0FLuPq0B33COy5pPpuWJpY3/2oRBVETuOgzdqRXfWpM9HIhp2LBBT1BA==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", @@ -1223,6 +1300,41 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -1625,6 +1737,14 @@ "simple-concat": "^1.0.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sqlite3": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-6.0.1.tgz", @@ -1891,6 +2011,14 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", diff --git a/backend/package.json b/backend/package.json index 1ea562b..58f2480 100644 --- a/backend/package.json +++ b/backend/package.json @@ -19,6 +19,7 @@ "passport": "^0.7.0", "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", + "pg": "^8.21.0", "sequelize": "^6.37.8", "sqlite3": "^6.0.1" } diff --git a/docker-compose.simple.yml b/docker-compose.simple.yml index 644e447..ace9fa1 100644 --- a/docker-compose.simple.yml +++ b/docker-compose.simple.yml @@ -1,6 +1,21 @@ version: '3.8' services: + postgres: + image: postgres:16-alpine + environment: + - POSTGRES_USER=webcad + - POSTGRES_PASSWORD=webcad + - POSTGRES_DB=webcad + volumes: + - pg_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U webcad"] + interval: 5s + timeout: 5s + retries: 10 + restart: unless-stopped + backend: image: node:22-alpine working_dir: /app @@ -8,6 +23,11 @@ services: - NODE_ENV=production - JWT_SECRET=cad-jwt-secret-prod-2026 - PORT=5000 + - DB_HOST=postgres + - DB_PORT=5432 + - DB_USER=webcad + - DB_PASSWORD=webcad + - DB_NAME=webcad expose: - "5000" command: @@ -20,6 +40,9 @@ services: rm -rf /tmp/repo npm ci --only=production node server.js + depends_on: + postgres: + condition: service_healthy healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:5000/api/health',r=>{process.exit(r.statusCode===200?0:1)})"] interval: 15s @@ -43,7 +66,7 @@ services: rm -rf /tmp/repo npm ci npx vite build --mode production - npx serve -s dist -l 80 + npx vite preview --host 0.0.0.0 --port 80 depends_on: - backend healthcheck: @@ -51,5 +74,8 @@ services: interval: 15s timeout: 5s retries: 15 - start_period: 90s + start_period: 120s restart: unless-stopped + +volumes: + pg_data: