Files
dashboard/DOCKER_SETUP.md
Matthias Hochmeister f09748f4a1 inital
2026-02-23 17:08:58 +01:00

502 lines
10 KiB
Markdown

# Docker Setup Documentation
## Overview
This document describes the production-ready Docker setup for the Feuerwehr Dashboard application, including multi-stage builds, security best practices, and deployment instructions.
## Architecture
The application consists of three Docker containers:
1. **PostgreSQL Database** - postgres:16-alpine
2. **Backend API** - Node.js application (TypeScript compiled to JavaScript)
3. **Frontend** - React SPA served by Nginx
All containers are connected via a Docker bridge network and orchestrated using Docker Compose.
## Files Structure
```
feuerwehr_dashboard/
├── docker-compose.yml # Production orchestration
├── docker-compose.dev.yml # Development orchestration
├── docker-test.sh # Docker build testing script
├── backend/
│ ├── Dockerfile # Multi-stage backend build
│ └── .dockerignore # Backend Docker ignore rules
└── frontend/
├── Dockerfile # Multi-stage frontend build
├── nginx.conf # Nginx configuration for SPA
└── .dockerignore # Frontend Docker ignore rules
```
## Backend Dockerfile
**Location:** `/backend/Dockerfile`
### Features
- **Multi-stage build** - Separate build and production stages
- **Build stage:**
- Based on node:20-alpine
- Installs all dependencies (including devDependencies)
- Compiles TypeScript to JavaScript
- Prunes devDependencies after build
- **Production stage:**
- Based on node:20-alpine
- Installs wget for health checks
- Creates non-root user (nodejs:1001)
- Copies only production node_modules
- Copies compiled JavaScript
- Copies database migrations to dist/
- Runs as non-root user
- Exposes port 3000
- Includes health check
### Build Command
```bash
cd backend
docker build -t feuerwehr-backend:latest .
```
### Image Size
Expected final image size: ~150-200 MB (alpine-based)
### Security Features
- Non-root user execution
- Minimal base image (Alpine Linux)
- Only production dependencies included
- No source code in final image
## Frontend Dockerfile
**Location:** `/frontend/Dockerfile`
### Features
- **Multi-stage build** - Build stage with Node.js + production stage with Nginx
- **Build stage:**
- Based on node:20-alpine
- Installs dependencies
- Runs Vite build
- Accepts build arguments for environment variables
- **Production stage:**
- Based on nginx:alpine
- Installs wget for health checks
- Copies custom nginx.conf
- Copies built static assets
- Configures non-root nginx user
- Exposes port 80
- Includes health check
### Build Command
```bash
cd frontend
docker build \
--build-arg VITE_API_URL=http://localhost:3000 \
--build-arg VITE_APP_NAME="Feuerwehr Dashboard" \
--build-arg VITE_APP_VERSION="1.0.0" \
-t feuerwehr-frontend:latest .
```
### Build Arguments
- `VITE_API_URL` - Backend API URL (default: http://localhost:3000)
- `VITE_APP_NAME` - Application name (default: "Feuerwehr Dashboard")
- `VITE_APP_VERSION` - Application version (default: "1.0.0")
### Image Size
Expected final image size: ~50-80 MB (alpine + static assets)
### Security Features
- Non-root nginx execution
- Minimal base image (Alpine Linux)
- Security headers configured
- No source code in final image
## Nginx Configuration
**Location:** `/frontend/nginx.conf`
### Features
1. **SPA Routing**
- All routes fall back to index.html
- Proper handling of client-side routing
2. **Performance**
- Gzip compression enabled
- Static asset caching (1 year)
- No caching for index.html
3. **Security Headers**
- X-Frame-Options: SAMEORIGIN
- X-Content-Type-Options: nosniff
- X-XSS-Protection: 1; mode=block
- Referrer-Policy: strict-origin-when-cross-origin
4. **Health Check**
- Endpoint: /health
- Returns 200 with "healthy" text
5. **Error Handling**
- 404 errors redirect to index.html
- Custom 50x error page
## Docker Compose
**Location:** `/docker-compose.yml`
### Services
#### PostgreSQL
```yaml
postgres:
image: postgres:16-alpine
ports: 5432:5432
volumes: postgres_data_prod
health_check: pg_isready
restart: unless-stopped
```
#### Backend
```yaml
backend:
build: ./backend
ports: 3000:3000
depends_on: postgres (healthy)
health_check: wget localhost:3000/health
restart: unless-stopped
```
#### Frontend
```yaml
frontend:
build: ./frontend
build_args: VITE_API_URL
ports: 80:80
depends_on: backend (healthy)
health_check: wget localhost:80/health
restart: unless-stopped
```
### Environment Variables
Create a `.env` file based on `.env.example`:
**Required:**
- `POSTGRES_PASSWORD` - Database password
- `JWT_SECRET` - JWT signing secret
**Optional:**
- `POSTGRES_DB` - Database name (default: feuerwehr_prod)
- `POSTGRES_USER` - Database user (default: prod_user)
- `POSTGRES_PORT` - Database port (default: 5432)
- `BACKEND_PORT` - Backend port (default: 3000)
- `FRONTEND_PORT` - Frontend port (default: 80)
- `CORS_ORIGIN` - CORS origin (default: http://localhost:80)
- `VITE_API_URL` - Frontend API URL (default: http://localhost:3000)
### Networks
- `feuerwehr_network` - Bridge network connecting all services
### Volumes
- `postgres_data_prod` - Persistent PostgreSQL data
## Usage
### 1. Test Docker Builds
Run the test script to verify Docker builds work:
```bash
./docker-test.sh
```
This script will:
- Check Docker availability
- Build backend image
- Build frontend image
- Report success/failure
- Optionally cleanup test images
### 2. Configure Environment
Copy and configure environment file:
```bash
cp .env.example .env
# Edit .env and set required variables
```
### 3. Build and Start Services
```bash
# Build and start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Check service status
docker-compose ps
```
### 4. Access Application
- **Frontend:** http://localhost:80
- **Backend API:** http://localhost:3000
- **Database:** localhost:5432
### 5. Stop Services
```bash
# Stop all services
docker-compose down
# Stop and remove volumes
docker-compose down -v
```
## Health Checks
All services include health checks:
### PostgreSQL
- **Command:** `pg_isready -U $USER -d $DB`
- **Interval:** 10s
- **Retries:** 5
### Backend
- **Command:** `wget localhost:3000/health`
- **Interval:** 30s
- **Retries:** 3
- **Start Period:** 40s
### Frontend
- **Command:** `wget localhost:80/health`
- **Interval:** 30s
- **Retries:** 3
- **Start Period:** 30s
## Troubleshooting
### Backend Build Fails
1. Check TypeScript compilation:
```bash
cd backend
npm install
npm run build
```
2. Verify all source files exist
3. Check tsconfig.json configuration
### Frontend Build Fails
1. Check Vite build:
```bash
cd frontend
npm install
npm run build
```
2. Verify all dependencies are installed
3. Check build arguments are correct
### Container Won't Start
1. Check logs:
```bash
docker-compose logs [service-name]
```
2. Verify environment variables in .env
3. Check health check status:
```bash
docker-compose ps
```
### Database Connection Issues
1. Verify DATABASE_URL format:
```
postgresql://user:password@postgres:5432/database
```
2. Check postgres service is healthy:
```bash
docker-compose ps postgres
```
3. Verify network connectivity:
```bash
docker-compose exec backend ping postgres
```
## Security Considerations
### Production Checklist
- [ ] Set strong POSTGRES_PASSWORD
- [ ] Set strong JWT_SECRET (min 32 characters)
- [ ] Use HTTPS in production
- [ ] Configure proper CORS_ORIGIN
- [ ] Enable firewall rules
- [ ] Regular security updates
- [ ] Monitor container logs
- [ ] Backup database regularly
### Image Security
- Alpine Linux base (minimal attack surface)
- Non-root user execution
- No unnecessary packages
- Security headers enabled
- Health checks configured
## Maintenance
### Update Dependencies
```bash
# Rebuild images with latest dependencies
docker-compose build --no-cache
docker-compose up -d
```
### Backup Database
```bash
# Create backup
docker-compose exec postgres pg_dump -U $USER $DB > backup.sql
# Restore backup
docker-compose exec -T postgres psql -U $USER $DB < backup.sql
```
### View Logs
```bash
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f backend
# Last 100 lines
docker-compose logs --tail=100 backend
```
### Restart Services
```bash
# Restart all
docker-compose restart
# Restart specific service
docker-compose restart backend
```
## Performance Optimization
### Build Cache
Docker uses layer caching. To optimize:
1. Copy package files first
2. Install dependencies
3. Copy source code last
This ensures dependency installation is cached.
### Image Size
Current image sizes:
- Backend: ~150-200 MB
- Frontend: ~50-80 MB
- Total: ~200-280 MB
### Resource Limits
Add resource limits in docker-compose.yml:
```yaml
services:
backend:
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
```
## Monitoring
### Container Stats
```bash
docker stats
```
### Health Status
```bash
docker-compose ps
```
### Resource Usage
```bash
docker system df
```
## Production Deployment
### Using Docker Compose
```bash
# On production server
git clone <repository>
cd feuerwehr_dashboard
cp .env.example .env
# Configure .env with production values
docker-compose up -d
```
### Using Container Registry
```bash
# Build and tag images
docker build -t registry.example.com/feuerwehr-backend:v1.0.0 backend/
docker build -t registry.example.com/feuerwehr-frontend:v1.0.0 frontend/
# Push to registry
docker push registry.example.com/feuerwehr-backend:v1.0.0
docker push registry.example.com/feuerwehr-frontend:v1.0.0
# Pull and run on production
docker pull registry.example.com/feuerwehr-backend:v1.0.0
docker pull registry.example.com/feuerwehr-frontend:v1.0.0
docker-compose up -d
```
## Additional Resources
- [Docker Documentation](https://docs.docker.com/)
- [Docker Compose Documentation](https://docs.docker.com/compose/)
- [Nginx Documentation](https://nginx.org/en/docs/)
- [Node.js Best Practices](https://github.com/goldbergyoni/nodebestpractices)