feat: add Dockerfile and .dockerignore, refactor backend to use DATA_DIR for database and uploads

Now able to use docker image
This commit is contained in:
2025-11-11 02:08:48 +01:00
parent 3d9f7d2052
commit 9c61bf2e2c
4 changed files with 60 additions and 18 deletions

10
.dockerignore Normal file
View File

@@ -0,0 +1,10 @@
node_modules
frontend/node_modules
backend/node_modules
frontend/dist
backend/dist
backend/db.sqlite
backend/uploads
*.log
.DS_Store
.env

11
.gitignore vendored
View File

@@ -8,26 +8,19 @@ dist/
frontend/dist/ frontend/dist/
backend/dist/ backend/dist/
# SQLite database and uploads # Persistent backend data (database and uploads)
backend/db.sqlite backend/data/
backend/uploads/
# Logs # Logs
logs/ logs/
*.log *.log
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
pnpm-debug.log*
# Editor directories and files # Editor directories and files
.vscode/ .vscode/
.idea/ .idea/
.DS_Store .DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# Environment files (if any) # Environment files (if any)
.env .env

26
Dockerfile Normal file
View File

@@ -0,0 +1,26 @@
# Build frontend
FROM node:24-alpine AS frontend
WORKDIR /app/frontend
COPY frontend/package*.json ./
RUN npm install
COPY frontend ./
RUN npm run build
# Build backend
FROM node:24-alpine AS backend
WORKDIR /app
COPY backend/package*.json ./backend/
COPY backend/ ./backend/
RUN cd backend && npm install
RUN mkdir -p /data/uploads && chmod -R 777 /data
# Copy built frontend into backend
COPY --from=frontend /app/frontend/dist ./frontend/dist
WORKDIR /app/backend
EXPOSE 3000
ENV DATA_DIR=/data
CMD ["node", "index.js"]

View File

@@ -6,13 +6,19 @@ const multer = require('multer');
const fs = require('fs'); const fs = require('fs');
const app = express(); const app = express();
const dbPath = path.join(__dirname, 'db.sqlite');
const db = new sqlite3.Database(dbPath);
const upload = multer({ dest: path.join(__dirname, 'uploads/') });
// Use DATA_DIR env var if set, otherwise use local "data" folder
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, 'data');
const dbPath = path.join(DATA_DIR, 'db.sqlite');
const db = new sqlite3.Database(dbPath);
const upload = multer({ dest: path.join(DATA_DIR, 'uploads/') });
app.use(cors()); app.use(cors());
app.use(express.json()); app.use(express.json());
app.use('/uploads', express.static(path.join(__dirname, 'uploads'))); app.use('/uploads', express.static(path.join(DATA_DIR, 'uploads')));
// Create uploads directory if it doesn't exist
fs.mkdirSync(path.join(DATA_DIR, 'uploads'), { recursive: true });
// Initialize database and ensure counters table exists // Initialize database and ensure counters table exists
db.serialize(() => { db.serialize(() => {
@@ -38,7 +44,6 @@ app.get('/api/counters', (req, res) => {
}); });
}); });
// Create a new counter with image // Create a new counter with image
app.post('/api/counters', upload.single('image'), (req, res) => { app.post('/api/counters', upload.single('image'), (req, res) => {
const { name = 'Counter', value = 0 } = req.body; const { name = 'Counter', value = 0 } = req.body;
@@ -97,12 +102,20 @@ const clientBuildPath = path.join(__dirname, '..', 'frontend', 'dist');
app.use(express.static(clientBuildPath)); app.use(express.static(clientBuildPath));
// For SPA: serve index.html for any unknown route (after API and uploads) // For SPA: serve index.html for any unknown route (after API and uploads)
// app.get('*', (req, res) => { app.get('/*path', (req, res) => {
// if (req.path.startsWith('/api') || req.path.startsWith('/uploads')) return res.status(404).end(); if (req.path.startsWith('/api') || req.path.startsWith('/uploads')) return res.status(404).end();
// res.sendFile(path.join(clientBuildPath, 'index.html')); res.sendFile(path.join(clientBuildPath, 'index.html'));
// }); });
const PORT = 3000; const PORT = 3000;
app.listen(PORT, () => { app.listen(PORT, () => {
console.log(`API server running on http://localhost:${PORT}`); console.log(`API server running on http://localhost:${PORT}`);
}); });
process.on('SIGTERM', () => {
console.log('SIGTERM received, shutting down gracefully...');
db.close(() => {
console.log('Database connection closed.');
process.exit(0);
});
});