TSP MOOC Platform

A docker based platform dedicated to improve the learning experience of TSP MOOC

View project on GitHub

Create your image (and service)

Introduction to docker (and Dockerfile)

Nota: This is a quick and volontary incomplete description of what is docker and how to easily create a basic image. For a more complete understanding please visit the docker user guide

This platform is based on docker so to be able to understand how you can contribute to the platform you need to understand some basis about docker. In a nutshell, docker is a "chroot on steroids". It means that you isolate each process from in the other in what is called a container (basically its a part of the OS that is completely isolated from the OS itself). The TSP platform is composed of these containers to provide to the student reusable, ready-to-use environment for practical work; for example, in a relational database course we could provide a database with some data already present to the student. We could also provide a GUI to let the student learn easily the SQL syntax without having to install, manage or upgrade its own database and tools. Back to docker, there is two kind of things that you need to know to be able to provide these services:

  • images: an image is the file system of the system that you want to provide. It already exist many images like debian or ubuntu for a base OS, but you can also found some service already installed and configured like MySQL or WordPress. (You can browse them on the Docker Hub Registry)
  • containers: a container is a running instance of an image. An image is just a file system while the container is the piece of OS that run on that fs (this distinction permit to easily create a distributed cluster of the same software).

Okay, now how do I create my own image ? To do that, docker introduce a file: the Dockerfile. A Dockerfile is a list of instruction that are executed sequentially to create an image. For example, if I want to create an image with apache installed on a debian jessie system I would create the following Dockerfile:

FROM debian:jessie

RUN apt-get update && apt-get install apache2

In this example, we create our image on top of the debian:jessie image (FROM) and run a simple command apt-get update && apt-get install apache2 with the RUN instruction. You'll find a complete list of the Dockerfile available commands at https://docs.docker.com/reference/builder/.

We now know how to describe how to create an image, we have to effectively create this image. Do to that there is single command:

docker build path/to/Dockerfile

# You can also tag your image to easily find it afterwards
# The version is optionnal, if not specified it will be mark as latest
docker build -t image-tag-name[:version] path/to/Dockerfile

And voilà ! You now have a docker image ready to be distributed to your student (or anyone that use docker really).

Separate your container by process (and link them instead)

Docker is designed to run a single process per container, that's why the container stop when the process of the CMD instruction die. So how can we have a system with multi process ? There is many possibility: you can use a process manager, use a bash script with the & symbol (as long as the last process isn't killed) or you can stick to the docker philosophy: one process per container. In that case we need a way to make our container communicate between them. Docker provide us a way to link our container together with a functionnality called… link !

To demonstrate the concept of link we will take the example of a database (MySQL) and a managing tool for that database (phpMyAdmin). Luckily for us, there already are images of these software.

Again, this is a basic introduction to link. For a more advanced version, see the official one.

# Download the base images
docker pull mysql
docker pull corbinu/docker-phpmyadmin

# Run the MySQL server
docker run -d \
  –name mysqlcontainer \
  -e MYSQL_ROOT_PASSWORD=password \
  –expose 3306 \
  -v /var/lib/mysql \
  mysql

So with these commands we have downloaded phpmyadmin and mysql, and there are ready to use ! The third command is the one to run a MySQL database with the root password set to password, the name mysqlcontainer, we expose the port 3306 to allow connection to the database and the argument -v tell docker to store the content of the specified directory on the host machine (it will not be deleted with the container). Note that the name of this container is mandatory. We need it to be able to refer to it from our other container.

Now, we are going to run the phpmyadmin container:

# Run the
docker run -d \
  –name phpmyadmin \
  –link mysqlcontainer:mysql \
  -e MYSQL_USERNAME=root \
  -e MYSQL_PASSWORD=password \
  -p 80 \
  corbinu/docker-phpmyadmin

So what have we done with this command ? We are running the container in the background (-d), with the name of phpmyadmin (-name phpmyadmin), pass to the container two environment variable: MYSQL_USERNAME and MYSQL_PASSWORD, expose the port 80 to the host and all of that with the image corbinu/docker-phpmyadmin. And we have linked the container mysqlcontainer to our phpmyadmin container with the alias mysql. This alias is used by docker to create two principals things:

  • an entry in the /etc/hosts file. It means that from the container, we can now use the mysql uri to link to our mysql container (eg. you can ping mysql).
  • a bunch of environment variable that can help you to programmaticaly connect to the linked container (see the docker docs).

That's all, you now know how to make containers communicate between them !

Introduce services

This part is greatly linked to the TSP MOOC Overview software. If you don't use it, this section will not interest you.

This section is here to describe how you can add a service to TSP MOOC Overview. This software let the student choose what courses to install or run. It also remove all courses manual installation. To do that, we have to publish publicly the images of these courses and have a way to specify to the software how these image must be run (with a volume ? some environment variable ?). All of this is done via the config.yml file. This section is all about how to add (or remove) a service from this file.

Here is a complete example of a config.yml file:

services:
  - id: tsp-mooc-db
    completeName: Relational Database
    stack:
      - containerName: tsp-moocdb-postgres
        image: tsp-moocdb-postgres:latest
      - containerName: tsp-moocdb-web
        image: tsp-moocdb-web
  - id: django-example
    completeName: Django overview
    stack:
      - containerName: db
        image: paintedfox/postgresql
        environment:
          USER: docker
          PASS: docker
          DB: docker
      - containerName: djangodocker_web
        image: djangodocker_web
        links:
          - db
        ports:
          - "8000:8080"
        volumes:
          - .:/app

This file define many services. Each service is composed of an id and a name (completeName, it's what is displayed to the user in the GUI). Then each service must defined a stack. A stack is a representation of the state of the required docker container. The syntax is based on the fig tool.