- Added helmet for security headers and configured content security policy - Implemented CORS with a whitelist for allowed origins - Introduced express-validator for input validation in API endpoints - Set request size limits to prevent DoS attacks - Added global error handling and 404 response - Updated TypeScript configuration to use node16 module resolution - Improved Docker Compose configuration for security and resource limits - Created a comprehensive .env.example for environment configuration - Implemented automated security scans in CI/CD with Trivy - Added cleanup script for debugging ports - Established a detailed security policy document
151 lines
4.0 KiB
YAML
151 lines
4.0 KiB
YAML
# Docker Compose für Full Stack Application
|
|
# SICHERHEITS-OPTIMIERT für Gitea Actions & Production
|
|
version: "3.8"
|
|
|
|
services:
|
|
app:
|
|
# Automatischer Build aus dem aktuellen Verzeichnis
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
args:
|
|
NODE_ENV: ${NODE_ENV:-production}
|
|
BUILD_VERSION: ${BUILD_VERSION:-latest}
|
|
|
|
# Optional: Image-Name für Registry-Push (für CI/CD)
|
|
# image: ${REGISTRY:-localhost}/${IMAGE_NAME:-fullstack-app}:${TAG:-latest}
|
|
|
|
container_name: ${APP_CONTAINER_NAME:-fullstack-app}
|
|
restart: unless-stopped
|
|
|
|
# Non-root User (UID/GID 1000)
|
|
user: "1000:1000"
|
|
|
|
environment:
|
|
- NODE_ENV=${NODE_ENV:-production}
|
|
# Optional: Nur wenn PostgreSQL verwendet wird
|
|
- DATABASE_URL=${DATABASE_URL:-}
|
|
- JWT_SECRET=${JWT_SECRET}
|
|
|
|
# Security Options
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
cap_drop:
|
|
- ALL
|
|
cap_add:
|
|
- NET_BIND_SERVICE # Erlaubt Binding an Ports < 1024 (falls nötig)
|
|
|
|
# Resource Limits (verhindern DoS)
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '2.0'
|
|
memory: 2G
|
|
reservations:
|
|
cpus: '0.5'
|
|
memory: 512M
|
|
|
|
networks:
|
|
- app-network
|
|
|
|
# Optional: Nur aktivieren wenn PostgreSQL verwendet wird
|
|
# depends_on:
|
|
# postgres:
|
|
# condition: service_healthy
|
|
|
|
ports:
|
|
- "${APP_PORT:-8080}:8080" # Port 8080 für non-root
|
|
|
|
# Volumes für persistente Daten
|
|
volumes:
|
|
- app-data:/data
|
|
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
|
|
# =============================================================================
|
|
# PostgreSQL Service (OPTIONAL)
|
|
# =============================================================================
|
|
# Nur aktivieren wenn PostgreSQL benötigt wird.
|
|
# Für SQLite oder andere Datenbanken kann dieser Service entfernt werden.
|
|
#
|
|
# Um PostgreSQL zu aktivieren:
|
|
# 1. Entferne die Kommentare (#) vor dem gesamten postgres-Service
|
|
# 2. Aktiviere "depends_on" im app-Service (siehe oben)
|
|
# 3. Setze DATABASE_URL in .env
|
|
# =============================================================================
|
|
|
|
# postgres:
|
|
# image: postgres:15-alpine
|
|
# container_name: ${POSTGRES_CONTAINER_NAME:-postgres-db}
|
|
# restart: unless-stopped
|
|
#
|
|
# # Non-root User (postgres verwendet UID 70 standardmäßig)
|
|
# user: "70:70"
|
|
#
|
|
# environment:
|
|
# POSTGRES_DB: ${POSTGRES_DB:-appdb}
|
|
# POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
|
# POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} # MUSS in .env gesetzt werden!
|
|
# POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256" # Sichere Auth
|
|
# POSTGRES_HOST_AUTH_METHOD: scram-sha-256
|
|
#
|
|
# # Security Options
|
|
# security_opt:
|
|
# - no-new-privileges:true
|
|
# cap_drop:
|
|
# - ALL
|
|
# cap_add:
|
|
# - CHOWN
|
|
# - DAC_OVERRIDE
|
|
# - FOWNER
|
|
# - SETGID
|
|
# - SETUID
|
|
#
|
|
# # Resource Limits
|
|
# deploy:
|
|
# resources:
|
|
# limits:
|
|
# cpus: '1.0'
|
|
# memory: 1G
|
|
# reservations:
|
|
# cpus: '0.25'
|
|
# memory: 256M
|
|
#
|
|
# volumes:
|
|
# - postgres_data:/var/lib/postgresql/data
|
|
#
|
|
# networks:
|
|
# - app-network
|
|
#
|
|
# # KEIN Port-Expose nach außen - nur intern erreichbar!
|
|
# # Für lokales Debugging kann der Port freigegeben werden:
|
|
# # ports:
|
|
# # - "${POSTGRES_PORT:-5432}:5432"
|
|
#
|
|
# healthcheck:
|
|
# test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"]
|
|
# interval: 10s
|
|
# timeout: 5s
|
|
# retries: 5
|
|
# start_period: 10s
|
|
|
|
networks:
|
|
app-network:
|
|
driver: bridge
|
|
# Optional: Netzwerk isolieren
|
|
internal: false # Auf 'true' setzen wenn kein Internet-Zugriff nötig
|
|
|
|
volumes:
|
|
# Persistente Daten für die App (z.B. SQLite-Datenbank, Uploads, etc.)
|
|
app-data:
|
|
driver: local
|
|
|
|
# Optional: Nur wenn PostgreSQL verwendet wird
|
|
# postgres_data:
|
|
# driver: local
|