mirror of
https://github.com/ChristianLight/tutor.git
synced 2024-12-12 14:17:46 +00:00
Easily launch multiple platforms on a single server
By using a web proxy on the host, it's now extremely easy to launch multiple platforms on a single server.
This commit is contained in:
parent
f45a24caea
commit
a70d48c6bb
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## Latest
|
## Latest
|
||||||
|
|
||||||
|
- [Feature] Multiple platforms on a single server \o/
|
||||||
- [Feature] Easily configure web proxy on the host
|
- [Feature] Easily configure web proxy on the host
|
||||||
- [Bugfix] Fix `images pull all` command which failed on "all" image
|
- [Bugfix] Fix `images pull all` command which failed on "all" image
|
||||||
- [Improvement] Add configurable mongodb, SMTP and rabbitmq authentication
|
- [Improvement] Add configurable mongodb, SMTP and rabbitmq authentication
|
||||||
|
@ -148,6 +148,36 @@ If you have configured your platform to use SSL/TLS certificates for HTTPS acces
|
|||||||
tutor local https create
|
tutor local https create
|
||||||
tutor local https renew
|
tutor local https renew
|
||||||
|
|
||||||
|
Running multiple Open edX platforms on a single server
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
With Tutor, it is easy to run multiple Open edX instances on a single server. To do so, the following configuration parameters must be different for all platforms:
|
||||||
|
|
||||||
|
- ``TUTOR_ROOT``: so that configuration, environment and data are not mixed up between platforms.
|
||||||
|
- ``LOCAL_PROJECT_NAME``: the various docker-compose projects cannot share the same name.
|
||||||
|
- ``NGINX_HTTP_PORT``, ``NGINX_HTTPS_PORT``: ports cannot be shared by two different containers.
|
||||||
|
- ``LMS_HOST``, ``CMS_HOST``: the different platforms must be accessible from different domain (or subdomain) names.
|
||||||
|
|
||||||
|
In addition, a web proxy must be setup on the host, as described :ref:`above <web_proxy>`.
|
||||||
|
|
||||||
|
As an example, here is how to launch two different platforms, with nginx running as a web proxy:
|
||||||
|
|
||||||
|
# platform 1
|
||||||
|
export TUTOR_ROOT=~/openedx/site1
|
||||||
|
tutor config save --set WEB_PROXY=true --set LOCAL_PROJECT_NAME=tutor_site1 --set NGINX_HTTP_PORT=81 --set NGINX_HTTPS_PORT=481
|
||||||
|
tutor local quickstart
|
||||||
|
sudo ln -s $(tutor config printroot)/env/local/proxy/nginx/openedx.conf /etc/nginx/sites-enabled/site1.conf
|
||||||
|
|
||||||
|
|
||||||
|
# platform 2
|
||||||
|
export TUTOR_ROOT=~/openedx/site2
|
||||||
|
tutor config save --set WEB_PROXY=true --set LOCAL_PROJECT_NAME=tutor_site2 --set NGINX_HTTP_PORT=82 --set NGINX_HTTPS_PORT=482
|
||||||
|
tutor local quickstart
|
||||||
|
sudo ln -s $(tutor config printroot)/env/local/proxy/nginx/openedx.conf /etc/nginx/sites-enabled/site2.conf
|
||||||
|
|
||||||
|
You should then have two different platforms, completely isolated from one another, running on the same server.
|
||||||
|
|
||||||
|
|
||||||
Loading different production settings for ``edx-platform``
|
Loading different production settings for ``edx-platform``
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ If you'd rather use a graphical user interface for viewing logs, you are encoura
|
|||||||
"Cannot start service nginx: driver failed programming external connectivity"
|
"Cannot start service nginx: driver failed programming external connectivity"
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
The containerized Nginx needs to listen to ports 80 and 443 on the host. If there is already a webserver, such as Apache or Nginx, running on the host, the nginx container will not be able to start. To solve this issue, check :ref:`web_proxy`.
|
The containerized Nginx needs to listen to ports 80 and 443 on the host. If there is already a webserver, such as Apache or Nginx, running on the host, the nginx container will not be able to start. To solve this issue, check :ref:`out to setup a web proxy <web_proxy>`.
|
||||||
|
|
||||||
Help! The Docker containers are eating all my RAM/CPU/CHEESE
|
Help! The Docker containers are eating all my RAM/CPU/CHEESE
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
@ -22,9 +22,7 @@ from . import ops
|
|||||||
def local():
|
def local():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@click.command(
|
@click.command(help="Configure and run Open edX from scratch")
|
||||||
help="Configure and run Open edX from scratch"
|
|
||||||
)
|
|
||||||
@click.option("-p", "--pullimages", "pullimages_", is_flag=True, help="Update docker images")
|
@click.option("-p", "--pullimages", "pullimages_", is_flag=True, help="Update docker images")
|
||||||
@opts.root
|
@opts.root
|
||||||
def quickstart(pullimages_, root):
|
def quickstart(pullimages_, root):
|
||||||
@ -42,16 +40,13 @@ def quickstart(pullimages_, root):
|
|||||||
click.echo(fmt.title("Starting the platform in detached mode"))
|
click.echo(fmt.title("Starting the platform in detached mode"))
|
||||||
start.callback(root, True)
|
start.callback(root, True)
|
||||||
|
|
||||||
@click.command(
|
@click.command(help="Update docker images")
|
||||||
help="Update docker images",
|
|
||||||
)
|
|
||||||
@opts.root
|
@opts.root
|
||||||
def pullimages(root):
|
def pullimages(root):
|
||||||
docker_compose(root, "pull")
|
config = tutor_config.load(root)
|
||||||
|
docker_compose(root, config, "pull")
|
||||||
|
|
||||||
@click.command(
|
@click.command(help="Run all configured Open edX services")
|
||||||
help="Run all configured Open edX services",
|
|
||||||
)
|
|
||||||
@opts.root
|
@opts.root
|
||||||
@click.option("-d", "--detach", is_flag=True, help="Start in daemon mode")
|
@click.option("-d", "--detach", is_flag=True, help="Start in daemon mode")
|
||||||
def start(root, detach):
|
def start(root, detach):
|
||||||
@ -59,11 +54,11 @@ def start(root, detach):
|
|||||||
if detach:
|
if detach:
|
||||||
command.append("-d")
|
command.append("-d")
|
||||||
|
|
||||||
docker_compose(root, *command)
|
config = tutor_config.load(root)
|
||||||
|
docker_compose(root, config, *command)
|
||||||
|
|
||||||
if detach:
|
if detach:
|
||||||
click.echo(fmt.info("The Open edX platform is now running in detached mode"))
|
click.echo(fmt.info("The Open edX platform is now running in detached mode"))
|
||||||
config = tutor_config.load(root)
|
|
||||||
http = "https" if config["ACTIVATE_HTTPS"] else "http"
|
http = "https" if config["ACTIVATE_HTTPS"] else "http"
|
||||||
urls = []
|
urls = []
|
||||||
if not config["ACTIVATE_HTTPS"] and not config["WEB_PROXY"]:
|
if not config["ACTIVATE_HTTPS"] and not config["WEB_PROXY"]:
|
||||||
@ -81,7 +76,8 @@ def start(root, detach):
|
|||||||
@click.command(help="Stop a running platform",)
|
@click.command(help="Stop a running platform",)
|
||||||
@opts.root
|
@opts.root
|
||||||
def stop(root):
|
def stop(root):
|
||||||
docker_compose(root, "rm", "--stop", "--force")
|
config = tutor_config.load(root)
|
||||||
|
docker_compose(root, config, "rm", "--stop", "--force")
|
||||||
|
|
||||||
@click.command(
|
@click.command(
|
||||||
help="""Restart some components from a running platform.
|
help="""Restart some components from a running platform.
|
||||||
@ -96,7 +92,8 @@ def restart(root, service):
|
|||||||
command += ["lms", "cms", "lms_worker", "cms_worker"]
|
command += ["lms", "cms", "lms_worker", "cms_worker"]
|
||||||
elif service != "all":
|
elif service != "all":
|
||||||
command += [service]
|
command += [service]
|
||||||
docker_compose(root, *command)
|
config = tutor_config.load(root)
|
||||||
|
docker_compose(root, config, *command)
|
||||||
|
|
||||||
@click.command(
|
@click.command(
|
||||||
help="Run a command in one of the containers",
|
help="Run a command in one of the containers",
|
||||||
@ -116,7 +113,8 @@ def run(root, service, command, args):
|
|||||||
run_command.append(command)
|
run_command.append(command)
|
||||||
if args:
|
if args:
|
||||||
run_command += args
|
run_command += args
|
||||||
docker_compose(root, *run_command)
|
config = tutor_config.load(root)
|
||||||
|
docker_compose(root, config, *run_command)
|
||||||
|
|
||||||
@click.command(
|
@click.command(
|
||||||
help="Create databases and run database migrations",
|
help="Create databases and run database migrations",
|
||||||
@ -134,16 +132,18 @@ def init_mysql(root):
|
|||||||
if os.path.exists(mysql_data_path):
|
if os.path.exists(mysql_data_path):
|
||||||
return
|
return
|
||||||
click.echo(fmt.info("Initializing MySQL database..."))
|
click.echo(fmt.info("Initializing MySQL database..."))
|
||||||
docker_compose(root, "up", "-d", "mysql")
|
docker_compose(root, config, "up", "-d", "mysql")
|
||||||
while True:
|
while True:
|
||||||
click.echo(fmt.info(" waiting for mysql initialization"))
|
click.echo(fmt.info(" waiting for mysql initialization"))
|
||||||
|
# TODO this is duplicate code with the docker_compose function. We
|
||||||
|
# should rely on a dedicated function in utils module.
|
||||||
logs = subprocess.check_output([
|
logs = subprocess.check_output([
|
||||||
"docker-compose", "-f", tutor_env.pathjoin(root, "local", "docker-compose.yml"),
|
"docker-compose", "-f", tutor_env.pathjoin(root, "local", "docker-compose.yml"),
|
||||||
"--project-name", "tutor_local", "logs", "mysql",
|
"--project-name", config["LOCAL_PROJECT_NAME"], "logs", "mysql",
|
||||||
])
|
])
|
||||||
if b"MySQL init process done. Ready for start up." in logs:
|
if b"MySQL init process done. Ready for start up." in logs:
|
||||||
click.echo(fmt.info("MySQL database initialized"))
|
click.echo(fmt.info("MySQL database initialized"))
|
||||||
docker_compose(root, "stop", "mysql")
|
docker_compose(root, config, "stop", "mysql")
|
||||||
return
|
return
|
||||||
sleep(4)
|
sleep(4)
|
||||||
|
|
||||||
@ -219,7 +219,8 @@ def logs(root, follow, tail, service):
|
|||||||
if tail is not None:
|
if tail is not None:
|
||||||
command += ["--tail", str(tail)]
|
command += ["--tail", str(tail)]
|
||||||
command += service
|
command += service
|
||||||
docker_compose(root, *command)
|
config = tutor_config.load(root)
|
||||||
|
docker_compose(root, config, *command)
|
||||||
|
|
||||||
@click.command(help="Create an Open edX user and interactively set their password")
|
@click.command(help="Create an Open edX user and interactively set their password")
|
||||||
@opts.root
|
@opts.root
|
||||||
@ -261,12 +262,13 @@ def portainer(root, port):
|
|||||||
utils.docker_run(*docker_run)
|
utils.docker_run(*docker_run)
|
||||||
|
|
||||||
def run_bash(root, service, command):
|
def run_bash(root, service, command):
|
||||||
docker_compose(root, "run", "--rm", service, "bash", "-e", "-c", command)
|
config = tutor_config.load(root)
|
||||||
|
docker_compose(root, config, "run", "--rm", service, "bash", "-e", "-c", command)
|
||||||
|
|
||||||
def docker_compose(root, *command):
|
def docker_compose(root, config, *command):
|
||||||
return utils.docker_compose(
|
return utils.docker_compose(
|
||||||
"-f", tutor_env.pathjoin(root, "local", "docker-compose.yml"),
|
"-f", tutor_env.pathjoin(root, "local", "docker-compose.yml"),
|
||||||
"--project-name", "tutor_local",
|
"--project-name", config["LOCAL_PROJECT_NAME"],
|
||||||
*command
|
*command
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ DOCKER_IMAGE_NGINX: "nginx:1.13"
|
|||||||
DOCKER_IMAGE_RABBITMQ: "rabbitmq:3.6.10"
|
DOCKER_IMAGE_RABBITMQ: "rabbitmq:3.6.10"
|
||||||
DOCKER_IMAGE_SMTP: "namshi/smtp:latest"
|
DOCKER_IMAGE_SMTP: "namshi/smtp:latest"
|
||||||
DOCKER_REGISTRY: ""
|
DOCKER_REGISTRY: ""
|
||||||
|
LOCAL_PROJECT_NAME: "tutor_local"
|
||||||
ELASTICSEARCH_HOST: "elasticsearch"
|
ELASTICSEARCH_HOST: "elasticsearch"
|
||||||
ELASTICSEARCH_PORT: 9200
|
ELASTICSEARCH_PORT: 9200
|
||||||
MEMCACHED_HOST: "memcached"
|
MEMCACHED_HOST: "memcached"
|
||||||
|
Loading…
Reference in New Issue
Block a user