project initialization
Some checks failed
System Monitoring / Health Checks (push) Has been cancelled
System Monitoring / Performance Monitoring (push) Has been cancelled
System Monitoring / Database Monitoring (push) Has been cancelled
System Monitoring / Cache Monitoring (push) Has been cancelled
System Monitoring / Log Monitoring (push) Has been cancelled
System Monitoring / Resource Monitoring (push) Has been cancelled
System Monitoring / Uptime Monitoring (push) Has been cancelled
System Monitoring / Backup Monitoring (push) Has been cancelled
System Monitoring / Security Monitoring (push) Has been cancelled
System Monitoring / Monitoring Dashboard (push) Has been cancelled
System Monitoring / Alerting (push) Has been cancelled
Security Scanning / Dependency Scanning (push) Has been cancelled
Security Scanning / Code Security Scanning (push) Has been cancelled
Security Scanning / Secrets Scanning (push) Has been cancelled
Security Scanning / Container Security Scanning (push) Has been cancelled
Security Scanning / Compliance Checking (push) Has been cancelled
Security Scanning / Security Dashboard (push) Has been cancelled
Security Scanning / Security Remediation (push) Has been cancelled

This commit is contained in:
2025-10-05 02:37:33 +08:00
parent 2cbb6d5fa1
commit b3fff546e9
226 changed files with 97805 additions and 35 deletions

347
docker-compose.prod.yml Normal file
View File

@@ -0,0 +1,347 @@
version: '3.8'
services:
# Application Services
backend:
image: ghcr.io/${GITHUB_REPOSITORY:-malaysian-sme-platform}:latest-backend
restart: unless-stopped
environment:
- DEBUG=False
- ENVIRONMENT=production
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
- REDIS_URL=redis://redis:6379/0
- SECRET_KEY=${SECRET_KEY}
- ALLOWED_HOSTS=${ALLOWED_HOSTS}
- CSRF_TRUSTED_ORIGINS=${CSRF_TRUSTED_ORIGINS}
- SENTRY_DSN=${SENTRY_DSN}
- ROLLBAR_ACCESS_TOKEN=${ROLLBAR_ACCESS_TOKEN}
volumes:
- backend_logs:/app/logs
- media_files:/app/media
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health/"]
interval: 30s
timeout: 10s
retries: 3
deploy:
replicas: 3
resources:
limits:
memory: 1G
cpus: '0.5'
reservations:
memory: 512M
cpus: '0.25'
frontend:
image: ghcr.io/${GITHUB_REPOSITORY:-malaysian-sme-platform}:latest-frontend
restart: unless-stopped
environment:
- REACT_APP_API_URL=https://api.malaysian-sme-platform.com
- REACT_APP_ENVIRONMENT=production
- REACT_APP_SENTRY_DSN=${FRONTEND_SENTRY_DSN}
depends_on:
- backend
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/"]
interval: 30s
timeout: 10s
retries: 3
deploy:
replicas: 2
resources:
limits:
memory: 512M
cpus: '0.25'
reservations:
memory: 256M
cpus: '0.1'
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.prod.conf:/etc/nginx/nginx.conf
- ssl_certs:/etc/nginx/ssl
- static_files:/var/www/static
- media_files:/var/www/media
depends_on:
- backend
- frontend
healthcheck:
test: ["CMD", "curl", "-f", "https://localhost/health/"]
interval: 30s
timeout: 10s
retries: 3
# Database Services
postgres:
image: postgres:15
restart: unless-stopped
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_INITDB_ARGS="--auth-host=scram-sha-256"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backups:/backups
- ./scripts:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
memory: 2G
cpus: '1.0'
reservations:
memory: 1G
cpus: '0.5'
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 3s
retries: 3
deploy:
resources:
limits:
memory: 512M
cpus: '0.25'
reservations:
memory: 256M
cpus: '0.1'
# Monitoring and Logging
prometheus:
image: prom/prometheus:latest
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9090/-/healthy"]
interval: 30s
timeout: 10s
retries: 3
grafana:
image: grafana/grafana:latest
restart: unless-stopped
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- grafana_data:/var/lib/grafana
- ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards
- ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources
depends_on:
- prometheus
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
# Logging
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.8.0
restart: unless-stopped
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- xpack.security.enabled=false
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:9200/_cluster/health || exit 1"]
interval: 10s
timeout: 5s
retries: 5
logstash:
image: docker.elastic.co/logstash/logstash:8.8.0
restart: unless-stopped
volumes:
- ./monitoring/logstash/pipeline:/usr/share/logstash/pipeline
depends_on:
- elasticsearch
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9600"]
interval: 30s
timeout: 10s
retries: 3
kibana:
image: docker.elastic.co/kibana/kibana:8.8.0
restart: unless-stopped
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5601/api/status"]
interval: 30s
timeout: 10s
retries: 3
# Security
fail2ban:
image: crazymax/fail2ban:latest
restart: unless-stopped
cap_add:
- NET_ADMIN
- NET_RAW
volumes:
- ./fail2ban:/data
- /var/log:/var/log:ro
- backend_logs:/app/logs:ro
environment:
- F2B_DB_PURGE_AGE=30d
- F2B_LOG_TARGET=/data/fail2ban.log
healthcheck:
test: ["CMD", "fail2ban-client", "ping"]
interval: 30s
timeout: 10s
retries: 3
# Backup Services
backup:
image: alpine:latest
restart: "no"
volumes:
- postgres_data:/data/postgres
- redis_data:/data/redis
- media_files:/data/media
- ./backups:/backups
- ./scripts/backup.sh:/backup.sh
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_S3_BUCKET=${AWS_S3_BUCKET}
- BACKUP_RETENTION_DAYS=30
entrypoint: /bin/sh
command: /backup.sh
# Worker Services
celery:
image: ghcr.io/${GITHUB_REPOSITORY:-malaysian-sme-platform}:latest-backend
restart: unless-stopped
command: celery -A backend worker -l info
environment:
- DEBUG=False
- ENVIRONMENT=production
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
- REDIS_URL=redis://redis:6379/0
- SECRET_KEY=${SECRET_KEY}
volumes:
- backend_logs:/app/logs
- media_files:/app/media
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
deploy:
replicas: 2
resources:
limits:
memory: 512M
cpus: '0.25'
reservations:
memory: 256M
cpus: '0.1'
celery-beat:
image: ghcr.io/${GITHUB_REPOSITORY:-malaysian-sme-platform}:latest-backend
restart: unless-stopped
command: celery -A backend beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler
environment:
- DEBUG=False
- ENVIRONMENT=production
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
- REDIS_URL=redis://redis:6379/0
- SECRET_KEY=${SECRET_KEY}
volumes:
- backend_logs:/app/logs
- media_files:/app/media
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
flower:
image: mher/flower:latest
restart: unless-stopped
environment:
- CELERY_BROKER_URL=redis://redis:6379/0
- FLOWER_PORT=5555
ports:
- "5555:5555"
depends_on:
- redis
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5555/"]
interval: 30s
timeout: 10s
retries: 3
volumes:
postgres_data:
driver: local
redis_data:
driver: local
backend_logs:
driver: local
static_files:
driver: local
media_files:
driver: local
ssl_certs:
driver: local
prometheus_data:
driver: local
grafana_data:
driver: local
elasticsearch_data:
driver: local
networks:
default:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16