diff --git a/.gitignore b/.gitignore index a6e6e08..bd31e70 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ .*.swp -data/* +config.json +edxapp/config/*.env.json +edxapp/config/*.auth.json +nginx/config/*.conf +mysql/config/database +mysql/config/username +mysql/config/password diff --git a/Makefile b/Makefile index ad63e34..7c03f95 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,41 @@ -directories: - mkdir -p ./data/edxapp/logs ./data/edxapp/uploads ./data/edxapp/staticfiles +.PHONY: all configure build migrate assets up daemon + +all: configure build migrate assets daemon + +##################### Bootstrapping commands + +configure: + ./configure + +build: + docker-compose build + migrate: - docker-compose run lms ./manage.py lms migrate --settings=production - docker-compose run cms ./manage.py cms migrate --settings=production + docker-compose run --rm lms bash -c "./wait-for-mysql.sh && ./manage.py lms migrate --settings=production" + docker-compose run --rm cms bash -c "./wait-for-mysql.sh && ./manage.py cms migrate --settings=production" + assets: - docker-compose run lms paver update_assets lms --settings=production - docker-compose run cms paver update_assets cms --settings=production + docker-compose run --rm lms paver update_assets lms --settings=production + docker-compose run --rm cms paver update_assets cms --settings=production + +##################### Running commands + +up: + docker-compose up + +daemon: + docker-compose up -d && \ + echo "Daemon is up and running" + +stop: + docker-compose stop + +##################### Additional commands + lms-shell: - docker-compose run lms ./manage.py lms shell --settings=production + docker-compose run --rm lms ./manage.py lms shell --settings=production cms-shell: - docker-compose run lms ./manage.py cms shell --settings=production + docker-compose run --rm lms ./manage.py cms shell --settings=production import-demo-course: - docker-compose run cms git clone https://github.com/edx/edx-demo-course ../edx-demo-course && \ - cd ../edx-demo-course && \ - git checkout open-release/ginkgo.master && \ - cd ../edx-platform && \ - python ./manage.py cms --settings=production import ../data ../edx-demo-course + docker-compose run --rm cms /bin/bash -c "git clone https://github.com/edx/edx-demo-course ../edx-demo-course && git -C ../edx-demo-course checkout open-release/ginkgo.master && python ./manage.py cms --settings=production import ../data ../edx-demo-course" diff --git a/README.md b/README.md index 3d6e56a..e083c68 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,79 @@ -# [WIP] Docker-compose Open edX production stack +# Open edX quick install (in Docker containers) -This is a work-in-progress. +This is a **one-click production install of [Open edX](https://openedx.org)**. -The production stack is sufficient for a minimal production deployment of Open edX. +The deployment of a full-featured Open edX platform is a highly technical and complex project... but we can remove most of the complexity by relying on pre-configured Docker containers and by using only a subset of all possible features. We made this so that non-technical people could still install Open edX by themselves: knowing how to launch a server and ssh into it should be enough. But we also made sure that every step of the deploy process could be customized if you have the technical skills. -## Lauch a production stack +## Quickstart -Prepare build: +All you have to do is [download the content of this repository](https://codeload.github.com/regisb/openedx-docker/zip/master), uncompress and run: - make directories + make all -Build and run: +There is no step #2. You will be asked some questions about the configuration of your Open edX platform. The build step will take some time, but then you will have both an LMS and a CMS running behind a web server on port 80. You should be able to access your platform at the address you gave during the configuration phase. - docker-compose build # go get a coffee - docker-compose up +To be honest, I really don't like 1-click installs :-p They tend to hide much of the important details. So I strongly recommend you read the more detailed instructions below to understand what is going on exactly and to troubleshoot potential issues. -The LMS will be reachable at [http://openedxdemo.overhang.io](http://openedxdemo.overhang.io). +## Requirements -The CMS will be reachable at [http://studio.openedxdemo.overhang.io](http://studio.openedxdemo.overhang.io). +The only prerequisite for running this is Python and a working docker install. You will need both docker and docker-compose. Follow the instructions from the official documentation: -For local development, you should point to http://localhost:8800. +- [Python](https://www.python.org/downloads/): all versions >= 2.7 are supported. +- [Docker install](https://docs.docker.com/engine/installation/) +- [Docker compose install](https://docs.docker.com/compose/install/) -On the first run you will need to migrate the database and collect static assets: +Note that the web server container will bind to port 80, so if you already have a web server running (Apache or Nginx, for instance), you should stop it. + +You should be able to run Open edX on any platform that supports Docker and Python, including Mac OS and Windows. For now, only Ubuntu 16.04 was tested but we have no reason to believe the install would not work on a different OS. + +At a minimum, the server running the containers should have 4 Gb of RAM. + +## Step-by-step install + +### Configure + + make configure + +This is the only non-automatic step in the install process. You will be asked various questions about your Open edX platform and appropriate configuration files will be generated. If you would like to automate this step then you should run `make configure` interactively once. After that, you will have a `config.json` file at the root of the repository. Just upload it to wherever you want to run Open edX and then run `./configure --silent` instead of `make configure`. All values from `config.json` will be automatically loaded. + +### Build + + make build # go get a coffee + +Building the images may require a long time, depending on your bandwidth, as you will have to checkout the `edx-platform` repository (> 1 Gb) as well as the python dependencies. Once the images have been built, this step can be repeated very quickly. + +### Migrations and assets make migrate make assets -To import the Open edX demo course, run: +These commands should be run just once. They will create the database tables and generate static assets, such as images, stylesheets and Javascript dependencies. + +### Running Open edX + + make up + +This will launch the various docker containers required for your Open edX platform. The LMS and the Studio will then be reachable at the domain name you specified during the configuration step. + +## Additional commands + +### Importing the demo course + +On a fresh install, your platform will not have a single course. To import the [Open edX demo course](https://github.com/edx/edx-demo-course ), run: make import-demo-course -To daemonize: +### Daemonizing - docker-compose up -d +Note that in production, you will probably want to daemonize the services. Instead of `make up`, run: -## Development + make daemon + +And then, to stop all services: + + make stop + +### Development Open a bash in the lms: @@ -45,10 +84,11 @@ Open a python shell in the lms or the cms: make lms-shell make cms-shell -## TODO +## Disclaimers & Warnings -- Make sure that secret keys are not shared with the entire world -- Don't duplicate args between containers -- Add arguments to set domain name, platform name, etc. -- Add documentation on host Nginx -- Better readme +This project is the follow-up of my work on an [install from scratch of Open edX](https://github.com/regisb/openedx-install). It does not rely on any hack or complex deployment script. In particular, we do not use the Open edX [Ansible deployment playbooks](https://github.com/edx/configuration/). That means that the folks at edX.org are *not* responsible for troubleshooting issues of this project. Please don't bother Ned ;-) + +If you have a problem, feel free to open a [Github issue](https://github.com/regisb/openedx-docker/issues) that describes: +- the problem you are facing: this includes the exact error message, or a screenshot of the error. +- what action triggered the error: which command line instruction, which url you tried to access, etc. +- any error logs that you may find: you may want to take a look at the files in `data/lms/logs`, for instance. diff --git a/configure b/configure new file mode 100755 index 0000000..f8a8e0d --- /dev/null +++ b/configure @@ -0,0 +1,198 @@ +#! /usr/bin/env python +# coding: utf8 +from __future__ import unicode_literals, print_function +import argparse +import codecs +import json +import os +import random +import string +import sys + +class Configurator(object): + + def __init__(self, silent=False, **default_overrides): + self.__values = [] + self.__default_overrides = default_overrides + if silent: + self.__input = None + else: + try: + self.__input = raw_input + except NameError: + self.__input = input + + def as_dict(self): + return dict(self.__values) + + def add(self, name, question, default=""): + default = self.__default_overrides.get(name, default) + message = question + " (default: \"{}\"): ".format(default) + value = self.ask(message, default) + self.set(name, value) + + return self + + def add_boolean(self, name, question, default=True): + default = self.__default_overrides.get(name, default) + message = question + " ({}) ".format("Y/n" if default else "y/N") + value = None + while value is None: + answer = self.ask(message, default) + value = { + "y": True, + "n": False, + default: default, + }.get(answer) + self.set(name, value) + return self + + def ask(self, message, default): + if self.__input: + return self.__input(message) or default + return default + + def get(self, name): + for key, value in self.__values: + if key == name: + return value + return None + + def set(self, name, value): + self.__values.append((name, value)) + + +def substitute(src, dst, delimiter='$', **values): + Template = template_class(delimiter) + + with codecs.open(src, encoding='utf-8') as fi: + template = Template(fi.read()) + try: + substituted = template.substitute(**values) + except KeyError as e: + sys.stderr.write("ERROR Missing config value '{}' for template {}\n".format(e.args[0], src)) + sys.exit(1) + + with open(dst, 'w') as fo: + fo.write(substituted) + + print("Generated config file {} (from template {})".format(dst, src)) + +def template_class(user_delimiter='$'): + """ + The default delimiter of the python Template class is '$'. Here, we + generate a Template class with a custom delimiter. This cannot be done + after the class creation because the Template metaclass uses the delimiter + value. + """ + class Template(string.Template): + delimiter = user_delimiter + return Template + + +def main(): + parser = argparse.ArgumentParser("Config file generator for Open edX") + parser.add_argument('-c', '--config', default="config.json", + help="Load default values from this file. Config values will be saved there.") + parser.add_argument('-s', '--silent', action='store_true', + help=( + "Be silent and accept all default values. " + "This is good for debugging, but probably not what you want" + )) + args = parser.parse_args() + + # Load defaults + defaults = {} + if os.path.exists(args.config): + with open(args.config) as f: + defaults = json.load(f) + + configurator = Configurator(silent=args.silent, **defaults).add( + 'LMS_HOST', "Your website domain name for students (LMS)", 'www.myopenedx.com' + ).add_boolean( + 'HTTPS_LMS', "Will you use https for the LMS?", False + ).add( + 'CMS_HOST', "Your website domain name for teachers (CMS)", 'studio.myopenedx.com' + ).add_boolean( + 'HTTPS_CMS', "Will you use https for the CMS?", False + ).add( + 'SECRET_KEY', "Secret key -- if you don't know what this is, you can safely accept the default", + "".join([random.choice(string.ascii_letters + string.digits) for _ in range(24)]) + ).add( + 'PLATFORM_NAME', "Platform name/title", "My Open edX" + ).add( + 'MYSQL_DATABASE', "MySQL database name", 'openedx' + ).add( + 'MYSQL_USERNAME', "MySQL database username", 'openedx' + ).add( + 'MYSQL_PASSWORD', "MySQL database password", 'password' + ).add( + 'MONGODB_DATABASE', "MongoDb database name", 'openedx' + ) + + # Save values + with open(args.config, 'w') as f: + json.dump(configurator.as_dict(), f, sort_keys=True, indent=4) + print("\nConfiguration values were saved to ", args.config) + + configurator.set('PROTOCOL_LMS', 'https' if configurator.get('HTTPS_LMS') else 'http') + configurator.set('PROTOCOL_CMS', 'https' if configurator.get('HTTPS_CMS') else 'http') + + # Open edX + substitute( + os.path.join('edxapp', 'config', 'templates', 'lms.env.json.templ'), + os.path.join('edxapp', 'config', 'lms.env.json'), + **configurator.as_dict() + ) + substitute( + os.path.join('edxapp', 'config', 'templates', 'cms.env.json.templ'), + os.path.join('edxapp', 'config', 'cms.env.json'), + **configurator.as_dict() + ) + substitute( + os.path.join('edxapp', 'config', 'templates', 'lms.auth.json.templ'), + os.path.join('edxapp', 'config', 'lms.auth.json'), + **configurator.as_dict() + ) + substitute( + os.path.join('edxapp', 'config', 'templates', 'cms.auth.json.templ'), + os.path.join('edxapp', 'config', 'cms.auth.json'), + **configurator.as_dict() + ) + + # MySQL + substitute( + os.path.join('mysql', 'config', 'templates', 'username.templ'), + os.path.join('mysql', 'config', 'username'), + **configurator.as_dict() + ) + substitute( + os.path.join('mysql', 'config', 'templates', 'password.templ'), + os.path.join('mysql', 'config', 'password'), + **configurator.as_dict() + ) + substitute( + os.path.join('mysql', 'config', 'templates', 'database.templ'), + os.path.join('mysql', 'config', 'database'), + **configurator.as_dict() + ) + + # Nginx + # We need a different delimiter in nginx config files, because the '$' sign + # is widely used there + substitute( + os.path.join('nginx', 'config', 'templates', 'lms.conf.templ'), + os.path.join('nginx', 'config', 'lms.conf'), + delimiter='£', **configurator.as_dict() + ) + substitute( + os.path.join('nginx', 'config', 'templates', 'cms.conf.templ'), + os.path.join('nginx', 'config', 'cms.conf'), + delimiter='£', **configurator.as_dict() + ) + + print("\nConfiguration files were successfuly generated. You may now build the app containers.") + + +if __name__ == '__main__': + main() diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 0000000..9cb3f4c --- /dev/null +++ b/data/.gitignore @@ -0,0 +1,7 @@ +cms/ +cms_worker/ +lms/ +lms_worker/ +mysql/ +mongodb/ +rabbitmq/ diff --git a/docker-compose.yml b/docker-compose.yml index 3971e2f..296328b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,26 +16,24 @@ services: mysql: image: mysql:5.6.36 command: mysqld --character-set-server=utf8 --collation-server=utf8_general_ci - environment: - MYSQL_ROOT_PASSWORD: "" - MYSQL_DATABASE: "openedx" - MYSQL_USER: "openedx" - MYSQL_PASSWORD: "password" - MYSQL_ALLOW_EMPTY_PASSWORD: "yes" volumes: - ./data/mysql:/var/lib/mysql + - ./mysql/config/:/etc/mysql/conf.d/openedx + environment: + # Load values from files generated by configurator + MYSQL_DATABASE_FILE: /etc/mysql/conf.d/openedx/database + MYSQL_USER_FILE: /etc/mysql/conf.d/openedx/username + MYSQL_PASSWORD_FILE: /etc/mysql/conf.d/openedx/password + MYSQL_ROOT_PASSWORD_FILE: /etc/mysql/conf.d/openedx/password nginx: build: context: ./nginx - args: - lms_host: learn.overhang.io - cms_host: studio.learn.overhang.io - #restart: on-failure + restart: on-failure ports: - - "8800:80" + - "80:80" volumes: - - ./data/edxapp:/openedx/data:ro + - ./data/lms:/openedx/data:ro depends_on: - lms @@ -45,10 +43,9 @@ services: - ./data/rabbitmq:/var/lib/rabbitmq # Simple SMTP server + # TODO this smtp server doesn't send any email. Fix this. smtp: image: namshi/smtp - environment: - PORT: 9025 ############# LMS and CMS @@ -56,13 +53,10 @@ services: build: context: ./edxapp args: - lms_host: learn.overhang.io - cms_host: studio.learn.overhang.io service_variant: lms - secret_key: "12UyBHiBWxcPT1NP4prP5QhHc" - #restart: on-failure + restart: on-failure volumes: - - ./data/edxapp:/openedx/data + - ./data/lms:/openedx/data depends_on: - memcached - mongodb @@ -74,32 +68,40 @@ services: build: context: ./edxapp args: - lms_host: learn.overhang.io - cms_host: studio.learn.overhang.io service_variant: cms - secret_key: "12UyBHiBWxcPT1NP4prP5QhHc" - #restart: on-failure + restart: on-failure volumes: - - ./data/edxapp:/openedx/data + - ./data/cms:/openedx/data depends_on: - lms ############# LMS and CMS workers - # TODO one service per queue? + # We could probably create one service per queue here. For small instances, it is not necessary. lms_worker: build: context: ./edxapp args: - lms_host: learn.overhang.io - cms_host: studio.learn.overhang.io service_variant: lms - secret_key: "12UyBHiBWxcPT1NP4prP5QhHc" command: ./manage.py lms --settings=production celery worker --loglevel=info --hostname=edx.lms.core.default.%%h --maxtasksperchild 100 environment: C_FORCE_ROOT: "1" # run celery tasks as root #nofear - #restart: on-failure + restart: on-failure volumes: - - ./data/edxapp:/openedx/data + - ./data/lms_worker:/openedx/data depends_on: - lms + + cms_worker: + build: + context: ./edxapp + args: + service_variant: cms + command: ./manage.py cms --settings=production celery worker --loglevel=info --hostname=edx.cms.core.default.%%h --maxtasksperchild 100 + environment: + C_FORCE_ROOT: "1" # run celery tasks as root #nofear + restart: on-failure + volumes: + - ./data/cms_worker:/openedx/data + depends_on: + - cms diff --git a/edxapp/Dockerfile b/edxapp/Dockerfile index 35448a1..7369b0c 100644 --- a/edxapp/Dockerfile +++ b/edxapp/Dockerfile @@ -3,65 +3,58 @@ FROM ubuntu:16.04 ############ common to lms & cms # Install system requirements -RUN apt update -RUN apt upgrade -y -# Global requirements -RUN apt install -y language-pack-en git python-virtualenv build-essential software-properties-common curl git-core libxml2-dev libxslt1-dev python-pip libmysqlclient-dev python-apt python-dev libxmlsec1-dev libfreetype6-dev swig gcc g++ -# edxapp requirements -RUN apt install -y gettext gfortran graphviz graphviz-dev libffi-dev libfreetype6-dev libgeos-dev libjpeg8-dev liblapack-dev libpng12-dev libxml2-dev libxmlsec1-dev libxslt1-dev nodejs npm ntp pkg-config +RUN apt update && \ + apt upgrade -y && \ + # Global requirements + apt install -y language-pack-en git python-virtualenv build-essential software-properties-common curl git-core libxml2-dev libxslt1-dev python-pip libmysqlclient-dev python-apt python-dev libxmlsec1-dev libfreetype6-dev swig gcc g++ && \ + # edxapp requirements + apt install -y gettext gfortran graphviz graphviz-dev libffi-dev libfreetype6-dev libgeos-dev libjpeg8-dev liblapack-dev libpng12-dev libxml2-dev libxmlsec1-dev libxslt1-dev nodejs npm ntp pkg-config && \ + # Our requirements + apt install -y mysql-client # Install symlink so that we have access to 'node' binary without virtualenv. # This replaces the "nodeenv" install. RUN apt install -y nodejs-legacy # Static assets will reside in /openedx/data and edx-platform will be -# checked-out in /openedx +# checked-out in /openedx/ +RUN mkdir /openedx /openedx/data /openedx/edx-platform VOLUME /openedx/data -WORKDIR /openedx - -# Checkout edx-platform code -RUN git clone https://github.com/edx/edx-platform.git WORKDIR /openedx/edx-platform -RUN git fetch && \ + +## Checkout edx-platform code +RUN git clone https://github.com/edx/edx-platform.git . && \ git checkout open-release/ginkgo.master # Install python requirements -RUN pip install pip==8.1.2 -RUN pip install setuptools==24.0.3 RUN pip install -r requirements/edx/pre.txt RUN pip install -r requirements/edx/github.txt RUN pip install -r requirements/edx/local.txt RUN pip install -r requirements/edx/base.txt RUN pip install -r requirements/edx/post.txt RUN pip install -r requirements/edx/paver.txt -RUN pip install ced # Finish requirements install RUN paver install_prereqs -ARG lms_host=localhost:8000 -ARG cms_host=localhost:8000 -ARG platform_name="My Ginkgo Open edX" -# service variang is "lms" or "cms" -ARG service_variant -ARG secret_key - -# Generate configuration files -ENV LMS_HOST=$lms_host CMS_HOST=$cms_host PLATFORM_NAME=$platform_name SECRET_KEY=$secret_key +# Copy configuration files COPY ./config/production_lms.py /openedx/edx-platform/lms/envs/production.py COPY ./config/production_cms.py /openedx/edx-platform/cms/envs/production.py -COPY ./config/lms.env.json.templ /openedx/ -COPY ./config/cms.env.json.templ /openedx/ -COPY ./config/lms.auth.json.templ /openedx/ -COPY ./config/cms.auth.json.templ /openedx/ -RUN ced /openedx/lms.env.json.templ -o /openedx/lms.env.json -RUN ced /openedx/cms.env.json.templ -o /openedx/cms.env.json -RUN ced /openedx/lms.auth.json.templ -o /openedx/lms.auth.json -RUN ced /openedx/cms.auth.json.templ -o /openedx/cms.auth.json +COPY ./config/production_common.py /openedx/edx-platform/lms/envs/production_common.py +COPY ./config/production_common.py /openedx/edx-platform/cms/envs/production_common.py +COPY ./config/lms.env.json /openedx/ +COPY ./config/cms.env.json /openedx/ +COPY ./config/lms.auth.json /openedx/ +COPY ./config/cms.auth.json /openedx/ +# Copy convenient script +COPY ./wait-for-mysql.sh . ############ End of code common to lms & cms +# service variant is "lms" or "cms" +ARG service_variant + # Configure environment ENV DJANGO_SETTINGS_MODULE ${service_variant}.envs.production ENV SERVICE_VARIANT ${service_variant} diff --git a/edxapp/config/production_cms.py b/edxapp/config/production_cms.py index 895b6c2..bb2c7ec 100644 --- a/edxapp/config/production_cms.py +++ b/edxapp/config/production_cms.py @@ -1,21 +1,5 @@ -from .aws import * - -update_module_store_settings(MODULESTORE, doc_store_settings=DOC_STORE_CONFIG) - -MEDIA_ROOT = "/openedx/uploads/" -FEATURES['ENABLE_DISCUSSION_SERVICE'] = False +from .production_common import * ALLOWED_HOSTS = [ ENV_TOKENS.get('CMS_BASE'), ] - -# Don't rely on AWS for sending email -EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" - -# We need to activate dev_env for logging, otherwise rsyslog is required (but -# it is not available in docker). -LOGGING = get_logger_config(LOG_DIR, - logging_env=ENV_TOKENS['LOGGING_ENV'], - debug=False, - dev_env=True, - service_variant=SERVICE_VARIANT) diff --git a/edxapp/config/production_common.py b/edxapp/config/production_common.py new file mode 100644 index 0000000..1cc8767 --- /dev/null +++ b/edxapp/config/production_common.py @@ -0,0 +1,24 @@ +import os +from .aws import * + +update_module_store_settings(MODULESTORE, doc_store_settings=DOC_STORE_CONFIG) + +MEDIA_ROOT = "/openedx/data/uploads/" +FEATURES['ENABLE_DISCUSSION_SERVICE'] = False + +# Don't rely on AWS for sending email +EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" +EMAIL_HOST = 'smtp' + +# We need to activate dev_env for logging, otherwise rsyslog is required (but +# it is not available in docker). +LOGGING = get_logger_config(LOG_DIR, + logging_env=ENV_TOKENS['LOGGING_ENV'], + debug=False, + dev_env=True, + service_variant=SERVICE_VARIANT) + +# Create folders if necessary +for folder in [LOG_DIR, MEDIA_ROOT, STATIC_ROOT_BASE]: + if not os.path.exists(folder): + os.makedirs(folder) diff --git a/edxapp/config/production_lms.py b/edxapp/config/production_lms.py index 83e7046..df14f5a 100644 --- a/edxapp/config/production_lms.py +++ b/edxapp/config/production_lms.py @@ -1,22 +1,6 @@ -from .aws import * - -update_module_store_settings(MODULESTORE, doc_store_settings=DOC_STORE_CONFIG) - -MEDIA_ROOT = "/openedx/data/uploads/" -FEATURES['ENABLE_DISCUSSION_SERVICE'] = False +from .production_common import * ALLOWED_HOSTS = [ ENV_TOKENS.get('LMS_BASE'), FEATURES['PREVIEW_LMS_BASE'], ] - -# Don't rely on AWS for sending email -EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" - -# We need to activate dev_env for logging, otherwise rsyslog is required (but -# it is not available in docker). -LOGGING = get_logger_config(LOG_DIR, - logging_env=ENV_TOKENS['LOGGING_ENV'], - debug=False, - dev_env=True, - service_variant=SERVICE_VARIANT) diff --git a/edxapp/config/cms.auth.json.templ b/edxapp/config/templates/cms.auth.json.templ similarity index 81% rename from edxapp/config/cms.auth.json.templ rename to edxapp/config/templates/cms.auth.json.templ index 879c7fa..b2d2fd7 100644 --- a/edxapp/config/cms.auth.json.templ +++ b/edxapp/config/templates/cms.auth.json.templ @@ -13,7 +13,7 @@ "CONTENTSTORE": { "ENGINE": "xmodule.contentstore.mongo.MongoContentStore", "DOC_STORE_CONFIG": { - "db": "edxapp", + "db": "${MONGODB_DATABASE}", "host": "mongodb" } }, @@ -24,9 +24,9 @@ "DATABASES": { "default": { "ENGINE": "django.db.backends.mysql", - "NAME": "openedx", - "USER": "openedx", - "PASSWORD": "password", + "NAME": "${MYSQL_DATABASE}", + "USER": "${MYSQL_USERNAME}", + "PASSWORD": "${MYSQL_PASSWORD}", "HOST": "mysql", "PORT": "3306", "ATOMIC_REQUESTS": true diff --git a/edxapp/config/cms.env.json.templ b/edxapp/config/templates/cms.env.json.templ similarity index 95% rename from edxapp/config/cms.env.json.templ rename to edxapp/config/templates/cms.env.json.templ index 7c7b415..5de37be 100644 --- a/edxapp/config/cms.env.json.templ +++ b/edxapp/config/templates/cms.env.json.templ @@ -8,8 +8,8 @@ "FEATURES": { "PREVIEW_LMS_BASE": "localhost:8000" }, - "LMS_ROOT_URL": "http://${LMS_HOST}", - "CMS_ROOT_URL": "http://${CMS_HOST}", + "LMS_ROOT_URL": "${PROTOCOL_LMS}://${LMS_HOST}", + "CMS_ROOT_URL": "${PROTOCOL_CMS}://${CMS_HOST}", "CMS_BASE": "${CMS_HOST}", "LMS_BASE": "${LMS_HOST}", "CELERY_BROKER_HOSTNAME": "rabbitmq", diff --git a/edxapp/config/lms.auth.json.templ b/edxapp/config/templates/lms.auth.json.templ similarity index 79% rename from edxapp/config/lms.auth.json.templ rename to edxapp/config/templates/lms.auth.json.templ index 879c7fa..108b66b 100644 --- a/edxapp/config/lms.auth.json.templ +++ b/edxapp/config/templates/lms.auth.json.templ @@ -13,20 +13,20 @@ "CONTENTSTORE": { "ENGINE": "xmodule.contentstore.mongo.MongoContentStore", "DOC_STORE_CONFIG": { - "db": "edxapp", + "db": "${MONGODB_DATABASE}", "host": "mongodb" } }, "DOC_STORE_CONFIG": { - "db": "edxapp", + "db": "${MONGODB_DATABASE}", "host": "mongodb" }, "DATABASES": { "default": { "ENGINE": "django.db.backends.mysql", - "NAME": "openedx", - "USER": "openedx", - "PASSWORD": "password", + "NAME": "${MYSQL_DATABASE}", + "USER": "${MYSQL_USERNAME}", + "PASSWORD": "${MYSQL_PASSWORD}", "HOST": "mysql", "PORT": "3306", "ATOMIC_REQUESTS": true diff --git a/edxapp/config/lms.env.json.templ b/edxapp/config/templates/lms.env.json.templ similarity index 94% rename from edxapp/config/lms.env.json.templ rename to edxapp/config/templates/lms.env.json.templ index 604a7c5..565a657 100644 --- a/edxapp/config/lms.env.json.templ +++ b/edxapp/config/templates/lms.env.json.templ @@ -8,10 +8,10 @@ "FEATURES": { "PREVIEW_LMS_BASE": "${LMS_HOST}" }, - "LMS_ROOT_URL": "http://${LMS_HOST}", - "CMS_ROOT_URL": "http://${CMS_HOST}", + "LMS_ROOT_URL": "${PROTOCOL_LMS}://${LMS_HOST}", + "CMS_ROOT_URL": "${PROTOCOL_CMS}://${CMS_HOST}", "CMS_BASE": "${CMS_HOST}", - "LMS_BASE": "openedxdemo.overhang.io", + "LMS_BASE": "${LMS_HOST}", "CELERY_BROKER_HOSTNAME": "rabbitmq", "CELERY_BROKER_TRANSPORT": "amqp", "MEDIA_ROOT": "/openedx/data/uploads/", diff --git a/edxapp/wait-for-mysql.sh b/edxapp/wait-for-mysql.sh new file mode 100755 index 0000000..344ce24 --- /dev/null +++ b/edxapp/wait-for-mysql.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +echo "Waiting for mysql database" +until echo "show tables;" | ./manage.py lms --settings=production dbshell +do + printf "." + sleep 1 +done + +echo -e "\nmysql database ready" diff --git a/mysql/config/templates/database.templ b/mysql/config/templates/database.templ new file mode 100644 index 0000000..4e54088 --- /dev/null +++ b/mysql/config/templates/database.templ @@ -0,0 +1 @@ +${MYSQL_DATABASE} diff --git a/mysql/config/templates/password.templ b/mysql/config/templates/password.templ new file mode 100644 index 0000000..ee16543 --- /dev/null +++ b/mysql/config/templates/password.templ @@ -0,0 +1 @@ +${MYSQL_PASSWORD} diff --git a/mysql/config/templates/username.templ b/mysql/config/templates/username.templ new file mode 100644 index 0000000..24e45d6 --- /dev/null +++ b/mysql/config/templates/username.templ @@ -0,0 +1 @@ +${MYSQL_USERNAME} diff --git a/nginx/Dockerfile b/nginx/Dockerfile index c9726dd..b6e7256 100644 --- a/nginx/Dockerfile +++ b/nginx/Dockerfile @@ -1,16 +1,5 @@ FROM nginx:1.13 VOLUME /openedx/data -# Install ced -RUN apt update -RUN apt install -y python-pip -RUN pip install ced - -ARG lms_host=localhost -ARG cms_host=studio.$lms_host -ENV LMS_HOST=$lms_host CMS_HOST=$cms_host - -COPY ./config/lms.conf.templ /etc/nginx/conf.d/lms.conf.templ -RUN ced -o /etc/nginx/conf.d/lms.conf -d £ /etc/nginx/conf.d/lms.conf.templ -COPY ./config/cms.conf.templ /etc/nginx/conf.d/cms.conf.templ -RUN ced -o /etc/nginx/conf.d/cms.conf -d £ /etc/nginx/conf.d/cms.conf.templ +COPY ./config/lms.conf /etc/nginx/conf.d/lms.conf +COPY ./config/cms.conf /etc/nginx/conf.d/cms.conf diff --git a/nginx/config/cms.conf.templ b/nginx/config/templates/cms.conf.templ similarity index 100% rename from nginx/config/cms.conf.templ rename to nginx/config/templates/cms.conf.templ diff --git a/nginx/config/lms.conf.templ b/nginx/config/templates/lms.conf.templ similarity index 100% rename from nginx/config/lms.conf.templ rename to nginx/config/templates/lms.conf.templ