🚀 Refactor: Saubere Docker-Struktur mit getrennten dev/prod Umgebungen
- Neue Docker-Struktur: docker/{dev,prod}/ für klare Trennung
- Entfernt: docker-compose.override.yml (problematisch)
- Hinzugefügt: ./dev.sh und ./prod.sh Scripts für einfache Bedienung
- Container-spezifische Konfigurationen in docker/{dev,prod}/*/config/
- Aktualisierte READMEs für neue Struktur
- Backend-Daten in .gitignore hinzugefügt
- Bereinigt: Veraltete Dockerfiles und Konfigurationsdateien
Jetzt: Wartungsfreundlich, keine Verwirrung zwischen Umgebungen
This commit is contained in:
parent
7ea95341c0
commit
2678ad9b12
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -24,3 +24,6 @@ npm-debug.log*
|
||||||
# Build outputs
|
# Build outputs
|
||||||
dist/
|
dist/
|
||||||
build/
|
build/
|
||||||
|
|
||||||
|
# Backend data (uploaded images, database, etc.)
|
||||||
|
backend/src/data/
|
||||||
|
|
|
||||||
|
|
@ -1,52 +1,79 @@
|
||||||
## Dev: Schnellstart
|
# Development Setup
|
||||||
|
|
||||||
Kurz und knapp — so startest und nutzt du die lokale Dev‑Umgebung mit HMR (nginx als Proxy vor dem CRA dev server):
|
## Schnellstart
|
||||||
|
|
||||||
Voraussetzungen
|
### Starten (Development Environment)
|
||||||
- Docker & Docker Compose (Docker Compose Plugin)
|
|
||||||
|
|
||||||
Starten (Dev)
|
|
||||||
1. Build & Start (daemon):
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up --build -d image-uploader-frontend
|
# Mit Script (empfohlen):
|
||||||
```
|
./dev.sh
|
||||||
2. Logs verfolgen:
|
|
||||||
```bash
|
|
||||||
docker compose logs -f image-uploader-frontend
|
|
||||||
```
|
|
||||||
3. Browser öffnen: http://localhost:3000 (HMR aktiv)
|
|
||||||
|
|
||||||
Ändern & Testen
|
# Oder manuell:
|
||||||
- Dateien editieren im `frontend/src/...` → HMR übernimmt Änderungen sofort.
|
docker compose -f docker/dev/docker-compose.yml up -d
|
||||||
- Wenn du nginx‑Konfiguration anpassen willst, editiere `frontend/conf/conf.d/default.conf` (Dev‑Variante wird beim Containerstart benutzt). Nach Änderung: nginx reload ohne Neustart:
|
|
||||||
```bash
|
|
||||||
docker compose exec image-uploader-frontend nginx -s reload
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Probleme mit `node_modules`
|
### Zugriff
|
||||||
- Wenn du ein host‑seitiges `frontend/node_modules` hast, lösche es (konsistenter ist der container‑verwaltete Volume):
|
- **Frontend**: http://localhost:3000 (Hot Module Reloading aktiv)
|
||||||
```bash
|
- **Backend**: http://localhost:5001 (API)
|
||||||
rm -rf frontend/node_modules
|
- **Slideshow**: http://localhost:3000/slideshow
|
||||||
```
|
|
||||||
Danach `docker compose up --build -d image-uploader-frontend` erneut ausführen.
|
|
||||||
|
|
||||||
Stoppen
|
### Logs verfolgen
|
||||||
```bash
|
```bash
|
||||||
docker compose down
|
# Alle Services:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml logs -f
|
||||||
|
|
||||||
|
# Nur Frontend:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml logs -f frontend-dev
|
||||||
|
|
||||||
|
# Nur Backend:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml logs -f backend-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Hinweis
|
### Entwicklung
|
||||||
- Diese Dev‑Konfiguration läuft lokal mit erweiterten Rechten (nur für Entwicklung). Produktions‑Images/Configs bleiben unverändert.
|
|
||||||
|
|
||||||
|
#### Frontend-Entwicklung
|
||||||
|
- Code in `frontend/src/` editieren → Hot Module Reload übernimmt Änderungen
|
||||||
|
- Volumes: Source-Code wird live in Container gemountet
|
||||||
|
- Container-Namen: `image-uploader-frontend-dev`
|
||||||
|
|
||||||
Build and start:
|
#### Backend-Entwicklung
|
||||||
docker compose up --build -d image-uploader-frontend
|
- Code in `backend/src/` editieren → Container restart für Änderungen
|
||||||
|
- Container-Namen: `image-uploader-backend-dev`
|
||||||
|
- Environment: `NODE_ENV=development`
|
||||||
|
|
||||||
Tail logs:
|
#### Konfiguration anpassen
|
||||||
docker compose logs -f image-uploader-frontend
|
- **Frontend**: `docker/dev/frontend/config/.env`
|
||||||
|
- **Backend**: `docker/dev/backend/config/.env`
|
||||||
|
- **Nginx**: `docker/dev/frontend/nginx.conf`
|
||||||
|
|
||||||
Reload nginx (after editing conf in container):
|
### Container-Management
|
||||||
docker compose exec image-uploader-frontend nginx -s reload
|
|
||||||
|
```bash
|
||||||
|
# Status anzeigen:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml ps
|
||||||
|
|
||||||
|
# Container neustarten:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml restart
|
||||||
|
|
||||||
|
# Container neu bauen:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml build --no-cache
|
||||||
|
|
||||||
|
# Stoppen:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml down
|
||||||
|
|
||||||
|
# Mit Volumes löschen:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shell-Zugriff
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Frontend Container:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml exec frontend-dev bash
|
||||||
|
|
||||||
|
# Backend Container:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml exec backend-dev bash
|
||||||
|
```
|
||||||
|
|
||||||
docker compose exec image-uploader-frontend nginx -s reload
|
docker compose exec image-uploader-frontend nginx -s reload
|
||||||
docker compose down
|
docker compose down
|
||||||
109
README.md
109
README.md
|
|
@ -37,63 +37,36 @@ This project extends the original [Image-Uploader by vallezw](https://github.com
|
||||||
|
|
||||||
### Docker Deployment (Recommended)
|
### Docker Deployment (Recommended)
|
||||||
|
|
||||||
1. **Create docker-compose.yml**:
|
#### Production Environment
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
image-uploader-frontend:
|
|
||||||
image: gitea.lan.hobbyhimmel.de/hobbyhimmel/image-uploader-frontend:latest
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
build:
|
|
||||||
context: ./frontend
|
|
||||||
dockerfile: ./Dockerfile
|
|
||||||
depends_on:
|
|
||||||
- "image-uploader-backend"
|
|
||||||
environment:
|
|
||||||
- "API_URL=http://image-uploader-backend:5000"
|
|
||||||
- "CLIENT_URL=http://localhost"
|
|
||||||
container_name: "image-uploader-frontend"
|
|
||||||
networks:
|
|
||||||
- npm-nw
|
|
||||||
- image-uploader-internal
|
|
||||||
|
|
||||||
image-uploader-backend:
|
|
||||||
image: gitea.lan.hobbyhimmel.de/hobbyhimmel/image-uploader-backend:latest
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
build:
|
|
||||||
context: ./backend
|
|
||||||
dockerfile: ./Dockerfile
|
|
||||||
container_name: "image-uploader-backend"
|
|
||||||
networks:
|
|
||||||
- image-uploader-internal
|
|
||||||
volumes:
|
|
||||||
- app-data:/usr/src/app/src/data
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
app-data:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
networks:
|
|
||||||
npm-nw:
|
|
||||||
external: true
|
|
||||||
image-uploader-internal:
|
|
||||||
driver: bridge
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Start the application**:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up -d
|
# Start production environment
|
||||||
|
./prod.sh
|
||||||
|
|
||||||
|
# Or manually:
|
||||||
|
docker compose -f docker/prod/docker-compose.yml up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Development Environment
|
||||||
|
|
||||||
3. **Access the application**:
|
```bash
|
||||||
|
# Start development environment
|
||||||
|
./dev.sh
|
||||||
|
|
||||||
|
# Or manually:
|
||||||
|
docker compose -f docker/dev/docker-compose.yml up -d
|
||||||
|
### Access URLs
|
||||||
|
|
||||||
|
#### Production (Port 80):
|
||||||
- Upload Interface: `http://localhost`
|
- Upload Interface: `http://localhost`
|
||||||
- Backend: `http://localhost:5000`
|
|
||||||
- Slideshow Mode: `http://localhost/slideshow`
|
- Slideshow Mode: `http://localhost/slideshow`
|
||||||
|
- Groups Overview: `http://localhost/groups`
|
||||||
|
- Admin Panel: `http://localhost/moderation` (requires authentication)
|
||||||
|
|
||||||
|
#### Development (Port 3000):
|
||||||
|
- Upload Interface: `http://localhost:3000`
|
||||||
|
- Backend API: `http://localhost:5001`
|
||||||
|
- Slideshow Mode: `http://localhost:3000/slideshow`
|
||||||
|
|
||||||
### Multi-Image Upload
|
### Multi-Image Upload
|
||||||
|
|
||||||
|
|
@ -166,6 +139,44 @@ The application automatically generates optimized preview thumbnails for all upl
|
||||||
- View group statistics and metadata
|
- View group statistics and metadata
|
||||||
|
|
||||||
|
|
||||||
|
## Docker Structure
|
||||||
|
|
||||||
|
The application uses separate Docker configurations for development and production:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker/
|
||||||
|
├── .env.backend.example # Backend environment variables documentation
|
||||||
|
├── .env.frontend.example # Frontend environment variables documentation
|
||||||
|
├── dev/ # Development environment
|
||||||
|
│ ├── docker-compose.yml # Development services configuration
|
||||||
|
│ ├── backend/
|
||||||
|
│ │ ├── config/.env # Development backend configuration
|
||||||
|
│ │ └── Dockerfile # Development backend container
|
||||||
|
│ └── frontend/
|
||||||
|
│ ├── config/.env # Development frontend configuration
|
||||||
|
│ ├── config/env.sh # Runtime configuration script
|
||||||
|
│ ├── Dockerfile # Development frontend container
|
||||||
|
│ ├── nginx.conf # Development nginx configuration
|
||||||
|
│ └── start.sh # Development startup script
|
||||||
|
└── prod/ # Production environment
|
||||||
|
├── docker-compose.yml # Production services configuration
|
||||||
|
├── backend/
|
||||||
|
│ ├── config/.env # Production backend configuration
|
||||||
|
│ └── Dockerfile # Production backend container
|
||||||
|
└── frontend/
|
||||||
|
├── config/.env # Production frontend configuration
|
||||||
|
├── config/env.sh # Runtime configuration script
|
||||||
|
├── config/htpasswd # HTTP Basic Auth credentials
|
||||||
|
├── Dockerfile # Production frontend container
|
||||||
|
└── nginx.conf # Production nginx configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Configuration
|
||||||
|
|
||||||
|
- **Development**: Uses `docker/dev/` configuration with live reloading
|
||||||
|
- **Production**: Uses `docker/prod/` configuration with optimized builds
|
||||||
|
- **Scripts**: Use `./dev.sh` or `./prod.sh` for easy deployment
|
||||||
|
|
||||||
## Data Structure
|
## Data Structure
|
||||||
|
|
||||||
Data are stored in sqlite database. The structure is as follows:
|
Data are stored in sqlite database. The structure is as follows:
|
||||||
|
|
|
||||||
|
|
@ -1 +1,15 @@
|
||||||
REMOVE_IMAGES=<boolean | undefined>
|
# Backend Environment Variables
|
||||||
|
# Copy this file to .env and adjust values for local development
|
||||||
|
|
||||||
|
# Whether to remove images when starting the server (cleanup)
|
||||||
|
REMOVE_IMAGES=false
|
||||||
|
|
||||||
|
# Node.js environment (development, production, test)
|
||||||
|
NODE_ENV=development
|
||||||
|
|
||||||
|
# Port for the backend server
|
||||||
|
PORT=5000
|
||||||
|
|
||||||
|
# Database settings (if needed in future)
|
||||||
|
# DB_HOST=localhost
|
||||||
|
# DB_PORT=3306
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
FROM node:24
|
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
|
||||||
|
|
||||||
# Note: Node 24 LTS (v24.11.0) uses Debian Bookworm
|
|
||||||
|
|
||||||
# Install sqlite3 CLI
|
|
||||||
RUN apt-get update && apt-get install -y sqlite3 && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
COPY package*.json ./
|
|
||||||
|
|
||||||
# Development
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
# Production
|
|
||||||
# RUN npm ci --only=production
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
EXPOSE 5000
|
|
||||||
CMD [ "node", "src/index.js" ]
|
|
||||||
40
dev.sh
Executable file
40
dev.sh
Executable file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Development Environment Startup Script
|
||||||
|
# Starts the Project Image Uploader in development mode
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "🚀 Starting Project Image Uploader - Development Environment"
|
||||||
|
echo " Frontend: http://localhost:3000"
|
||||||
|
echo " Backend: http://localhost:5001"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if production is running
|
||||||
|
if docker compose ps | grep -q "image-uploader-frontend.*Up"; then
|
||||||
|
echo "⚠️ Production environment is running (Port 80)"
|
||||||
|
echo " Development will run on Port 3000 (no conflict)"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start development environment
|
||||||
|
echo "📦 Starting development containers..."
|
||||||
|
docker compose -f docker/dev/docker-compose.yml up -d
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Development environment started!"
|
||||||
|
echo ""
|
||||||
|
echo "📊 Container Status:"
|
||||||
|
docker compose -f docker/dev/docker-compose.yml ps
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔗 Access URLs:"
|
||||||
|
echo " 📱 Frontend (Development): http://localhost:3000"
|
||||||
|
echo " 🔧 Backend API (Development): http://localhost:5001"
|
||||||
|
echo ""
|
||||||
|
echo "📝 Useful Commands:"
|
||||||
|
echo " 📋 Show logs: docker compose -f docker/dev/docker-compose.yml logs -f"
|
||||||
|
echo " 🛑 Stop: docker compose -f docker/dev/docker-compose.yml down"
|
||||||
|
echo " 🔄 Restart: docker compose -f docker/dev/docker-compose.yml restart"
|
||||||
|
echo " 🏗️ Rebuild: docker compose -f docker/dev/docker-compose.yml build --no-cache"
|
||||||
|
echo ""
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
# Development override to mount the frontend source into a node container
|
|
||||||
# and run the React dev server with HMR so you can edit files locally
|
|
||||||
# without rebuilding images. This file is intended to be used together
|
|
||||||
# with the existing docker-compose.yml from the repository.
|
|
||||||
|
|
||||||
services:
|
|
||||||
image-uploader-frontend:
|
|
||||||
container_name: image-uploader-frontend-dev
|
|
||||||
# For dev convenience nginx needs to be able to bind to port 80 and write the pid file
|
|
||||||
# and we also adjust file permissions on bind-mounted node_modules; run as root in dev.
|
|
||||||
user: root
|
|
||||||
# Build and run a development image that contains both nginx and the
|
|
||||||
# React dev server. nginx will act as a reverse proxy to the dev server
|
|
||||||
# so the app behaves more like production while HMR still works.
|
|
||||||
build:
|
|
||||||
context: ./frontend
|
|
||||||
dockerfile: Dockerfile.dev
|
|
||||||
working_dir: /app
|
|
||||||
# Map host port 3000 to the nginx listener (container:80) so you can open
|
|
||||||
# http://localhost:3000 and see the nginx-served dev site.
|
|
||||||
ports:
|
|
||||||
- "3000:80"
|
|
||||||
volumes:
|
|
||||||
- ./frontend:/app:cached
|
|
||||||
# Keep container node_modules separate so host node_modules doesn't conflict
|
|
||||||
- node_modules:/app/node_modules
|
|
||||||
environment:
|
|
||||||
# Use the backend service name so the dev frontend (running in the same
|
|
||||||
# compose project) can reach the backend via the internal docker network.
|
|
||||||
- CHOKIDAR_USEPOLLING=true
|
|
||||||
- HOST=0.0.0.0
|
|
||||||
- API_URL=http://image-uploader-backend:5000
|
|
||||||
- CLIENT_URL=http://localhost:3000
|
|
||||||
networks:
|
|
||||||
- npm-nw
|
|
||||||
- image-uploader-internal
|
|
||||||
depends_on:
|
|
||||||
- image-uploader-backend
|
|
||||||
image-uploader-backend:
|
|
||||||
container_name: image-uploader-backend-dev
|
|
||||||
build:
|
|
||||||
context: ./backend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
working_dir: /usr/src/app
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
volumes:
|
|
||||||
- ./backend:/usr/src/app:cached
|
|
||||||
- backend_node_modules:/usr/src/app/node_modules
|
|
||||||
environment:
|
|
||||||
- NODE_ENV=development
|
|
||||||
networks:
|
|
||||||
- image-uploader-internal
|
|
||||||
command: [ "npm", "run", "server" ]
|
|
||||||
# The Dockerfile.dev provides a proper CMD that starts nginx and the
|
|
||||||
# react dev server; no ad-hoc command is required here.
|
|
||||||
|
|
||||||
networks:
|
|
||||||
npm-nw:
|
|
||||||
external: true
|
|
||||||
image-uploader-internal:
|
|
||||||
driver: bridge
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
node_modules:
|
|
||||||
driver: local
|
|
||||||
backend_node_modules:
|
|
||||||
driver: local
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
services:
|
|
||||||
image-uploader-frontend:
|
|
||||||
image: gitea.lan.hobbyhimmel.de/hobbyhimmel/image-uploader-frontend:latest
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
build:
|
|
||||||
context: ./frontend
|
|
||||||
dockerfile: ./Dockerfile
|
|
||||||
depends_on:
|
|
||||||
- "image-uploader-backend"
|
|
||||||
environment:
|
|
||||||
- "API_URL=http://image-uploader-backend:5000"
|
|
||||||
- "CLIENT_URL=http://localhost"
|
|
||||||
container_name: "image-uploader-frontend"
|
|
||||||
networks:
|
|
||||||
- npm-nw
|
|
||||||
- image-uploader-internal
|
|
||||||
|
|
||||||
image-uploader-backend:
|
|
||||||
image: gitea.lan.hobbyhimmel.de/hobbyhimmel/image-uploader-backend:latest
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
build:
|
|
||||||
context: ./backend
|
|
||||||
dockerfile: ./Dockerfile
|
|
||||||
container_name: "image-uploader-backend"
|
|
||||||
networks:
|
|
||||||
- image-uploader-internal
|
|
||||||
volumes:
|
|
||||||
- app-data:/usr/src/app/src/data
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
app-data:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
networks:
|
|
||||||
npm-nw:
|
|
||||||
external: true
|
|
||||||
image-uploader-internal:
|
|
||||||
driver: bridge
|
|
||||||
15
docker/.env.backend.example
Normal file
15
docker/.env.backend.example
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Backend Environment Variables
|
||||||
|
# Copy this file to .env and adjust values for local development
|
||||||
|
|
||||||
|
# Whether to remove images when starting the server (cleanup)
|
||||||
|
REMOVE_IMAGES=false
|
||||||
|
|
||||||
|
# Node.js environment (development, production, test)
|
||||||
|
NODE_ENV=development
|
||||||
|
|
||||||
|
# Port for the backend server
|
||||||
|
PORT=5000
|
||||||
|
|
||||||
|
# Database settings (if needed in future)
|
||||||
|
# DB_HOST=localhost
|
||||||
|
# DB_PORT=3306
|
||||||
12
docker/.env.frontend.example
Normal file
12
docker/.env.frontend.example
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Frontend Environment Variables
|
||||||
|
# These variables are used in both development and production containers
|
||||||
|
|
||||||
|
# Backend API URL - where the frontend should connect to the backend
|
||||||
|
# Development: http://backend-dev:5000 (container-to-container)
|
||||||
|
# Production: http://backend:5000 (container-to-container)
|
||||||
|
API_URL=http://backend:5000
|
||||||
|
|
||||||
|
# Client URL - the URL where users access the frontend
|
||||||
|
# Development: http://localhost:3000 (dev server)
|
||||||
|
# Production: http://localhost (nginx on port 80)
|
||||||
|
CLIENT_URL=http://localhost
|
||||||
22
docker/dev/backend/Dockerfile
Normal file
22
docker/dev/backend/Dockerfile
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
FROM node:24
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Install SQLite for database operations
|
||||||
|
RUN apt-get update && apt-get install -y sqlite3 && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copy package files and install dependencies
|
||||||
|
COPY backend/package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copy backend source code
|
||||||
|
COPY backend/ .
|
||||||
|
|
||||||
|
# Copy development environment configuration
|
||||||
|
COPY docker/dev/backend/config/.env ./.env
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
# Development command (will be overridden by docker-compose)
|
||||||
|
CMD ["npm", "run", "server"]
|
||||||
52
docker/dev/docker-compose.yml
Normal file
52
docker/dev/docker-compose.yml
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Development Environment
|
||||||
|
# Usage: docker compose -f docker/dev/docker-compose.yml up -d
|
||||||
|
# Or use: ./dev.sh
|
||||||
|
|
||||||
|
services:
|
||||||
|
frontend-dev:
|
||||||
|
container_name: image-uploader-frontend-dev
|
||||||
|
user: root
|
||||||
|
build:
|
||||||
|
context: ../../
|
||||||
|
dockerfile: docker/dev/frontend/Dockerfile
|
||||||
|
working_dir: /app
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
volumes:
|
||||||
|
- ../../frontend:/app:cached
|
||||||
|
- dev_frontend_node_modules:/app/node_modules
|
||||||
|
environment:
|
||||||
|
- CHOKIDAR_USEPOLLING=true
|
||||||
|
- API_URL=http://backend-dev:5000
|
||||||
|
- CLIENT_URL=http://localhost:3000
|
||||||
|
depends_on:
|
||||||
|
- backend-dev
|
||||||
|
networks:
|
||||||
|
- dev-internal
|
||||||
|
|
||||||
|
backend-dev:
|
||||||
|
container_name: image-uploader-backend-dev
|
||||||
|
build:
|
||||||
|
context: ../../
|
||||||
|
dockerfile: docker/dev/backend/Dockerfile
|
||||||
|
working_dir: /usr/src/app
|
||||||
|
ports:
|
||||||
|
- "5001:5000"
|
||||||
|
volumes:
|
||||||
|
- ../../backend:/usr/src/app:cached
|
||||||
|
- dev_backend_node_modules:/usr/src/app/node_modules
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=development
|
||||||
|
networks:
|
||||||
|
- dev-internal
|
||||||
|
command: [ "npm", "run", "server" ]
|
||||||
|
|
||||||
|
networks:
|
||||||
|
dev-internal:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
dev_frontend_node_modules:
|
||||||
|
driver: local
|
||||||
|
dev_backend_node_modules:
|
||||||
|
driver: local
|
||||||
|
|
@ -11,9 +11,12 @@ RUN useradd -m appuser || true
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy package files first to leverage Docker cache for npm install
|
# Copy package files first to leverage Docker cache for npm install
|
||||||
COPY package*.json ./
|
COPY frontend/package*.json ./
|
||||||
COPY env.sh ./
|
COPY docker/dev/frontend/config/env.sh ./
|
||||||
COPY nginx.dev.conf /etc/nginx/conf.d/default.conf
|
COPY docker/dev/frontend/config/.env ./
|
||||||
|
|
||||||
|
# Copy nginx configuration for development
|
||||||
|
COPY docker/dev/frontend/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
# Make /app owned by the non-root user, then run npm as that user so
|
# Make /app owned by the non-root user, then run npm as that user so
|
||||||
# node_modules are created with the correct owner and we avoid an expensive
|
# node_modules are created with the correct owner and we avoid an expensive
|
||||||
|
|
@ -27,8 +30,8 @@ RUN npm ci --no-audit --no-fund
|
||||||
|
|
||||||
# Switch back to root to add the start script and adjust nginx paths
|
# Switch back to root to add the start script and adjust nginx paths
|
||||||
USER root
|
USER root
|
||||||
COPY start-dev.sh /start-dev.sh
|
COPY docker/dev/frontend/start.sh /start.sh
|
||||||
RUN chmod +x /start-dev.sh
|
RUN chmod +x /start.sh
|
||||||
|
|
||||||
# Ensure nginx log/lib dirs are writable by the app user (small set)
|
# Ensure nginx log/lib dirs are writable by the app user (small set)
|
||||||
RUN chown -R appuser:appuser /var/lib/nginx /var/log/nginx || true
|
RUN chown -R appuser:appuser /var/lib/nginx /var/log/nginx || true
|
||||||
|
|
@ -39,4 +42,4 @@ USER appuser
|
||||||
|
|
||||||
EXPOSE 80 3000
|
EXPOSE 80 3000
|
||||||
|
|
||||||
CMD ["/start-dev.sh"]
|
CMD ["/start.sh"]
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
|
client_max_body_size 200M;
|
||||||
|
|
||||||
# API proxy to backend - must come before / location
|
# API proxy to development backend
|
||||||
# Upload endpoint
|
# Upload endpoint
|
||||||
location /api/upload {
|
location /api/upload {
|
||||||
proxy_pass http://image-uploader-backend:5000/upload;
|
proxy_pass http://backend-dev:5000/upload;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
@ -15,7 +16,7 @@ server {
|
||||||
|
|
||||||
# Download original images
|
# Download original images
|
||||||
location /api/download {
|
location /api/download {
|
||||||
proxy_pass http://image-uploader-backend:5000/download;
|
proxy_pass http://backend-dev:5000/download;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
@ -24,7 +25,7 @@ server {
|
||||||
|
|
||||||
# Preview/thumbnail images (optimized for gallery views)
|
# Preview/thumbnail images (optimized for gallery views)
|
||||||
location /api/previews {
|
location /api/previews {
|
||||||
proxy_pass http://image-uploader-backend:5000/previews;
|
proxy_pass http://backend-dev:5000/previews;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
@ -33,57 +34,51 @@ server {
|
||||||
|
|
||||||
# Groups API
|
# Groups API
|
||||||
location /api/groups {
|
location /api/groups {
|
||||||
proxy_pass http://image-uploader-backend:5000/groups;
|
proxy_pass http://backend-dev:5000/groups;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Moderation API (groups)
|
# Moderation Groups API
|
||||||
location /moderation/groups {
|
location /moderation/groups {
|
||||||
proxy_pass http://image-uploader-backend:5000/moderation/groups;
|
proxy_pass http://backend-dev:5000/moderation/groups;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Groups routes (both API and page routes)
|
# Groups dynamic routes
|
||||||
location /groups {
|
location ~ ^/groups/[a-zA-Z0-9_-]+(/.*)?$ {
|
||||||
# Try to serve as static file first, then proxy to React dev server
|
proxy_pass http://backend-dev:5000;
|
||||||
try_files $uri @proxy;
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Download endpoint (legacy, without /api prefix)
|
# Moderation routes
|
||||||
|
location /moderation {
|
||||||
|
proxy_pass http://backend-dev:5000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Legacy download endpoint (backwards compatibility)
|
||||||
location /download {
|
location /download {
|
||||||
proxy_pass http://image-uploader-backend:5000/download;
|
proxy_pass http://backend-dev:5000/download;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Proxy requests to the CRA dev server so nginx can be used as reverse proxy
|
# WebSocket support for hot reloading (React Dev Server)
|
||||||
location /sockjs-node/ {
|
location /ws {
|
||||||
proxy_pass http://127.0.0.1:3000;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "Upgrade";
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /sockjs-node {
|
|
||||||
proxy_pass http://127.0.0.1:3000;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "Upgrade";
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
}
|
|
||||||
|
|
||||||
location @proxy {
|
|
||||||
proxy_pass http://127.0.0.1:3000;
|
proxy_pass http://127.0.0.1:3000;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
|
@ -93,6 +88,7 @@ server {
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# All other requests go to React Dev Server for Hot Module Reloading
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://127.0.0.1:3000;
|
proxy_pass http://127.0.0.1:3000;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
|
|
@ -102,10 +98,4 @@ server {
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
}
|
}
|
||||||
|
|
||||||
# If a production build exists, serve static files directly for speed.
|
|
||||||
location /static/ {
|
|
||||||
alias /app/build/static/;
|
|
||||||
try_files $uri $uri/ =404;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
26
docker/dev/frontend/start.sh
Normal file
26
docker/dev/frontend/start.sh
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Make public writable so env.sh can write env-config.js
|
||||||
|
chmod -R a+rw ./public || true
|
||||||
|
|
||||||
|
# Run env.sh if present
|
||||||
|
if [ -x ./env.sh ]; then
|
||||||
|
./env.sh || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure node cache exists and is writable
|
||||||
|
mkdir -p /app/node_modules/.cache || true
|
||||||
|
chmod -R a+rw /app/node_modules || true
|
||||||
|
|
||||||
|
# Ensure HOST is set so CRA binds to 0.0.0.0
|
||||||
|
export HOST=${HOST:-0.0.0.0}
|
||||||
|
|
||||||
|
echo "🚀 Starting React development server..."
|
||||||
|
# Start the React development server in background
|
||||||
|
npm run dev &
|
||||||
|
DEV_PID=$!
|
||||||
|
|
||||||
|
echo "🌐 Starting nginx proxy..."
|
||||||
|
# Start nginx in foreground so container stays alive; nginx will proxy to the dev server
|
||||||
|
exec nginx -g 'daemon off;'
|
||||||
24
docker/prod/backend/Dockerfile
Normal file
24
docker/prod/backend/Dockerfile
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
FROM node:24-alpine
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Copy package.json and package-lock.json (if available)
|
||||||
|
COPY backend/package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm install --production
|
||||||
|
|
||||||
|
# Copy the source code
|
||||||
|
COPY backend/src ./src
|
||||||
|
|
||||||
|
# Copy production environment configuration
|
||||||
|
COPY docker/prod/backend/config/.env ./.env
|
||||||
|
|
||||||
|
# Create data directories for file storage
|
||||||
|
RUN mkdir -p src/data/images src/data/previews src/data/groups
|
||||||
|
|
||||||
|
# Expose port 5000
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
CMD ["node", "src/index.js"]
|
||||||
46
docker/prod/docker-compose.yml
Normal file
46
docker/prod/docker-compose.yml
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Production Environment
|
||||||
|
# Usage: docker compose -f docker/prod/docker-compose.yml up -d
|
||||||
|
# Or use: ./prod.sh
|
||||||
|
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
container_name: image-uploader-frontend
|
||||||
|
image: gitea.lan.hobbyhimmel.de/hobbyhimmel/image-uploader-frontend:latest
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
build:
|
||||||
|
context: ../../
|
||||||
|
dockerfile: docker/prod/frontend/Dockerfile
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
environment:
|
||||||
|
- API_URL=http://backend:5000
|
||||||
|
- CLIENT_URL=http://localhost
|
||||||
|
networks:
|
||||||
|
- npm-nw
|
||||||
|
- prod-internal
|
||||||
|
|
||||||
|
backend:
|
||||||
|
container_name: image-uploader-backend
|
||||||
|
image: gitea.lan.hobbyhimmel.de/hobbyhimmel/image-uploader-backend:latest
|
||||||
|
build:
|
||||||
|
context: ../../
|
||||||
|
dockerfile: docker/prod/backend/Dockerfile
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
volumes:
|
||||||
|
- image_data:/usr/src/app/src/data
|
||||||
|
networks:
|
||||||
|
- prod-internal
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
|
||||||
|
networks:
|
||||||
|
npm-nw:
|
||||||
|
external: true
|
||||||
|
prod-internal:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
image_data:
|
||||||
|
driver: local
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
# => Build container
|
# => Build container
|
||||||
FROM node:18-alpine AS build
|
FROM node:18-alpine AS build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package.json ./
|
COPY frontend/package.json ./
|
||||||
RUN npm install --silent
|
RUN npm install --silent
|
||||||
COPY . ./
|
COPY frontend/ ./
|
||||||
ENV NODE_OPTIONS=--openssl-legacy-provider
|
ENV NODE_OPTIONS=--openssl-legacy-provider
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
|
|
@ -12,10 +12,11 @@ FROM nginx:stable-alpine
|
||||||
|
|
||||||
# Nginx config
|
# Nginx config
|
||||||
RUN rm -rf /etc/nginx/conf.d
|
RUN rm -rf /etc/nginx/conf.d
|
||||||
COPY conf /etc/nginx
|
COPY docker/prod/frontend/nginx.conf /etc/nginx/nginx.conf
|
||||||
|
COPY frontend/conf /etc/nginx
|
||||||
|
|
||||||
# Copy htpasswd file for authentication
|
# Copy htpasswd file for authentication
|
||||||
COPY htpasswd /etc/nginx/.htpasswd
|
COPY docker/prod/frontend/config/htpasswd /etc/nginx/.htpasswd
|
||||||
|
|
||||||
# Static build
|
# Static build
|
||||||
COPY --from=build /app/build /usr/share/nginx/html
|
COPY --from=build /app/build /usr/share/nginx/html
|
||||||
|
|
@ -25,8 +26,8 @@ EXPOSE 80
|
||||||
|
|
||||||
# Copy .env file and shell script to container
|
# Copy .env file and shell script to container
|
||||||
WORKDIR /usr/share/nginx/html
|
WORKDIR /usr/share/nginx/html
|
||||||
COPY ./env.sh ./
|
COPY docker/prod/frontend/config/env.sh ./
|
||||||
COPY ./.env ./
|
COPY docker/prod/frontend/config/.env ./
|
||||||
|
|
||||||
# Add bash
|
# Add bash
|
||||||
RUN apk add --no-cache bash
|
RUN apk add --no-cache bash
|
||||||
29
docker/prod/frontend/config/env.sh
Executable file
29
docker/prod/frontend/config/env.sh
Executable file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Recreate config file
|
||||||
|
rm -rf ./env-config.js
|
||||||
|
touch ./env-config.js
|
||||||
|
|
||||||
|
# Add assignment
|
||||||
|
echo "window._env_ = {" >> ./env-config.js
|
||||||
|
|
||||||
|
# Read each line in .env file
|
||||||
|
# Each line represents key=value pairs
|
||||||
|
while read -r line || [[ -n "$line" ]];
|
||||||
|
do
|
||||||
|
# Split env variables by character `=`
|
||||||
|
if printf '%s\n' "$line" | grep -q -e '='; then
|
||||||
|
varname=$(printf '%s\n' "$line" | sed -e 's/=.*//')
|
||||||
|
varvalue=$(printf '%s\n' "$line" | sed -e 's/^[^=]*=//')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Read value of current variable if exists as Environment variable
|
||||||
|
value=$(printf '%s\n' "${!varname}")
|
||||||
|
# Otherwise use value from .env file
|
||||||
|
[[ -z $value ]] && value=${varvalue}
|
||||||
|
|
||||||
|
# Append configuration property to JS file
|
||||||
|
echo " $varname: \"$value\"," >> ./env-config.js
|
||||||
|
done < .env
|
||||||
|
|
||||||
|
echo "}" >> ./env-config.js
|
||||||
159
docker/prod/frontend/nginx.conf
Normal file
159
docker/prod/frontend/nginx.conf
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log main;
|
||||||
|
error_log /var/log/nginx/error.log warn;
|
||||||
|
|
||||||
|
# Gzip Settings
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_types
|
||||||
|
text/plain
|
||||||
|
text/css
|
||||||
|
text/xml
|
||||||
|
text/javascript
|
||||||
|
application/json
|
||||||
|
application/javascript
|
||||||
|
application/xml+rss
|
||||||
|
application/atom+xml
|
||||||
|
image/svg+xml;
|
||||||
|
|
||||||
|
# Server Config
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
# Allow large uploads (50MB)
|
||||||
|
client_max_body_size 50M;
|
||||||
|
|
||||||
|
# API proxy to image-uploader-backend service
|
||||||
|
location /upload {
|
||||||
|
proxy_pass http://image-uploader-backend:5000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# Allow large uploads for API too
|
||||||
|
client_max_body_size 50M;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API routes for new multi-upload features
|
||||||
|
location /api/upload {
|
||||||
|
proxy_pass http://image-uploader-backend:5000/upload;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# Allow large uploads for batch upload
|
||||||
|
client_max_body_size 100M;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API - Download original images
|
||||||
|
location /api/download {
|
||||||
|
proxy_pass http://image-uploader-backend:5000/download;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API - Preview/thumbnail images (optimized for gallery views)
|
||||||
|
location /api/previews {
|
||||||
|
proxy_pass http://image-uploader-backend:5000/previews;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API - Groups (NO PASSWORD PROTECTION)
|
||||||
|
location /api/groups {
|
||||||
|
proxy_pass http://image-uploader-backend:5000/groups;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Protected API - Moderation API routes (password protected) - must come before /groups
|
||||||
|
location /moderation/groups {
|
||||||
|
auth_basic "Restricted Area - Moderation API";
|
||||||
|
auth_basic_user_file /etc/nginx/.htpasswd;
|
||||||
|
|
||||||
|
proxy_pass http://image-uploader-backend:5000/moderation/groups;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API - Groups API routes (NO PASSWORD PROTECTION)
|
||||||
|
location ~ ^/groups/[a-zA-Z0-9_-]+(/.*)?$ {
|
||||||
|
proxy_pass http://image-uploader-backend:5000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /download {
|
||||||
|
proxy_pass http://image-uploader-backend:5000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Frontend page - Groups overview (NO PASSWORD PROTECTION)
|
||||||
|
location /groups {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.htm;
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
expires -1;
|
||||||
|
|
||||||
|
# Prevent indexing
|
||||||
|
add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive" always;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Protected routes - Moderation (password protected)
|
||||||
|
location /moderation {
|
||||||
|
auth_basic "Restricted Area - Moderation";
|
||||||
|
auth_basic_user_file /etc/nginx/.htpasswd;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.htm;
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
expires -1;
|
||||||
|
|
||||||
|
# Prevent indexing
|
||||||
|
add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive" always;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Frontend files
|
||||||
|
location / {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.htm;
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
expires -1; # Set it to different value depending on your standard requirements
|
||||||
|
}
|
||||||
|
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
API_URL=http://localhost
|
|
||||||
CLIENT_URL=http://localhost
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
# Allow large uploads (50MB)
|
|
||||||
client_max_body_size 50M;
|
|
||||||
|
|
||||||
# API proxy to image-uploader-backend service
|
|
||||||
location /upload {
|
|
||||||
proxy_pass http://image-uploader-backend:5000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# Allow large uploads for API too
|
|
||||||
client_max_body_size 50M;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API routes for new multi-upload features
|
|
||||||
location /api/upload {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/upload;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# Allow large uploads for batch upload
|
|
||||||
client_max_body_size 100M;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API - Download original images
|
|
||||||
location /api/download {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/download;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API - Preview/thumbnail images (optimized for gallery views)
|
|
||||||
location /api/previews {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/previews;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API - Groups (NO PASSWORD PROTECTION)
|
|
||||||
location /api/groups {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/groups;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Protected API - Moderation API routes (password protected) - must come before /groups
|
|
||||||
location /moderation/groups {
|
|
||||||
auth_basic "Restricted Area - Moderation API";
|
|
||||||
auth_basic_user_file /etc/nginx/.htpasswd;
|
|
||||||
|
|
||||||
proxy_pass http://image-uploader-backend:5000/moderation/groups;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API - Groups API routes (NO PASSWORD PROTECTION)
|
|
||||||
location ~ ^/groups/[a-zA-Z0-9_-]+(/.*)?$ {
|
|
||||||
proxy_pass http://image-uploader-backend:5000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /download {
|
|
||||||
proxy_pass http://image-uploader-backend:5000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Frontend page - Groups overview (NO PASSWORD PROTECTION)
|
|
||||||
location /groups {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
expires -1;
|
|
||||||
|
|
||||||
# Prevent indexing
|
|
||||||
add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive" always;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Protected routes - Moderation (password protected)
|
|
||||||
location /moderation {
|
|
||||||
auth_basic "Restricted Area - Moderation";
|
|
||||||
auth_basic_user_file /etc/nginx/.htpasswd;
|
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
expires -1;
|
|
||||||
|
|
||||||
# Prevent indexing
|
|
||||||
add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive" always;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Frontend files
|
|
||||||
location / {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
expires -1; # Set it to different value depending on your standard requirements
|
|
||||||
}
|
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
|
||||||
location = /50x.html {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
# Allow large uploads (50MB)
|
|
||||||
client_max_body_size 50M;
|
|
||||||
|
|
||||||
# API proxy to image-uploader-backend service
|
|
||||||
location /upload {
|
|
||||||
proxy_pass http://image-uploader-backend:5000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# Allow large uploads for API too
|
|
||||||
client_max_body_size 50M;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API routes for new multi-upload features
|
|
||||||
location /api/upload {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/upload;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# Allow large uploads for batch upload
|
|
||||||
client_max_body_size 100M;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API - Download original images
|
|
||||||
location /api/download {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/download;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API - Preview/thumbnail images (optimized for gallery views)
|
|
||||||
location /api/previews {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/previews;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API - Groups (NO PASSWORD PROTECTION)
|
|
||||||
location /api/groups {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/groups;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Protected API - Moderation API routes (password protected) - must come before /groups
|
|
||||||
location /moderation/groups {
|
|
||||||
auth_basic "Restricted Area - Moderation API";
|
|
||||||
auth_basic_user_file /etc/nginx/.htpasswd;
|
|
||||||
|
|
||||||
proxy_pass http://image-uploader-backend:5000/moderation/groups;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# API - Groups API routes (NO PASSWORD PROTECTION)
|
|
||||||
location ~ ^/groups/[a-zA-Z0-9_-]+(/.*)?$ {
|
|
||||||
proxy_pass http://image-uploader-backend:5000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /download {
|
|
||||||
proxy_pass http://image-uploader-backend:5000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Frontend page - Groups overview (NO PASSWORD PROTECTION)
|
|
||||||
location /groups {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
expires -1;
|
|
||||||
|
|
||||||
# Prevent indexing
|
|
||||||
add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive" always;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Protected routes - Moderation (password protected)
|
|
||||||
location /moderation {
|
|
||||||
auth_basic "Restricted Area - Moderation";
|
|
||||||
auth_basic_user_file /etc/nginx/.htpasswd;
|
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
expires -1;
|
|
||||||
|
|
||||||
# Prevent indexing
|
|
||||||
add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive" always;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Frontend files
|
|
||||||
location / {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
expires -1; # Set it to different value depending on your standard requirements
|
|
||||||
}
|
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
|
||||||
location = /50x.html {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
gzip on;
|
|
||||||
gzip_http_version 1.0;
|
|
||||||
gzip_comp_level 5; # 1-9
|
|
||||||
gzip_min_length 256;
|
|
||||||
gzip_proxied any;
|
|
||||||
gzip_vary on;
|
|
||||||
|
|
||||||
# MIME-types
|
|
||||||
gzip_types
|
|
||||||
application/atom+xml
|
|
||||||
application/javascript
|
|
||||||
application/json
|
|
||||||
application/rss+xml
|
|
||||||
application/vnd.ms-fontobject
|
|
||||||
application/x-font-ttf
|
|
||||||
application/x-web-app-manifest+json
|
|
||||||
application/xhtml+xml
|
|
||||||
application/xml
|
|
||||||
font/opentype
|
|
||||||
image/svg+xml
|
|
||||||
image/x-icon
|
|
||||||
text/css
|
|
||||||
text/plain
|
|
||||||
text/x-component;
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
window._env_ = {
|
|
||||||
API_URL: "http://localhost:5000",
|
|
||||||
CLIENT_URL: "http://localhost",
|
|
||||||
}
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Make public writable so env.sh can write env-config.js
|
|
||||||
chmod -R a+rw ./public || true
|
|
||||||
|
|
||||||
# Run env.sh if present
|
|
||||||
if [ -x ./env.sh ]; then
|
|
||||||
./env.sh || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy nginx config from mounted source if available so dev config can be
|
|
||||||
# edited on the host without rebuilding the image. Priority:
|
|
||||||
# 1) ./conf/conf.d/default.conf (project's conf folder)
|
|
||||||
# 2) ./nginx.dev.conf (bundled with the dev image at build time)
|
|
||||||
if [ -f /app/conf/conf.d/default.conf ]; then
|
|
||||||
echo "Using nginx config from /app/conf/conf.d/default.conf (creating dev variant)"
|
|
||||||
# Backup original
|
|
||||||
cp /app/conf/conf.d/default.conf /app/conf/conf.d/default.conf.backup || true
|
|
||||||
# Write a deterministic dev nginx config that proxies known API routes to
|
|
||||||
# the backend and proxies '/' to the CRA dev server so HMR works through nginx.
|
|
||||||
cat > /etc/nginx/conf.d/default.conf <<'NGINXDEV'
|
|
||||||
server {
|
|
||||||
listen 80 default_server;
|
|
||||||
listen [::]:80 default_server;
|
|
||||||
client_max_body_size 200M;
|
|
||||||
|
|
||||||
location /upload {
|
|
||||||
proxy_pass http://image-uploader-backend:5000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
client_max_body_size 200M;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/upload {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/upload;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
client_max_body_size 200M;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/download {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/download;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/previews {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/previews;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/groups {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/groups;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /moderation/groups {
|
|
||||||
proxy_pass http://image-uploader-backend:5000/moderation/groups;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ ^/groups/[a-zA-Z0-9_-]+(/.*)?$ {
|
|
||||||
proxy_pass http://image-uploader-backend:5000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /download {
|
|
||||||
proxy_pass http://image-uploader-backend:5000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Proxy webpack dev server (supports HMR / WebSocket upgrades)
|
|
||||||
location /sockjs-node/ {
|
|
||||||
proxy_pass http://127.0.0.1:3000;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "Upgrade";
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://127.0.0.1:3000;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "Upgrade";
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
NGINXDEV
|
|
||||||
elif [ -f /app/nginx.dev.conf ]; then
|
|
||||||
echo "Using bundled nginx.dev.conf"
|
|
||||||
cp /app/nginx.dev.conf /etc/nginx/conf.d/default.conf || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ensure node cache exists and is writable
|
|
||||||
mkdir -p /app/node_modules/.cache || true
|
|
||||||
chmod -R a+rw /app/node_modules || true
|
|
||||||
|
|
||||||
# Ensure HOST is set so CRA binds to 0.0.0.0
|
|
||||||
export HOST=${HOST:-0.0.0.0}
|
|
||||||
|
|
||||||
# Start the React development server in background
|
|
||||||
npm run dev &
|
|
||||||
DEV_PID=$!
|
|
||||||
|
|
||||||
# Start nginx in foreground so container stays alive; nginx will proxy to the dev server
|
|
||||||
exec nginx -g 'daemon off;'
|
|
||||||
52
prod.sh
52
prod.sh
|
|
@ -10,14 +10,8 @@ BLUE='\033[0;34m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
NC='\033[0m' # No Color
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
# Image Namen definieren
|
|
||||||
FRONTEND_IMAGE="gitea.lan.hobbyhimmel.de/hobbyhimmel/image-uploader-frontend"
|
|
||||||
BACKEND_IMAGE="gitea.lan.hobbyhimmel.de/hobbyhimmel/image-uploader-backend"
|
|
||||||
VERSION="latest"
|
|
||||||
|
|
||||||
echo -e "${BLUE}=== Image-Uploader Production Environment ===${NC}"
|
echo -e "${BLUE}=== Image-Uploader Production Environment ===${NC}"
|
||||||
echo -e "${BLUE}Frontend Image: ${FRONTEND_IMAGE}:${VERSION}${NC}"
|
echo -e "${BLUE}Using docker/prod/docker-compose.yml${NC}"
|
||||||
echo -e "${BLUE}Backend Image: ${BACKEND_IMAGE}:${VERSION}${NC}"
|
|
||||||
echo
|
echo
|
||||||
|
|
||||||
# Menü anzeigen
|
# Menü anzeigen
|
||||||
|
|
@ -43,84 +37,76 @@ read -p "Deine Wahl (0-13): " choice
|
||||||
case $choice in
|
case $choice in
|
||||||
1)
|
1)
|
||||||
echo -e "${GREEN}Starte Production Container...${NC}"
|
echo -e "${GREEN}Starte Production Container...${NC}"
|
||||||
docker compose -f docker-compose.yml up -d
|
docker compose -f docker/prod/docker-compose.yml up -d
|
||||||
echo -e "${GREEN}Container gestartet!${NC}"
|
echo -e "${GREEN}Container gestartet!${NC}"
|
||||||
echo -e "${BLUE}Frontend: http://localhost${NC}"
|
echo -e "${BLUE}Frontend: http://localhost${NC}"
|
||||||
echo -e "${BLUE}Backend: http://localhost:5000${NC}"
|
echo -e "${BLUE}Backend: http://localhost:5000${NC}"
|
||||||
echo -e "${BLUE}Slideshow: http://localhost/slideshow${NC}"
|
echo -e "${BLUE}Slideshow: http://localhost/slideshow${NC}"
|
||||||
echo -e "${BLUE}Logs verfolgen mit: docker compose -f docker-compose.yml logs -f${NC}"
|
echo -e "${BLUE}Logs verfolgen mit: docker compose -f docker/prod/docker-compose.yml logs -f${NC}"
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
echo -e "${GREEN}Baue Production Images...${NC}"
|
echo -e "${GREEN}Baue Production Images...${NC}"
|
||||||
echo -e "${BLUE}Baue Frontend Image...${NC}"
|
echo -e "${BLUE}Baue mit docker/prod/docker-compose.yml...${NC}"
|
||||||
docker build -t ${FRONTEND_IMAGE}:${VERSION} ./frontend
|
docker compose -f docker/prod/docker-compose.yml build
|
||||||
echo -e "${BLUE}Baue Backend Image...${NC}"
|
|
||||||
docker build -t ${BACKEND_IMAGE}:${VERSION} ./backend
|
|
||||||
echo -e "${GREEN}Production Images erfolgreich gebaut!${NC}"
|
echo -e "${GREEN}Production Images erfolgreich gebaut!${NC}"
|
||||||
;;
|
;;
|
||||||
3)
|
3)
|
||||||
echo -e "${GREEN}Pushe Production Images zur Registry...${NC}"
|
echo -e "${GREEN}Pushe Production Images zur Registry...${NC}"
|
||||||
echo -e "${BLUE}Pushe Frontend Image...${NC}"
|
docker compose -f docker/prod/docker-compose.yml push
|
||||||
docker push ${FRONTEND_IMAGE}:${VERSION}
|
|
||||||
echo -e "${BLUE}Pushe Backend Image...${NC}"
|
|
||||||
docker push ${BACKEND_IMAGE}:${VERSION}
|
|
||||||
echo -e "${GREEN}Production Images erfolgreich gepusht!${NC}"
|
echo -e "${GREEN}Production Images erfolgreich gepusht!${NC}"
|
||||||
;;
|
;;
|
||||||
4)
|
4)
|
||||||
echo -e "${GREEN}Baue Container neu...${NC}"
|
echo -e "${GREEN}Baue Container neu...${NC}"
|
||||||
docker compose -f docker-compose.yml down
|
docker compose -f docker/prod/docker-compose.yml down
|
||||||
docker compose -f docker-compose.yml up --build -d
|
docker compose -f docker/prod/docker-compose.yml up --build -d
|
||||||
echo -e "${GREEN}Container neu gebaut und gestartet!${NC}"
|
echo -e "${GREEN}Container neu gebaut und gestartet!${NC}"
|
||||||
echo -e "${BLUE}Frontend: http://localhost${NC}"
|
echo -e "${BLUE}Frontend: http://localhost${NC}"
|
||||||
echo -e "${BLUE}Slideshow: http://localhost/slideshow${NC}"
|
echo -e "${BLUE}Slideshow: http://localhost/slideshow${NC}"
|
||||||
;;
|
;;
|
||||||
5)
|
5)
|
||||||
echo -e "${YELLOW}Stoppe Container...${NC}"
|
echo -e "${YELLOW}Stoppe Container...${NC}"
|
||||||
docker compose -f docker-compose.yml down
|
docker compose -f docker/prod/docker-compose.yml down
|
||||||
echo -e "${GREEN}Container gestoppt!${NC}"
|
echo -e "${GREEN}Container gestoppt!${NC}"
|
||||||
;;
|
;;
|
||||||
6)
|
6)
|
||||||
echo -e "${GREEN}Öffne Frontend Container Shell...${NC}"
|
echo -e "${GREEN}Öffne Frontend Container Shell...${NC}"
|
||||||
docker compose -f docker-compose.yml exec image-uploader-frontend bash
|
docker compose -f docker/prod/docker-compose.yml exec frontend bash
|
||||||
;;
|
;;
|
||||||
7)
|
7)
|
||||||
echo -e "${GREEN}Öffne Backend Container Shell...${NC}"
|
echo -e "${GREEN}Öffne Backend Container Shell...${NC}"
|
||||||
docker compose -f docker-compose.yml exec image-uploader-backend bash
|
docker compose -f docker/prod/docker-compose.yml exec backend bash
|
||||||
;;
|
;;
|
||||||
8)
|
8)
|
||||||
echo -e "${GREEN}Zeige Frontend Logs...${NC}"
|
echo -e "${GREEN}Zeige Frontend Logs...${NC}"
|
||||||
docker compose -f docker-compose.yml logs -f image-uploader-frontend
|
docker compose -f docker/prod/docker-compose.yml logs -f frontend
|
||||||
;;
|
;;
|
||||||
9)
|
9)
|
||||||
echo -e "${GREEN}Zeige Backend Logs...${NC}"
|
echo -e "${GREEN}Zeige Backend Logs...${NC}"
|
||||||
docker compose -f docker-compose.yml logs -f image-uploader-backend
|
docker compose -f docker/prod/docker-compose.yml logs -f backend
|
||||||
;;
|
;;
|
||||||
10)
|
10)
|
||||||
echo -e "${GREEN}Zeige alle Logs...${NC}"
|
echo -e "${GREEN}Zeige alle Logs...${NC}"
|
||||||
docker compose -f docker-compose.yml logs -f
|
docker compose -f docker/prod/docker-compose.yml logs -f
|
||||||
;;
|
;;
|
||||||
11)
|
11)
|
||||||
echo -e "${GREEN}Container Status:${NC}"
|
echo -e "${GREEN}Container Status:${NC}"
|
||||||
docker compose -f docker-compose.yml ps
|
docker compose -f docker/prod/docker-compose.yml ps
|
||||||
echo
|
echo
|
||||||
echo -e "${BLUE}Detaillierte Informationen:${NC}"
|
echo -e "${BLUE}Detaillierte Informationen:${NC}"
|
||||||
docker images | grep "image-uploader" || echo "Keine lokalen Images gefunden"
|
docker images | grep "image-uploader" || echo "Keine lokalen Images gefunden"
|
||||||
;;
|
;;
|
||||||
12)
|
12)
|
||||||
echo -e "${GREEN}Upload-Verzeichnis Inhalt:${NC}"
|
echo -e "${GREEN}Upload-Verzeichnis Inhalt:${NC}"
|
||||||
if docker compose -f docker-compose.yml ps -q image-uploader-backend > /dev/null 2>&1; then
|
if docker compose -f docker/prod/docker-compose.yml ps -q backend > /dev/null 2>&1; then
|
||||||
echo -e "${BLUE}Hochgeladene Bilder (data/images):${NC}"
|
echo -e "${BLUE}Hochgeladene Bilder (data/images):${NC}"
|
||||||
docker compose -f docker-compose.yml exec image-uploader-backend ls -la /usr/src/app/data/images/ || echo "Upload-Verzeichnis ist leer"
|
docker compose -f docker/prod/docker-compose.yml exec backend ls -la /usr/src/app/src/data/ || echo "Upload-Verzeichnis ist leer"
|
||||||
echo
|
|
||||||
echo -e "${BLUE}JSON Metadaten (data/db):${NC}"
|
|
||||||
docker compose -f docker-compose.yml exec image-uploader-backend ls -la /usr/src/app/data/db/ || echo "Keine Metadaten vorhanden"
|
|
||||||
else
|
else
|
||||||
echo -e "${YELLOW}Backend Container ist nicht gestartet.${NC}"
|
echo -e "${YELLOW}Backend Container ist nicht gestartet.${NC}"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
13)
|
13)
|
||||||
echo -e "${YELLOW}Stoppe und lösche Container inkl. Volumes...${NC}"
|
echo -e "${YELLOW}Stoppe und lösche Container inkl. Volumes...${NC}"
|
||||||
docker compose -f docker-compose.yml down -v
|
docker compose -f docker/prod/docker-compose.yml down -v
|
||||||
echo -e "${GREEN}Container und Volumes gelöscht!${NC}"
|
echo -e "${GREEN}Container und Volumes gelöscht!${NC}"
|
||||||
;;
|
;;
|
||||||
0)
|
0)
|
||||||
|
|
@ -128,7 +114,7 @@ case $choice in
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo -e "${RED}Ungültige Option! Bitte wähle 0-12.${NC}"
|
echo -e "${RED}Ungültige Option! Bitte wähle 0-13.${NC}"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
Loading…
Reference in New Issue
Block a user