version: '3.7'

# * Global variables
x-logging: &default-logging
  driver: json-file
  options:
    max-size: '200k'
    max-file: '10'

# * Services
services:
  # ** Loadbalancer
  loadbalancer:
    image: '${NGINX_IMAGE}:${NGINX_TAG}'
    container_name: ${COMPOSE_PROJECT_NAME}_nginx
    ports:
      - ${NGINX_PUBLIC_HTTP}:80
      - ${NGINX_PUBLIC_HTTPS}:443
    logging: *default-logging
    depends_on:
      - nexus
    volumes:
      - ./loadbalancer/etc/nginx.conf:/etc/nginx/nginx.conf
      - ./loadbalancer/etc/locations.conf:/etc/nginx/locations.conf
      - ./loadbalancer/etc/nexus-dev.crt:/etc/nginx/nexus-dev.crt
      - ./loadbalancer/etc/nexus-dev.pem:/etc/nginx/nexus-dev.pem

  # ** Redis
  redis:
    image: '${REDIS_IMAGE}:${REDIS_TAG}'
    container_name: ${COMPOSE_PROJECT_NAME}_redis
    ports:
      - ${REDIS_PUBLIC_PORT}:6379
    logging: *default-logging
    entrypoint: redis-server --appendonly yes
    sysctls:
      net.core.somaxconn: '65535'
    volumes:
      - 'redis-data:/data'

  # ** Postgres
  postgres:
    image: '${POSTGRES_IMAGE}:${POSTGRES_TAG}'
    container_name: ${COMPOSE_PROJECT_NAME}_postgres
    ports:
      - ${POSTGRES_PUBLIC_PORT}:5432
    logging: *default-logging
    healthcheck:
      test: ['CMD', 'pg_isready', '-q', '-d', '${POSTGRES_DB}', '-U', '${POSTGRES_USER}']
      timeout: 45s
      interval: 10s
      retries: 10
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - 'postgres-data:/var/lib/postgresql/data'

  # ** Nexus
  nexus:
    image: '${NEXUS_IMAGE}:${NEXUS_TAG}'
    container_name: ${COMPOSE_PROJECT_NAME}_nexus
    ports:
      - '${NEXUS_PUBLIC_PORT}:4004'
    logging: *default-logging
    env_file:
      - nexus.env
    environment:
      NEXUS_REDIS_NODES: redis://redis:6379
      NEXUS_REDIS_USE_CLUSTER: 'false'
      NEXUS_DB_HOST: postgres
      NEXUS_DB_PORT: 5432
      NEXUS_DB_USER: ${POSTGRES_USER}
      NEXUS_DB_PASSWORD: ${POSTGRES_PASSWORD}
      NEXUS_DB_DATABASE: ${POSTGRES_DB}
      NODE_ENV: production
      NEXUS_REDIRECT_PROTOCOL: http://
    healthcheck:
      test: ['CMD-SHELL', 'curl --silent --fail http://localhost:4004/health || exit 1']
      interval: 30s
      timeout: 30s
      retries: 3
    depends_on:
      - redis
      - postgres
    volumes:
      - 'nexus-data:/etc/nexus-api/data'

  # ** Elasticsearch
  elasticsearch:
    image: '${ELASTICSEARCH_IMAGE}:${ELASTIC_RELEASE}'
    container_name: ${COMPOSE_PROJECT_NAME}_elasticsearch
    logging: *default-logging
    environment:
      - cluster.name=nexus-cluster
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - 'ES_JAVA_OPTS=-Xms512m -Xmx512m'
    healthcheck:
      test: ['CMD-SHELL', 'curl --silent --fail http://localhost:9200/_cluster/health || exit 1']
      interval: 30s
      timeout: 30s
      retries: 3
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - es-data:/usr/share/elasticsearch/data
    ports:
      - ${ELASTICSEARCH_PUBLIC_PORT}:9200
      - ${ELASTICSEARCH_CLUSTER_PORT}:9300

  # ** Kibana
  kibana:
    image: '${KIBANA_IMAGE}:${ELASTIC_RELEASE}'
    container_name: ${COMPOSE_PROJECT_NAME}_kibana
    environment:
      - ELASTICSEARCH_URL="http://elasticsearch:9200"
      - SERVER_BASEPATH=/kibana
      - SERVER_REWRITEBASEPATH=true
    ports:
      - ${KIBANA_PUBLIC_PORT}:5601
    healthcheck:
      test: ['CMD-SHELL', 'curl --silent --fail http://localhost:5601/kibana/api/status || exit 1']
      interval: 30s
      timeout: 30s
      retries: 3

  # ** Filebeat
  filebeat:
    image: '${FILEBEAT_IMAGE}:${ELASTIC_RELEASE}'
    container_name: ${COMPOSE_PROJECT_NAME}_filebeat
    logging: *default-logging
    command: ['--strict.perms=false']
    user: root
    restart: on-failure
    depends_on:
      - elasticsearch
      - kibana
    environment:
      - ELASTICSEARCH_HOSTS=elasticsearch:9200
      - KIBANA_HOST=kibana:5601
    volumes:
      - './filebeat/conf/filebeat.docker.yml:/usr/share/filebeat/filebeat.yml:ro'
      - '/var/run/docker.sock:/var/run/docker.sock:ro'
      - '/var/lib/docker/containers/:/var/lib/docker/containers/:ro'

  # ** Prometheus
  prometheus:
    image: '${PROMETHEUS_IMAGE}:${PROMETHEUS_TAG}'
    container_name: ${COMPOSE_PROJECT_NAME}_prometheus
    logging: *default-logging
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
    ports:
      - ${PROMETHEUS_PUBLIC_PORT}:9090
    depends_on:
      - nexus
    volumes:
      - './prometheus/conf:/etc/prometheus/'
      - 'prometheus-data:/prometheus'
  # ** Grafana
  grafana:
    image: '${GRAFANA_IMAGE}:${GRAFANA_TAG}'
    container_name: ${COMPOSE_PROJECT_NAME}_grafana
    logging: *default-logging
    user: '472'
    ports:
      - ${GRAFANA_PUBLIC_PORT}:3000
    environment:
      - GF_USERS_ALLOW_SIGN_UP="${GF_USERS_ALLOW_SIGN_UP}"
      - 'GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s/grafana/'
      - GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD}
    depends_on:
      - prometheus
    volumes:
      - ./grafana/conf/provisioning:/etc/grafana/provisioning/
      - grafana-data:/var/lib/grafana

# * Volumes
volumes:
  postgres-data: {}
  redis-data: {}
  nexus-data: {}
  es-data: {}
  prometheus-data: {}
  grafana-data: {}
