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
347 lines
8.9 KiB
YAML
347 lines
8.9 KiB
YAML
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 |