# This file contains all of the services for an edX installation. See https://docs.docker.com/compose/compose-file/
# for the appropriate syntax and definitions.
#
# Housekeeping Rules:
# - Group third-party services, edX services, and edX microfrontends separately
# - Alphabetize services in the groups
# - Alphabetize individual configuration options for each service
# - Every service's container name should be prefixed with "edx.devstack." to avoid conflicts with other containers
#   that might be running for the same service.

version: "2.1"

services:

  # ================================================
  # Third-party services
  # ================================================

  chrome:
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.chrome"
    hostname: chrome.devstack.edx
    image: edxops/chrome:${OPENEDX_RELEASE:-latest}
    shm_size: 2g
    networks:
      default:
        aliases:
          - edx.devstack.chrome
    ports:
      - "15900:5900"
    volumes:  # for file uploads
      - ../edx-e2e-tests/upload_files:/edx/app/e2e/edx-e2e-tests/upload_files
      - ../edx-platform/common/test/data:/edx/app/edxapp/edx-platform/common/test/data

  devpi:
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.devpi"
    hostname: devpi.devstack.edx
    image: edxops/devpi:${OPENEDX_RELEASE:-latest}
    networks:
      default:
        aliases:
          - edx.devstack.devpi
    ports:
      - "3141:3141"
    volumes:
      - devpi_data:/data

  elasticsearch:
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.elasticsearch"
    hostname: elasticsearch.devstack.edx
    image: edxops/elasticsearch:devstack
    networks:
      default:
        aliases:
          - edx.devstack.elasticsearch
    # TODO: What to do about these forwarded ports? They'll conflict with ports forwarded by the Vagrant VM.
    # ports:
    #   - "9200:9200"
    #   - "9300:9300"
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data
      - elasticsearch_data:/usr/share/elasticsearch/logs

  # This is meant to be used to test ES upgrades so that we do not have to upgrade all of our services to ES5 at once.
  elasticsearch7:
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.elasticsearch7"
    hostname: elasticsearch7.devstack.edx
    image: elasticsearch:7.8.1
    networks:
      default:
        aliases:
          - edx.devstack.elasticsearch7
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - elasticsearch7_data:/usr/share/elasticsearch/data
    environment:
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"

  firefox:
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.firefox"
    hostname: firefox.devstack.edx
    image: edxops/firefox:${OPENEDX_RELEASE:-latest}
    shm_size: 2g
    networks:
      default:
        aliases:
          - edx.devstack.firefox
    ports:
      - "25900:5900"
    volumes:  # for file uploads
      - ../edx-e2e-tests/upload_files:/edx/app/e2e/edx-e2e-tests/upload_files
      - ../edx-platform/common/test/data:/edx/app/edxapp/edx-platform/common/test/data

  memcached:
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.memcached"
    hostname: memcached.devstack.edx
    image: memcached:1.5.10-alpine
    networks:
      default:
        aliases:
          - edx.devstack.memcached
    # ports:
    #   - "11211:11211"

  mongo:
    # We use WiredTiger in all environments. In development environments we use small files
    # to conserve disk space, and disable the journal for a minor performance gain.
    # See https://docs.mongodb.com/v3.0/reference/program/mongod/#options for complete details.
    command: mongod --smallfiles --nojournal --storageEngine wiredTiger
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.mongo"
    hostname: mongo.devstack.edx
    image: mongo:${MONGO_VERSION:-4.0.22}
    networks:
      default:
        aliases:
          - edx.devstack.mongo
    # ports:
    #  - "27017:27017"
    volumes:
      - mongo_data:/data/db

  mysql:
    command: mysqld --character-set-server=utf8 --collation-server=utf8_general_ci
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.mysql"
    hostname: mysql.devstack.edx
    environment:
      MYSQL_ROOT_PASSWORD: ""
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
    image: mysql:5.6
    networks:
      default:
        aliases:
          - edx.devstack.mysql
    # ports:
    #   - "3506:3306"
    volumes:
      - mysql_data:/var/lib/mysql

  mysql57:
    command: mysqld --character-set-server=utf8 --collation-server=utf8_general_ci
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.mysql57"
    hostname: mysql57.devstack.edx
    environment:
      MYSQL_ROOT_PASSWORD: ""
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
    image: mysql:5.7
    networks:
      default:
        aliases:
          - edx.devstack.mysql57
    # ports:
    #   - "3506:3306"
    volumes:
      - mysql57_data:/var/lib/mysql

  redis:
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.redis"
    hostname: redis.devstack.edx
    image: redis:2.8
    command: redis-server --requirepass password
    networks:
      default:
        aliases:
          - edx.devstack.redis

  # ================================================
  # edX services
  # ================================================

  credentials:
    command: bash -c 'source /edx/app/credentials/credentials_env && while true; do python /edx/app/credentials/credentials/manage.py runserver 0.0.0.0:18150; sleep 2; done'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.credentials"
    hostname: credentials.devstack.edx
    depends_on:
      - mysql57
      - memcached
      - lms
    # Allows attachment to the credentials service using 'docker attach <containerID>'.
    stdin_open: true
    tty: true
    environment:
      CACHE_LOCATION: edx.devstack.memcached:11211
      DB_HOST: edx.devstack.mysql57
      SOCIAL_AUTH_EDX_OIDC_URL_ROOT: http://edx.devstack.lms:18000/oauth2
      ENABLE_DJANGO_TOOLBAR: 1
      DJANGO_WATCHMAN_TIMEOUT: 30
    image: edxops/credentials:${OPENEDX_RELEASE:-latest}
    networks:
      default:
        aliases:
          - edx.devstack.credentials
    ports:
      - "18150:18150"

  discovery:
    command: bash -c 'source /edx/app/discovery/discovery_env && while true; do python /edx/app/discovery/discovery/manage.py runserver 0.0.0.0:18381; sleep 2; done'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.discovery"
    hostname: discovery.devstack.edx
    depends_on:
      - mysql57
      - elasticsearch7
      - memcached
    # Allows attachment to the discovery service using 'docker attach <containerID>'.
    stdin_open: true
    tty: true
    environment:
      # This next DB_MIGRATION_HOST line can be removed once edx/configuration has been updated with this value for
      # a while and most people have had a chance to do a "make pull" to get the latest images.
      DB_MIGRATION_HOST: edx.devstack.mysql57
      TEST_ELASTICSEARCH_URL: "edx.devstack.elasticsearch7"
      ENABLE_DJANGO_TOOLBAR: 1
      DJANGO_WATCHMAN_TIMEOUT: 30
    image: edxops/discovery:${OPENEDX_RELEASE:-latest}
    networks:
      default:
        aliases:
          - edx.devstack.discovery
    ports:
      - "18381:18381"
    volumes:
      - discovery_assets:/edx/var/discovery/

  ecommerce:
    command: bash -c 'source /edx/app/ecommerce/ecommerce_env && while true; do python /edx/app/ecommerce/ecommerce/manage.py runserver 0.0.0.0:18130; sleep 2; done'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.ecommerce"
    hostname: ecommerce.devstack.edx
    depends_on:
      - mysql57
      - memcached
      - lms
      - discovery
    # Allows attachment to the ecommerce service using 'docker attach <containerID>'.
    stdin_open: true
    tty: true
    environment:
      DJANGO_WATCHMAN_TIMEOUT: 30
      ENABLE_DJANGO_TOOLBAR: 1
    image: edxops/ecommerce:${OPENEDX_RELEASE:-latest}
    networks:
      default:
        aliases:
          - edx.devstack.ecommerce
    ports:
      - "18130:18130"

  edx_notes_api:
    # Sleep as a part of start up to give elasticsearch enough time to start up.
    command: bash -c 'source /edx/app/edx_notes_api/edx_notes_api_env && while true; do python /edx/app/edx_notes_api/edx_notes_api/manage.py runserver 0.0.0.0:18120 --settings notesserver.settings.devstack; sleep 4; done'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.edxnotesapi"
    hostname: edx_notes_api.devstack.edx
    depends_on:
      - devpi
      - elasticsearch7
      - lms
      - mysql57
    image: edxops/notes:${OPENEDX_RELEASE:-latest}
    networks:
      default:
        aliases:
          - edx.devstack.edxnotesapi
    ports:
      - "18120:18120"
    environment:
      DB_ENGINE: "django.db.backends.mysql"
      DB_HOST: "edx.devstack.mysql57"
      DB_NAME: "notes"
      DB_PASSWORD: "password"
      DB_PORT: "3306"
      DB_USER: "notes001"
      DJANGO_WATCHMAN_TIMEOUT: 30
      ENABLE_DJANGO_TOOLBAR: 1
      ELASTICSEARCH_URL: "http://edx.devstack.elasticsearch7:9200"

  forum:
    command: bash -c 'source /edx/app/forum/ruby_env && source /edx/app/forum/devstack_forum_env && cd /edx/app/forum/cs_comments_service && bundle install && while true; do ruby app.rb -o 0.0.0.0 ; sleep 2; done'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.forum"
    hostname: forum.devstack.edx
    depends_on:
      - mongo
      - memcached
      - elasticsearch7
    image: edxops/forum:${OPENEDX_RELEASE:-latest}
    stdin_open: true
    tty: true
    networks:
      default:
        aliases:
          - edx.devstack.forum
    ports:
      - "44567:4567"

  lms:
    command: bash -c 'source /edx/app/edxapp/edxapp_env && while true; do python /edx/app/edxapp/edx-platform/manage.py lms runserver 0.0.0.0:18000 --settings devstack_docker; sleep 2; done'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.lms"
    hostname: lms.devstack.edx
    depends_on:
      - devpi
      - mysql57
      - memcached
      - mongo
      - discovery
      - forum
      - firefox
      - chrome
      - elasticsearch7
    # Allows attachment to the LMS service using 'docker attach <containerID>'.
    stdin_open: true
    tty: true
    environment:
      BOK_CHOY_HOSTNAME: edx.devstack.lms
      BOK_CHOY_LMS_PORT: 18003
      BOK_CHOY_CMS_PORT: 18031
      EDXAPP_TEST_MONGO_HOST: edx.devstack.mongo
      NO_PYTHON_UNINSTALL: 1
      DJANGO_WATCHMAN_TIMEOUT: 30
    image: edxops/edxapp:${OPENEDX_RELEASE:-latest}
    networks:
      default:
        aliases:
          - edx.devstack.lms
          - lms.devstack.edx
    ports:
      - "18000:18000"
      - "19876:19876" # JS test debugging
      # - "18003:18003"
      # - "18031:18031"
    volumes:
      - edxapp_lms_assets:/edx/var/edxapp/staticfiles/

  registrar:
    command: bash -c 'source /edx/app/registrar/registrar_env && while true; do python /edx/app/registrar/registrar/manage.py runserver 0.0.0.0:18734; sleep 2; done'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.registrar"
    hostname: registrar.devstack.edx
    depends_on:
      - discovery
      - lms
      - mysql57
      - memcached
      - redis
      - registrar-worker
    # Allows attachment to the registrar service using 'docker attach <containerID>'.
    stdin_open: true
    tty: true
    environment:
      DB_HOST: edx.devstack.mysql57
      DB_NAME: registrar
      DB_PORT: 3306
      DB_USER: registrar001
      DB_PASSWORD: password
      LMS_HOST: http://localhost:18000
      MEMCACHE_HOST: edx.devstack.memcached
      DJANGO_SETTINGS_MODULE: registrar.settings.devstack
      CELERY_ALWAYS_EAGER: 'false'
      CELERY_BROKER_TRANSPORT: redis
      CELERY_BROKER_HOSTNAME: edx.devstack.redis:6379
      CELERY_BROKER_VHOST: 10
      CELERY_BROKER_PASSWORD: password
      DJANGO_WATCHMAN_TIMEOUT: 30
    image: edxops/registrar:${OPENEDX_RELEASE:-latest}
    networks:
      default:
        aliases:
          - edx.devstack.registrar
    ports:
      - "18734:18734"
    volumes:
      - /edx/var/registrar/

  registrar-worker:
    command: bash -c 'source /edx/app/registrar/registrar_env && cd /edx/app/registrar/registrar && celery -A registrar worker -l debug -c 2'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.registrar-worker"
    hostname: registrar-worker.devstack.edx
    depends_on:
      - lms
      - mysql57
      - redis
    stdin_open: true
    tty: true
    environment:
      DB_HOST: edx.devstack.mysql57
      DB_NAME: registrar
      DB_PORT: 3306
      DB_USER: registrar001
      DB_PASSWORD: password
      LMS_HOST: http://localhost:18000
      MEMCACHE_HOST: edx.devstack.memcached
      DJANGO_SETTINGS_MODULE: registrar.settings.devstack
      CELERY_BROKER_TRANSPORT: redis
      CELERY_BROKER_HOSTNAME: edx.devstack.redis:6379
      CELERY_BROKER_VHOST: 10
      CELERY_BROKER_PASSWORD: password
      DJANGO_WATCHMAN_TIMEOUT: 30
    image: edxops/registrar:${OPENEDX_RELEASE:-latest}
    networks:
      default:
        aliases:
          - edx.devstack.registrar-worker
    ports:
      - "18735:18735"
    volumes:
      - /edx/var/registrar/

  studio:
    command: bash -c 'source /edx/app/edxapp/edxapp_env && while true; do python /edx/app/edxapp/edx-platform/manage.py cms runserver 0.0.0.0:18010 --settings devstack_docker; sleep 2; done'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.studio"
    hostname: studio.devstack.edx
    depends_on:
      - devpi
      - mysql57
      - elasticsearch7
      - memcached
      - mongo
      - firefox
      - chrome
      - lms
    # Allows attachment to the Studio service using 'docker attach <containerID>'.
    stdin_open: true
    tty: true
    environment:
      BOK_CHOY_HOSTNAME: edx.devstack.studio
      BOK_CHOY_LMS_PORT: 18103
      BOK_CHOY_CMS_PORT: 18131
      EDXAPP_TEST_MONGO_HOST: edx.devstack.mongo
      NO_PYTHON_UNINSTALL: 1
      DJANGO_WATCHMAN_TIMEOUT: 30
    image: edxops/edxapp:${OPENEDX_RELEASE:-latest}
    networks:
      default:
        aliases:
          - edx.devstack.studio
          - studio.devstack.edx
    ports:
      - "18010:18010"
      - "19877:19877" # JS test debugging
      # - "18103:18103"
      # - "18131:18131"
    volumes:
      - edxapp_studio_assets:/edx/var/edxapp/staticfiles/

  # ==========================================================================
  # edX Microfrontends
  #
  # TODO: Instead of having an nginx container for every single microfrontend
  # (there are like 12 now, right?), we should come up with an actual strategy
  # for micro-frontends in devtack.
  # ==========================================================================

  frontend-app-learning:
    extends:
      file: microfrontend.yml
      service: microfrontend
    working_dir: '/edx/app/frontend-app-learning'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.frontend-app-learning"
    networks:
      default:
        aliases:
          - edx.devstack.frontend-app-learning
    ports:
      - "2000:2000"
    depends_on:
      - lms

  frontend-app-payment:
    extends:
      file: microfrontend.yml
      service: microfrontend
    working_dir: '/edx/app/frontend-app-payment'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.frontend-app-payment"
    networks:
      default:
        aliases:
          - edx.devstack.frontend-app-payment
    ports:
      - "1998:1998"
    depends_on:
      - ecommerce

  frontend-app-publisher:
    extends:
      file: microfrontend.yml
      service: microfrontend
    working_dir: '/edx/app/frontend-app-publisher'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.frontend-app-publisher"
    networks:
      default:
        aliases:
          - edx.devstack.frontend-app-publisher
    ports:
      - "18400:18400"
    depends_on:
      - lms

  gradebook:
    extends:
      file: microfrontend.yml
      service: microfrontend
    working_dir: '/edx/app/gradebook'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.gradebook"
    networks:
      default:
        aliases:
          - edx.devstack.gradebook
    ports:
      - "1994:1994"
    depends_on:
      - lms

  program-console:
    extends:
      file: microfrontend.yml
      service: microfrontend
    working_dir: '/edx/app/program-console'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.program-console"
    networks:
      default:
        aliases:
          - edx.devstack.program-console
    ports:
      - "1976:1976"
    depends_on:
      - lms
      - registrar

  course-authoring:
    extends:
      file: microfrontend.yml
      service: microfrontend
    working_dir: '/edx/app/frontend-app-course-authoring'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.course-authoring"
    networks:
      default:
        aliases:
          - edx.devstack.course-authoring
    ports:
      - "2001:2001"
    depends_on:
      - studio

  frontend-app-library-authoring:
    extends:
      file: microfrontend.yml
      service: microfrontend
    working_dir: '/edx/app/frontend-app-library-authoring'
    container_name: "edx.${COMPOSE_PROJECT_NAME:-devstack}.frontend-app-library-authoring"
    networks:
      default:
        aliases:
          - edx.devstack.frontend-app-library-authoring
    ports:
      - "3001:3001"
    depends_on:
      - lms
      - studio

volumes:
  discovery_assets:
  edxapp_lms_assets:
  edxapp_studio_assets:
  elasticsearch_data:
  elasticsearch7_data:
  mongo_data:
  mysql_data:
  mysql57_data:
  devpi_data:
