---
# Base Docker-composition. For development, this composition is augmented in docker-compose.override.yml.

x-security-opt: &security-opt
  - no-new-privileges:true

# The Nginx-based images render their configuration templates into /etc/nginx/conf.d at startup,
# so that folder needs to be writable for the non-root Nginx user, also with a read-only root filesystem
x-nginx-config-dir: &nginx-config-dir
  - type: tmpfs
    target: /etc/nginx/conf.d
    tmpfs:
      mode: 0o1777

x-tz: &tz TZ=${TZ:-Europe/Amsterdam} # Timezone for log timestamps and date formatting; installed in each image

services:
  www:
    image: ictu/quality-time_proxy:${QUALITY_TIME_VERSION}
    ports:
      - "80:${PROXY_PORT:-80}"
    environment:
      - *tz
      - PROXY_PORT=${PROXY_PORT:-80}
      - FRONTEND_HOST=${FRONTEND_HOST:-frontend}
      - FRONTEND_PORT=${FRONTEND_PORT:-5000}
      - API_SERVER_HOST=${API_SERVER_HOST:-api_server}
      - API_SERVER_PORT=${API_SERVER_PORT:-5001}
    depends_on:
      - api_server
      - frontend
    cap_drop:
      - ALL
    cap_add:
      # Nginx binary has CAP_NET_BIND_SERVICE via setcap (see components/proxy/Dockerfile)
      # so it can listen on port 80 as non-root
      - NET_BIND_SERVICE
    security_opt: *security-opt
    read_only: true
    tmpfs:
      - /tmp # Nginx writes its pid file and temporary files to /tmp
    volumes: *nginx-config-dir
  frontend:
    image: ictu/quality-time_frontend:${QUALITY_TIME_VERSION}
    environment:
      - *tz
      - FRONTEND_PORT=${FRONTEND_PORT:-5000}
    depends_on:
      - api_server
    cap_drop:
      - ALL
    security_opt: *security-opt
    read_only: true
    tmpfs:
      - /tmp # Nginx writes its pid file and temporary files to /tmp
    volumes: *nginx-config-dir
  collector:
    image: ictu/quality-time_collector:${QUALITY_TIME_VERSION}
    environment:
      - *tz
      - DATABASE_USERNAME_FILE=/run/secrets/database_username
      - DATABASE_PASSWORD_FILE=/run/secrets/database_password
      - DATABASE_HOST=${DATABASE_HOST:-database}
      - DATABASE_PORT=${DATABASE_PORT:-27017}
      - COLLECTOR_MEASUREMENT_FREQUENCY=${COLLECTOR_MEASUREMENT_FREQUENCY:-900}
      - COLLECTOR_MEASUREMENT_LIMIT=${COLLECTOR_MEASUREMENT_LIMIT:-30}
      - COLLECTOR_MEASUREMENT_TIMEOUT=${COLLECTOR_MEASUREMENT_TIMEOUT:-120}
      - COLLECTOR_SLEEP_DURATION=${COLLECTOR_SLEEP_DURATION:-20}
      - COLLECTOR_LOG_LEVEL=${COLLECTOR_LOG_LEVEL:-WARNING}
      - COLUMNS=${COLUMNS} # Tell the Rich logging handler the terminal width
    secrets:
      - database_username
      - database_password
    depends_on:
      - database
    cap_drop:
      - ALL
    security_opt: *security-opt
    read_only: true
    tmpfs:
      - /tmp # The collector writes its health check file to /tmp
  notifier:
    image: ictu/quality-time_notifier:${QUALITY_TIME_VERSION}
    environment:
      - *tz
      - DATABASE_USERNAME_FILE=/run/secrets/database_username
      - DATABASE_PASSWORD_FILE=/run/secrets/database_password
      - DATABASE_HOST=${DATABASE_HOST:-database}
      - DATABASE_PORT=${DATABASE_PORT:-27017}
      - NOTIFIER_SLEEP_DURATION=${NOTIFIER_SLEEP_DURATION:-60}
      - NOTIFIER_LOG_LEVEL=${NOTIFIER_LOG_LEVEL:-WARNING}
      - COLUMNS=${COLUMNS} # Tell the Rich logging handler the terminal width
    secrets:
      - database_username
      - database_password
    depends_on:
      - database
    cap_drop:
      - ALL
    security_opt: *security-opt
    read_only: true
    tmpfs:
      - /tmp # The notifier writes its health check file to /tmp
  api_server:
    image: ictu/quality-time_api_server:${QUALITY_TIME_VERSION}
    environment:
      - *tz
      - API_SERVER_PORT=${API_SERVER_PORT:-5001}
      - API_SERVER_LOG_LEVEL=${API_SERVER_LOG_LEVEL:-WARNING}
      - DATABASE_USERNAME_FILE=/run/secrets/database_username
      - DATABASE_PASSWORD_FILE=/run/secrets/database_password
      - DATABASE_HOST=${DATABASE_HOST:-database}
      - DATABASE_PORT=${DATABASE_PORT:-27017}
      - LDAP_URL=${LDAP_URL:-ldap://ldap:389}
      - LDAP_ROOT_DN=${LDAP_ROOT_DN:-dc=example,dc=org}
      - LDAP_LOOKUP_USER_DN=${LDAP_LOOKUP_USER_DN:-cn=admin,dc=example,dc=org}
      - LDAP_LOOKUP_USER_PASSWORD=${LDAP_LOOKUP_USER_PASSWORD:-admin}
      - LDAP_SEARCH_FILTER=${LDAP_SEARCH_FILTER:-(|(uid=$$username)(cn=$$username))}
      - LOAD_EXAMPLE_REPORTS=${LOAD_EXAMPLE_REPORTS:-True}
      - FORWARD_AUTH_ENABLED=${FORWARD_AUTH_ENABLED:-False}
      - FORWARD_AUTH_HEADER=${FORWARD_AUTH_HEADER:-X-Forwarded-User}
      - RENDERER_HOST=${RENDERER_HOST:-renderer}
      - RENDERER_PORT=${RENDERER_PORT:-9000}
      - USER_SESSION_DURATION=${USER_SESSION_DURATION:-120}
      - COLUMNS=${COLUMNS} # Tell the Rich logging handler the terminal width
    secrets:
      - database_username
      - database_password
    depends_on:
      - database
    cap_drop:
      - ALL
    security_opt: *security-opt
    read_only: true
    tmpfs:
      - /tmp # Bottle buffers large request bodies, such as imported reports, in temporary files
  database:
    image: ictu/quality-time_database:${QUALITY_TIME_VERSION}
    command: --quiet
    environment:
      - *tz
      - MONGO_INITDB_ROOT_USERNAME_FILE=/run/secrets/database_username
      - MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/database_password
    secrets:
      - database_username
      - database_password
    volumes:
      - "dbdata:/data/db"
    cap_drop:
      - ALL
    security_opt: *security-opt
    read_only: true
    tmpfs:
      - /tmp # MongoDB creates its Unix domain socket in /tmp
  renderer:
    image: ictu/quality-time_renderer:${QUALITY_TIME_VERSION}
    environment:
      - *tz
      - PROXY_HOST=${PROXY_HOST:-www}
      - PROXY_PORT=${PROXY_PORT:-80}
      - LC_ALL=${LC_ALL:-en_GB.UTF-8} # Set the date format in the PDF export to DD-MM-YYYY
    cap_drop:
      - ALL
    security_opt: *security-opt
    read_only: true
    tmpfs:
      - /tmp # Chromium, used to render PDFs, writes temporary files to /tmp
volumes:
  dbdata:
secrets:
  database_password:
    file: database_password.txt
  database_username:
    file: database_username.txt
