version: '3.8' # Self-hosted infrastructure — no external dependencies # All services run on-premise or on your own servers services: # === Core Database === postgres: image: postgis/postgis:15-3.3 container_name: iom-postgres environment: POSTGRES_DB: iom POSTGRES_USER: iom POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-iom_s…} volumes: - postgres_data:/var/lib/postgresql/data - ./database/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql ports: - "5432:5432" networks: - iom-network # === Cache & Message Broker === redis: image: redis:7-alpine container_name: iom-redis command: redis-server --appendonly yes volumes: - redis_data:/data ports: - "6379:6379" networks: - iom-network # === Object Storage (S3-compatible) === minio: image: minio/minio:latest container_name: iom-minio command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin} volumes: - minio_data:/data ports: - "9000:9000" - "9001:9001" networks: - iom-network # Create MinIO bucket on startup minio-init: image: minio/mc:latest depends_on: - minio entrypoint: > /bin/sh -c " sleep 10; /usr/bin/mc config host add iom http://minio:9000 ${MINIO_ROOT_USER:-minioadmin} ${MINIO_ROOT_PASSWORD:-minioadmin}; /usr/bin/mc mb iom/iom-images || true; /usr/bin/mc mb iom/iom-exports || true; /usr/bin/mc policy set public iom/iom-images; exit 0; " networks: - iom-network # === Search Engine === elasticsearch: image: elasticsearch:8.11.0 container_name: iom-elasticsearch environment: - discovery.type=single-node - xpack.security.enabled=false - "ES_JAVA_OPTS=-Xms512m -Xmx512m" volumes: - elasticsearch_data:/usr/share/elasticsearch/data ports: - "9200:9200" networks: - iom-network # === Log Aggregation === loki: image: grafana/loki:2.9.0 container_name: iom-loki ports: - "3100:3100" volumes: - ./monitoring/loki-config.yml:/etc/loki/local-config.yaml - loki_data:/loki command: -config.file=/etc/loki/local-config.yaml networks: - iom-network promtail: image: grafana/promtail:2.9.0 container_name: iom-promtail volumes: - /var/log:/var/log:ro - ./monitoring/promtail-config.yml:/etc/promtail/config.yml command: -config.file=/etc/promtail/config.yml networks: - iom-network # === Message Queue (alternative to Redis) === rabbitmq: image: rabbitmq:3.12-management-alpine container_name: iom-rabbitmq environment: RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-iom} RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-iom} volumes: - rabbitmq_data:/var/lib/rabbitmq ports: - "5672:5672" - "15672:15672" networks: - iom-network # === VPN / Mesh Network === headscale: image: headscale/headscale:0.22.3 container_name: iom-headscale command: serve volumes: - ./vpn/headscale-config.yml:/etc/headscale/config.yml - headscale_data:/var/lib/headscale ports: - "8080:8080" networks: - iom-network # === Backup === restic: image: restic/restic:latest container_name: iom-backup environment: RESTIC_REPOSITORY: ${RESTIC_REPOSITORY:-/backups} RESTIC_PASSWORD: ${RESTIC_PASSWORD:-backup_s…} volumes: - restic_data:/backups - postgres_data:/data/postgres:ro - minio_data:/data/minio:ro command: > /bin/sh -c " restic init || true; restic backup /data; restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12; restic prune; " networks: - iom-network # === Container Registry === registry: image: registry:2 container_name: iom-registry environment: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data volumes: - registry_data:/data ports: - "5000:5000" networks: - iom-network # === CI/CD (Jenkins) === jenkins: image: jenkins/jenkins:lts container_name: iom-jenkins environment: JAVA_OPTS: -Djenkins.install.runSetupWizard=false volumes: - jenkins_data:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock ports: - "8081:8080" networks: - iom-network # === API (main application) === api: build: context: . dockerfile: Dockerfile container_name: iom-api environment: DATABASE_URL: postgresql://iom:${POSTGRES_PASSWORD:-iom_s…}@postgres:5432/iom REDIS_URL: redis://redis:6379/0 MINIO_ENDPOINT: minio:9000 MINIO_ACCESS_KEY: ${MINIO_ROOT_USER:-minioadmin} MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-minioadmin} ELASTICSEARCH_URL: http://elasticsearch:9200 RABBITMQ_URL: amqp://${RABBITMQ_USER:-iom}:${RABBITMQ_PASSWORD:-iom}@rabbitmq:5672/ JWT_SECRET: ${JWT_SECRET:-iom_jwt_s…} ENVIRONMENT: ${ENVIRONMENT:-production} LOG_LEVEL: ${LOG_LEVEL:-INFO} ports: - "8000:8000" depends_on: - postgres - redis - minio - elasticsearch networks: - iom-network # === Worker === worker: build: context: . dockerfile: Dockerfile.worker container_name: iom-worker environment: DATABASE_URL: postgresql://iom:${POSTGRES_PASSWORD:-iom_s…}@postgres:5432/iom REDIS_URL: redis://redis:6379/0 CELERY_BROKER_URL: redis://redis:6379/1 CELERY_RESULT_BACKEND: redis://redis:6379/2 MINIO_ENDPOINT: minio:9000 ELASTICSEARCH_URL: http://elasticsearch:9200 depends_on: - redis - postgres networks: - iom-network # === Nginx === nginx: image: nginx:alpine container_name: iom-nginx ports: - "80:80" - "443:443" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/ssl:/etc/nginx/ssl depends_on: - api networks: - iom-network # === Monitoring === prometheus: image: prom/prometheus:latest container_name: iom-prometheus ports: - "9090:9090" volumes: - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus networks: - iom-network grafana: image: grafana/grafana:latest container_name: iom-grafana ports: - "3000:3000" environment: GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin} GF_INSTALL_PLUGINS: grafana-lokiexplore-app volumes: - grafana_data:/var/lib/grafana - ./monitoring/dashboards:/etc/grafana/provisioning/dashboards - ./monitoring/datasources:/etc/grafana/provisioning/datasources networks: - iom-network volumes: postgres_data: redis_data: minio_data: elasticsearch_data: loki_data: rabbitmq_data: headscale_data: restic_data: registry_data: jenkins_data: prometheus_data: grafana_data: networks: iom-network: driver: bridge