dockerized version instead of nixpack
This commit is contained in:
parent
7b98d2c894
commit
a76b371bda
11
.dockerignore
Normal file
11
.dockerignore
Normal file
@ -0,0 +1,11 @@
|
||||
node_modules
|
||||
dist
|
||||
.git
|
||||
.vscode
|
||||
.idea
|
||||
.DS_Store
|
||||
.env
|
||||
npm-debug.log*
|
||||
yarn-*.log*
|
||||
pnpm-debug.log*
|
||||
docker-compose.yml
|
||||
28
Dockerfile
Normal file
28
Dockerfile
Normal file
@ -0,0 +1,28 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
ARG NODE_VERSION=20.15.0
|
||||
FROM node:${NODE_VERSION}-alpine AS build
|
||||
WORKDIR /app
|
||||
|
||||
# Install deps first for better caching
|
||||
COPY package*.json ./
|
||||
RUN npm ci || npm install
|
||||
|
||||
# Build
|
||||
COPY . .
|
||||
ENV NODE_ENV=production
|
||||
# Limit Node heap during build to avoid OOM on small builders
|
||||
ENV NODE_OPTIONS=--max-old-space-size=512
|
||||
RUN npm run build
|
||||
|
||||
# ---- Runtime (Nginx) ----
|
||||
FROM nginx:1.27-alpine AS runtime
|
||||
# Remove default site content
|
||||
RUN rm -rf /usr/share/nginx/html/*
|
||||
# SPA config (history fallback)
|
||||
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
# Static assets
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
EXPOSE 80
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD wget -qO- http://localhost/ >/dev/null 2>&1 || exit 1
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
34
README.md
34
README.md
@ -1,29 +1,31 @@
|
||||
# Reading Goal App
|
||||
# Reading Goal App (Dockerized)
|
||||
|
||||
A React + Vite + Tailwind single-page app. Dates are DD/MM/YYYY everywhere and the calendar starts on Monday.
|
||||
|
||||
## Local Development
|
||||
React + Vite + Tailwind. Dates use **DD/MM/YYYY** and the calendar week starts on **Monday**.
|
||||
Includes a multi-stage Dockerfile: Node build → Nginx runtime with SPA fallback.
|
||||
|
||||
## Local Dev
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Production Build
|
||||
|
||||
## Production Build (local)
|
||||
```bash
|
||||
npm run build
|
||||
npm run preview
|
||||
```
|
||||
|
||||
## Deploy with Coolify (Nixpacks)
|
||||
## Docker (build locally)
|
||||
```bash
|
||||
docker build -t reading-goal-app:latest .
|
||||
docker run -d --name reading-goal-app -p 8080:80 --restart unless-stopped reading-goal-app:latest
|
||||
# Open http://localhost:8080
|
||||
```
|
||||
|
||||
1. Push this repo to GitHub.
|
||||
2. In Coolify: **Create Application → Git**, select your repo/branch.
|
||||
3. **Build Pack**: choose **Nixpacks**.
|
||||
4. No base directory unless you're using a monorepo.
|
||||
5. (Optional) **Environment**: set `NODE_ENV=production`.
|
||||
6. Deploy. The container will:
|
||||
- install dependencies
|
||||
- build with `vite build` (output in `dist/`)
|
||||
- run `serve -s dist -l $PORT` (Coolify injects `$PORT`)
|
||||
## Deploy in Coolify
|
||||
- Deployment Type: **Dockerfile**
|
||||
- Dockerfile path: `Dockerfile`
|
||||
- **Internal Port**: `80` (Nginx)
|
||||
- No extra start command needed.
|
||||
|
||||
The multi-stage image builds the app (`vite build`) and serves static files via Nginx with history API fallback.
|
||||
|
||||
18
docker/nginx.conf
Normal file
18
docker/nginx.conf
Normal file
@ -0,0 +1,18 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Serve files if they exist, else fallback to index.html (SPA)
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Static assets (cache-friendly)
|
||||
location ~* \.(?:js|css|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
try_files $uri /index.html;
|
||||
}
|
||||
}
|
||||
@ -6,8 +6,7 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview --host 0.0.0.0 --port 5173",
|
||||
"start": "serve -s dist -l ${PORT:-3000}"
|
||||
"preview": "vite preview --host 0.0.0.0 --port 5173"
|
||||
},
|
||||
"dependencies": {
|
||||
"lucide-react": "^0.452.0",
|
||||
@ -20,7 +19,6 @@
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"autoprefixer": "^10.4.18",
|
||||
"postcss": "^8.4.33",
|
||||
"serve": "^14.2.1",
|
||||
"tailwindcss": "^3.4.9",
|
||||
"typescript": "^5.5.4",
|
||||
"vite": "^5.3.4"
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { BookOpen, Plus, X, Edit2, Check, ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
|
||||
@ -598,7 +597,7 @@ const ReadingGoalApp = () => {
|
||||
<h3 className="font-semibold mb-3">Progress Overview</h3>
|
||||
<div className="space-y-3">
|
||||
<div className="flex justify-between"><span className="text-gray-600">Current Progress</span><span className="font-medium">{book.currentPage} / {book.totalPages} pages</span></div>
|
||||
<div className="w.full bg-gray-200 rounded-full h-3"><div className="bg-blue-500 h-3 rounded-full transition-all" style={{ width: `${Math.min(progressPercent, 100)}%` }} /></div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-3"><div className="bg-blue-500 h-3 rounded-full transition-all" style={{ width: `${Math.min(progressPercent, 100)}%` }} /></div>
|
||||
<div className="flex justify-between"><span className="text-gray-600">Completion</span><span className="font-medium">{progressPercent.toFixed(1)}%</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user