Working devstack

This allows the user to run their own devstack inside the containers.
Yay!

Also, we handle file permissions cleanly: in docker-entrypoint.sh we
chmod the data and edx-platform files to the same UID of the user on the
host machine. No more permission headaches!
This commit is contained in:
Régis Behmo 2018-04-09 19:16:58 +02:00 committed by Régis B
parent 1f0509be2b
commit 1f7e68c662
6 changed files with 168 additions and 50 deletions

View File

@ -1,8 +1,19 @@
.PHONY: all configure build migrate assets up daemon
DOCKER_COMPOSE_RUN = docker-compose run --rm -e USERID="$$(id -u)"
ifneq ($(EDX_PLATFORM_SETTINGS),)
DOCKER_COMPOSE_RUN += -e SETTINGS=$(EDX_PLATFORM_SETTINGS)
endif
ifneq ($(EDX_PLATFORM_PATH),)
DOCKER_COMPOSE_RUN += --volume="$(EDX_PLATFORM_PATH):/openedx/edx-platform"
endif
DOCKER_COMPOSE_RUN_LMS = $(DOCKER_COMPOSE_RUN) -p 8000:8000 lms
DOCKER_COMPOSE_RUN_CMS = $(DOCKER_COMPOSE_RUN) -p 8001:8001 cms
all: configure build migrate assets daemon
##################### Bootstrapping commands
##################### Bootstrapping
configure:
./configure
@ -11,14 +22,14 @@ build:
docker-compose build
migrate:
docker-compose run --rm lms bash -c "./wait-for-greenlight.sh && ./manage.py lms --settings=production migrate"
docker-compose run --rm cms bash -c "./wait-for-greenlight.sh && ./manage.py cms --settings=production migrate"
$(DOCKER_COMPOSE_RUN_LMS) bash -c "wait-for-greenlight.sh && ./manage.py lms migrate"
$(DOCKER_COMPOSE_RUN_CMS) bash -c "wait-for-greenlight.sh && ./manage.py cms migrate"
assets:
docker-compose run --rm lms paver update_assets lms --settings=production
docker-compose run --rm cms paver update_assets cms --settings=production
$(DOCKER_COMPOSE_RUN_LMS) paver update_assets lms
$(DOCKER_COMPOSE_RUN_CMS) paver update_assets cms
##################### Running commands
##################### Running
up:
docker-compose up
@ -30,16 +41,24 @@ daemon:
stop:
docker-compose stop
##################### Additional commands
lms-shell:
docker-compose run --rm lms ./manage.py lms --settings=production shell
cms-shell:
docker-compose run --rm lms ./manage.py cms --settings=production shell
##################### Extra
import-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"
# Seed the course permissions: is it necessary? "./manage.py lms --settings=production seed_permissions_roles 'course-v1:edX+DemoX+Demo_Course'"
$(DOCKER_COMPOSE_RUN_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 import ../data ../edx-demo-course"
# Seed the course permissions: is it necessary? "./manage.py lms seed_permissions_roles 'course-v1:edX+DemoX+Demo_Course'"
create-staff-user:
docker-compose run --rm lms /bin/bash -c "./manage.py lms --settings=production manage_user --superuser --staff ${USERNAME} ${EMAIL} && ./manage.py lms --settings=production changepassword ${USERNAME}"
$(DOCKER_COMPOSE_RUN_LMS) /bin/bash -c "./manage.py lms manage_user --superuser --staff ${USERNAME} ${EMAIL} && ./manage.py lms changepassword ${USERNAME}"
##################### Development
lms:
$(DOCKER_COMPOSE_RUN_LMS) bash
cms:
$(DOCKER_COMPOSE_RUN_CMS) bash
lms-shell:
$(DOCKER_COMPOSE_RUN_LMS) ./manage.py lms shell
cms-shell:
$(DOCKER_COMPOSE_RUN_LMS) ./manage.py cms shell

View File

@ -1,8 +1,13 @@
# Open edX quick install (in Docker containers)
This is a **one-click production install of [Open edX](https://openedx.org)**.
This is a **one-click install of [Open edX](https://openedx.org), both for production and local development**.
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.
The deployment of a full-featured Open edX platform is a highly technical and complex project. Here, we greatly simplify it by:
1. relying on pre-configured Docker containers for external services, such as MySQL and MongoDb
2. activating only a subset of all Open edX features
We made this project 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.
## Quickstart
@ -10,9 +15,9 @@ All you have to do is [download the content of this repository](https://codeload
make all
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.
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, ready for production. You should be able to access your platform at the address you gave during the configuration phase.
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.
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. Also, instructions are given to setup a local development environment.
## Requirements
@ -22,7 +27,7 @@ The only prerequisite for running this is Python and a working docker install. Y
- [Docker install](https://docs.docker.com/engine/installation/)
- [Docker compose install](https://docs.docker.com/compose/install/)
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.
Note that the production 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.
@ -49,6 +54,8 @@ Building the images may require a long time, depending on your bandwidth, as you
These commands should be run just once. They will create the database tables and generate static assets, such as images, stylesheets and Javascript dependencies.
If migrations are stopped with a `Killed` message, this certainly means the docker containers don't have enough RAM. See the [troubleshooting](#troubleshooting) section.
### Running Open edX
make up
@ -83,15 +90,19 @@ And then, to stop all services:
### Logging
To view the logs from all containers:
To view the logs from all containers use the [`docker-compose logs`](https://docs.docker.com/compose/reference/logs/) command:
docker-compose logs -f
To view the logs from just one container, for instance the web server:
docker-compose logs -f
docker-compose logs -f nginx
### Development
The last commands produce the logs since the creation of the containers, which can be a lot. Similar to a `tail -f`, you can run:
docker-compose logs --tail=0 -f
### Debugging
Open a bash in the lms:
@ -102,6 +113,74 @@ Open a python shell in the lms or the cms:
make lms-shell
make cms-shell
## For developers
In addition to running Open edX in production, you can use the docker containers for local development. This means you can hack on Open edX without setting up a Virtual Machine. Essentially, this replaces the devstack provided by edX.
First, configure your project such that the LMS and the CMS can be accessed locally:
make configure
...
Your website domain name for students (LMS) (default: "www.myopenedx.com"): localhost:8000
Your website domain name for teachers (CMS) (default: "studio.myopenedx.com"): localhost:8001
...
Then, build the images and prepare the database:
make build
make migrate
Point to your local install of [edx-platform](https://github.com/edx/edx-platform/) on your host machine:
export EDX_PLATFORM_PATH=/path/to/your/edx-platform
Point to your settings file:
export EDX_PLATFORM_SETTINGS=development
In this example, you should have a `development.py` file in `edx-platform/lms/envs` and `edx-platform/cms/envs`. Here is a minimal settings file:
from .devstack import *
# Load module store settings from config files
update_module_store_settings(MODULESTORE, doc_store_settings=DOC_STORE_CONFIG)
# Set uploaded media file path
MEDIA_ROOT = "/openedx/data/uploads/"
# Deactivate forums
FEATURES['ENABLE_DISCUSSION_SERVICE'] = False
# 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
import os
for folder in [LOG_DIR, MEDIA_ROOT, STATIC_ROOT_BASE]:
if not os.path.exists(folder):
os.makedirs(folder)
You are ready to go! Run:
make lms
Or:
make cms
This will open a shell in the LMS container. You can then run just any command you are used to. For example:
paver lms
This will collect assets and run a development server which will **automatically reload** after you make changes to your edx-platform repository.
Note that the containers are built on the Ginkgo release. If you are working on a different version of Open edX, you will have to rebuild the images with a different `EDX_PLATFORM_VERSION` argument. You may also want to change the `EDX_PLATFORM_REPOSITORY` argument to point to your own fork of edx-platform.
## Troubleshooting
### "Running migrations... Killed!"

View File

@ -56,8 +56,8 @@ services:
lms:
build:
context: ./edxapp
args:
service_variant: lms
environment:
SERVICE_VARIANT: lms
restart: unless-stopped
volumes:
- ./data/lms:/openedx/data
@ -71,8 +71,8 @@ services:
cms:
build:
context: ./edxapp
args:
service_variant: cms
environment:
SERVICE_VARIANT: cms
restart: unless-stopped
volumes:
- ./data/cms:/openedx/data
@ -85,9 +85,9 @@ services:
lms_worker:
build:
context: ./edxapp
args:
service_variant: lms
command: ./manage.py lms --settings=production celery worker --loglevel=info --hostname=edx.lms.core.default.%%h --maxtasksperchild 100
environment:
SERVICE_VARIANT: lms
command: ./manage.py lms celery worker --loglevel=info --hostname=edx.lms.core.default.%%h --maxtasksperchild 100
restart: unless-stopped
environment:
C_FORCE_ROOT: "1" # run celery tasks as root #nofear
@ -99,9 +99,9 @@ services:
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:
SERVICE_VARIANT: cms
command: ./manage.py cms celery worker --loglevel=info --hostname=edx.cms.core.default.%%h --maxtasksperchild 100
restart: unless-stopped
environment:
C_FORCE_ROOT: "1" # run celery tasks as root #nofear

View File

@ -23,15 +23,19 @@ VOLUME /openedx/data
WORKDIR /openedx/edx-platform
## Checkout edx-platform code
RUN git clone https://github.com/edx/edx-platform.git --branch open-release/ginkgo.master --depth 1 .
ARG EDX_PLATFORM_REPOSITORY=https://github.com/edx/edx-platform.git
ARG EDX_PLATFORM_VERSION=open-release/ginkgo.master
RUN git clone $EDX_PLATFORM_REPOSITORY --branch $EDX_PLATFORM_VERSION --depth 1 .
VOLUME /openedx/edx-platform
# Install python requirements
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
# Install python requirements (clone source repos in a separate dir, otherwise
# will be overwritten when we mount edx-platform)
RUN pip install --src ../venv/src -r requirements/edx/pre.txt
RUN pip install --src ../venv/src -r requirements/edx/github.txt
RUN pip install --src ../venv/src -r requirements/edx/local.txt
RUN pip install --src ../venv/src -r requirements/edx/base.txt
RUN pip install --src ../venv/src -r requirements/edx/post.txt
RUN pip install --src ../venv/src -r requirements/edx/paver.txt
# Install nodejs requirements
RUN npm install
@ -46,17 +50,16 @@ COPY ./config/cms.env.json /openedx/
COPY ./config/lms.auth.json /openedx/
COPY ./config/cms.auth.json /openedx/
# Copy convenient script
COPY ./wait-for-greenlight.sh .
############ End of code common to lms & cms
# Copy convenient scripts
COPY ./wait-for-greenlight.sh /usr/local/bin/
COPY ./docker-entrypoint.sh /usr/local/bin/
# service variant is "lms" or "cms"
ARG service_variant
ENV SERVICE_VARIANT lms
ENV SETTINGS production
# Configure environment
ENV DJANGO_SETTINGS_MODULE ${service_variant}.envs.production
ENV SERVICE_VARIANT ${service_variant}
# Entrypoint will fix permissiosn of all files and run commands as openedx
ENTRYPOINT ["docker-entrypoint.sh"]
# Run server
EXPOSE 8000

17
edxapp/docker-entrypoint.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash -e
export DJANGO_SETTINGS_MODULE=$SERVICE_VARIANT.envs.$SETTINGS
USERID=${USERID:=1000}
## Configure user with a different USERID if requested.
if [ "$USERID" -ne 1000 ]
then
echo "creating new user 'openedx' with UID $USERID"
useradd -m openedx -u $USERID
chown -R openedx /openedx
# Run CMD as different user
exec chroot --userspec="$USERID" --skip-chdir / "$@"
else
# Run CMD as root (business as usual)
exec "$@"
fi

View File

@ -1,7 +1,7 @@
#!/bin/bash
echo "Checking system..."
until ./manage.py lms --settings=production check
until ./manage.py $SERVICE_VARIANT check
do
printf "."
sleep 1