Tutoriaux

Docker est un logiciel libre qui automatise le déploiement d'applications dans des conteneurs logiciels s'executant en isolation. Un container Docker, à l'opposé de machines virtuelles traditionnelles, ne requiert aucun système d'exploitation séparé et n'en fournit aucun mais s'appuie plutôt sur les fonctionnalités du noyau et utilise l'isolation de ressources ainsi que des espaces de noms séparés pour isoler le système d'exploitation tel que vu par l'application.

Architecture du cluster


Espaces de données

Les utilisateurs du cluster de calcul ont accès à deux espaces de stockage :

  • Joule : espace destiné au stockage uniquement.
  • Scratch : espace destiné aux calculs uniquement. Attention, cet espace n'est pas sauvegardé.
Chemin Type Accessible depuis Utilisation Performance Sauvegardé
/home/joule/ NFS noeuds de calcul espace de stockage moyenne non
/scratch/user/ Lustre noeuds de calcul + conteneurs espace de travail élevée non

Exécuter un programme contenu dans une image

Pour des raisons de sécurité, les conteneurs ne montent que l'espace de travail de l'utilisateur (/scratch/user/). Il faut donc s'assurer d'être dans le bon dossier avant de soumettre toute commande :

cd /scratch/user/[LOGIN]

Exemple :

cd /scratch/user/rey

Pour exécuter un programme :

drun [NOM DE L'IMAGE] [COMMANDE À EXÉCUTER]

Exemple :

drun faf-drugs python /usr/local/FAF-Drugs/bin/FAFDrugs.py -D 103_c.sdf -f drug -p xlogp3 -g --painsa --painsb --painsc --regular
Attention : Les conteneurs sont des espaces virtualisés dont le contenu est supprimé après son exécution. Toute donnée non écrite dans le dossier /scratch/user/ de l'utilisateur sera perdue.
Remarque : Il est possible d'utiliser le dossier /tmp/ d'un conteneur pour y stocker des fichiers temporaires qui seront supprimés automatiquement à la fin de l'exécution.

Quelques images de services et chemins vers les programmes :

Image Ligne de commande
faf-drugs /usr/local/FAF-Drugs/bin/FAFDrugs.py
frog2 www_iMolecule
opendocking babel
pdb2mol2
pdbqt2pdb
/usr/share/pyshared/AutoDockTools/Utilities24/prepare_ligand4.py
/usr/share/pyshared/AutoDockTools/Utilities24/prepare_receptor4.py
vina
autodock4

Soumettre un job sur le cluster

Commande de base

La commande de base pour soumettre un job est la suivante :

srun [COMMANDE À EXÉCUTER]

Pour soumettre un job avec un exécutable contenu dans une image, on doit donc combiner les deux commandes :

srun drun [NOM DE L'IMAGE] [COMMANDE À EXÉCUTER]

Utilisation de scripts batch

Pour soumettre des jobs en batch :

sbatch [SCRIPT.Q]

Exemple de script batch :

#!/bin/bash
#SBATCH --output=test.out
#SBATCH --array=1-5
case "$SLURM_ARRAY_TASK_ID" in 
   1) fichier='/scratch/user/rey/protein_1';;
   2) fichier='/scratch/user/rey/protein_2';;
   3) fichier='/scratch/user/rey/protein_3';;
   4) fichier='/scratch/user/rey/protein_4';;
   5) fichier='/scratch/user/rey/protein_5';;
esac
drun opendocking babel -i ${fichier}.pdb -o ${fichier}.mol2

Utilisation de la bibliothèque python cluster (experts)

Les développeurs disposent également d'une bibliothèque permettant la soumission de jobs directement depuis un script python. Pour l'instant la bibliothèque ne comporte qu'une seule fonction utilisable, mais ceci peut être amené à évoluer. La plupart des fonctions font usage de la bibliothèque python-drmaa pour soumettre des jobs via Slurm.

  • runTasks(command, args, tasks = 1, tasks_from = 1, docker_img = "opendocking", log_prefix = None, map_list = None, job_opts = '', joinFiles = True, progress = True)

    • command : chemin vers l'exécutable à l'intérieur du conteneur.
    • args : un tableau contenant les arguments à passer à la commande.
    • tasks : nombre de tâches à accomplir (job array). Chaque itération incrémente d'une unité la variable d'environnement TASK_ID accessible depuis les conteneurs.
    • tasks_from : valeur initiale pour la variable d'environnement TASK_ID.
    • docker_img : nom de l'image Docker à invoquer.
    • log_prefix : préfix du fichier de logs retourné par le conteneur. Prend par défaut le nom de l'image invoquée.
    • map_list : surcharge le paramètre tasks. Tableau contenant une liste de fichiers sur laquelle la fonction va boucler. Chaque fichier est accessible depuis un conteneur grâce à la variable d'environnement $(mapped_file ${TASK_ID}). Nécessite l'installation d'un interpréteur python dans l'image invoquée.
    • job_opts : ajouter des options de paramétrage pour Slurm.
    • joinFiles : fusionner tous les fichiers de logs en un seul. Si paramétré sur False, un fichier de log sera créé par tâche.
    • progress : ?

Exemple simple de script python utilisant la bibliothèque cluster :

#!/usr/bin/env python

import cluster

cmd = "PyPPPExec"

args = ["-s %s" % self.options.pepseq,
                    "-l %s" % self.options.label,
                    "--2012",
                    "-v"]
                    
cluster.runTasks(cmd, args, docker_img = "pep-sitefinder")

Erreurs fréquentes

  • -bash-4.2$ drun opendocking babel -i protein.pdb -o protein.mol2
    /bin/bash: line 0: cd: /home/joule/rey: No such file or directory

    Pour des raisons de sécurité, les conteneurs ne montent que l'espace de travail de l'utilisateur (/scratch/user/[LOGIN]). Il faut donc s'assurer d'être dans son dossier /scratch/user/[LOGIN].

Debian / Ubuntu

Debian 7 / Ubuntu 14.04

Docker est disponible dans les dépôts à partir de la version 14.04 d'Ubuntu et à partir de la version 7.7 de Debian :

sudo apt-get install docker.io

Afin de pouvoir utiliser les registres, les clients doivent pouvoir résoudre le nom DNS de la machine :

sudo echo "172.27.7.35  dev-registry.rpbs.univ-paris-diderot.fr docker-registry.rpbs.univ-paris-diderot.fr" >> /etc/hosts

Éditer le fichier /etc/default/docker et modifier la ligne suivante de cette façon :

DOCKER_OPTS="--dns 194.254.200.25 --insecure-registry dev-registry.rpbs.univ-paris-diderot.fr --insecure-registry docker-registry.rpbs.univ-paris-diderot.fr"

Pour utiliser Docker il faut soit posséder les droits administrateur (par exemple en utilisant la commande sudo), soit être présent dans le groupe docker. Pour éviter de devoir taper sudo devant chaque commande, il faut ajouter l'utilisateur au groupe docker :

adduser [ LOGIN ] docker

Exemple :

adduser rey docker

Debian 8

Le paquet docker.io a été retiré des dépôts officiels. Il faut donc ajouter le dépôt suivant :

sudo echo "deb https://apt.dockerproject.org/repo debian-jessie main" > /etc/apt/sources.list.d/docker.list

Télécharger la clé gpg :

apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

Mettre à jour la liste des paquets :

sudo apt-get update

Installer le paquet docker-engine :

sudo apt-get install docker-engine

Éditer le fichier /etc/default/docker et modifier la ligne suivante de cette façon :

DOCKER_OPTS="--dns 194.254.200.25 --insecure-registry dev-registry.rpbs.univ-paris-diderot.fr --insecure-registry docker-registry.rpbs.univ-paris-diderot.fr"

Éditer le fichier /lib/systemd/system/docker.service et modifier la section [Service] de façon à ce que les deux lignes suivantes y figurent :

[Service]
EnvironmentFile=-/etc/default/docker
ExecStart=/usr/bin/docker daemon -H fd:// $DOCKER_OPTS

Démarrer le démon docker :

sudo service docker start

Pour utiliser Docker il faut soit posséder les droits administrateur (par exemple en utilisant la commande sudo), soit être présent dans le groupe docker. Pour éviter de devoir taper sudo devant chaque commande, il faut ajouter l'utilisateur au groupe docker :

adduser [ LOGIN ] docker

Exemple :

adduser rey docker

Fedora

Fedora est disponible pour les versions suivantes de Fedora :

  • Fedora 20
  • Fedora 21
  • Fedora 22

Télécharger le paquet correspondant à sa version :

Version Nom du paquet
Fedora 20 docker-engine-1.7.1-1.fc20.x86_64.rpm
Fedora 21 docker-engine-1.7.1-1.fc21.x86_64.rpm
Fedora 22 docker-engine-1.7.1-1.fc22.x86_64.rpm

Installer le paquet :

sudo yum localinstall --nogpgcheck docker-engine-1.7.1-0.1.fc21.x86_64.rpm

Démarrer le démon Docker

sudo service docker start

Afin de pouvoir utiliser les registres, les clients doivent pouvoir résoudre le nom DNS de la machine :

sudo echo "172.27.7.35  dev-registry.rpbs.univ-paris-diderot.fr docker-registry.rpbs.univ-paris-diderot.fr" >> /etc/hosts

Éditer le fichier /etc/sysconfig/docker et modifier la ligne suivante de cette façon :

other_args="--dns 194.254.200.25 --insecure-registry dev-registry.rpbs.univ-paris-diderot.fr --insecure-registry docker-registry.rpbs.univ-paris-diderot.fr"

Pour utiliser Docker il faut soit posséder les droits administrateur (par exemple en utilisant la commande sudo), soit être présent dans le groupe docker. Pour éviter de devoir taper sudo devant chaque commande, il faut créer le groupe docker et ajouter l'utilisateur à ce groupe :

sudo usermod -aG docker [ LOGIN ]

Exemple :

sudo usermod -aG docker rey

Pour que Docker démarre automatiquement au boot du système :

sudo chkconfig docker on

Mac OS

Docker ne fonctionne pas nativement sous OS X. Il est nécessaire d'installer l'application Boot2Docker qui inclut une machine virtuelle (VM) VirtualBox, le logiciel Docker et l'outil de gestion Boot2Docker :

  1. Se rendre sur la page suivante.
  2. Télécharger Boot2Docker en cliquant sur Boot2Docker-x.x.x.pkg dans la section Download.
  3. Installer Boot2Docker en double-cliquant sur le paquet.

Afin de rendre le client Docker utilisable, il faut le personnaliser. D'abord vérifier que l'application Boot2Docker est lancée en tapant dans un terminal :

docker ps

Si un message d'erreur apparaît :

boot2docker up

Se connecter à la VM Boot2Docker :

boot2docker ssh

Puis éditer le script de démarrage :

touch /var/lib/boot2docker/bootlocal.sh
chmod +x /var/lib/boot2docker/bootlocal.sh
sudo vi /var/lib/boot2docker/bootlocal.sh

Et y copier/coller le contenu suivant :

#!/bin/sh
#Hostname setup
echo "172.27.7.35 dev-registry.rpbs.univ-paris-diderot.fr docker-registry.rpbs.univ-paris-diderot.fr" >> /etc/hosts

Éditer le fichier de configuration du démon Docker

sudo vi /var/lib/boot2docker/profile

Et modifier la ligne suivante :

EXTRA_ARGS="--dns 194.254.200.25 --insecure-registry dev-registry.univ-paris-diderot.fr --insecure-registry docker-registry.rpbs.univ-paris-diderot.fr"

Stopper et relancer la VM

exit
boot2docker down
boot2docker up

Vérifier que tout fonctionne en réalisant une recherche sur le registre de développement :

docker search dev-registry.univ-paris-diderot.fr/library

Manipulation d'images

Une image est un template à partir duquel on va exécuter des conteneurs.

Lister les images présentes sur sa machine :

docker images

Chercher des images hébergées sur le registre officiel Docker :

docker search centos      # exemple d'une recherche d'une distribution centos
docker search gitlab      # exemple d'une recherche d'un serveur gitlab
Remarque : Si aucune adresse n'est précisée, Docker cherchera sur le registre officiel Docker. Pour chercher une image présente sur les registres du laboratoire il faut donc préciser l'adresse comme expliqué ci-dessous.

Lister les images hébergées sur le registre de développement du laboratoire :

docker search dev-registry.rpbs.univ-paris-diderot.fr/library

Lister les images hébergées sur le registre de production du laboratoire :

docker search docker-registry.rpbs.univ-paris-diderot.fr/library

Télécharger une image sur sa machine depuis le registre officiel Docker :

docker pull debian:stable

Télécharger une image sur sa machine depuis le registre de production du laboratoire :

docker pull docker-registry.rpbs.univ-paris-diderot.fr/opendocking
Remarque : Télécharger une image écrasera celle présente sur la machine locale.

Pour renommer une image locale :

docker tag [ID DE L'IMAGE] [NOUVEAU NOM DE L'IMAGE]

Pour effacer une image locale :

docker rmi [ID DE L'IMAGE]
Remarque : Si une instance de cette image (conteneur) existe, Docker affichera une erreur. Il faut alors soit utiliser l'option -f, soit effacer les conteneurs avant.

Manipulation des conteneurs

Un conteneur est une instance d'exécution créée à partir d'un template (image).

Démarrer un conteneur en mode intéractif à partir d'une image :

docker run -it debian:stable /bin/bash
Remarque : Docker privilégiera toujours les images présentes sur la machine locale. Si l'image n'est pas présente localement, cette dernière sera téléchargée automatiquement. Pour mettre à jour l'image locale il faut donc d'abord soit effacer l'image locale, soit la retélécharger manuellement avec la commande docker pull.

En mode intéractif, le prompt du shell est modifié et affiche désormais l'identifiant du conteneur en cours d'exécution.

root@29d4663f7b11:~# _
Remarque : L'utilisateur par défaut est root.

Le conteneur se comporte de la même façon qu'une machine virtuelle. L'utilisateur est administrateur de cette machine (compte root), il est alors possible de réaliser des installations ou de modifier des fichiers sytème sans aucune incidence sur la machine hôte.

Pour sortir / couper le conteneur :

exit

ou encore :

Ctrl + D
Remarque : Par défault, le conteneur arrêté n'est pas effacé. Pour effacer le conteneur automatiquement après son arrêt il faut utiliser l'option --rm avec la commande docker run.

Pour lister les conteneurs (y compris ceux qui ont été stoppés) :

docker ps -a

Pour redémarrer un conteneur qui a été stoppé :

docker start -a -i [ID DU CONTENEUR]

Pour effacer un conteneur stoppé :

docker rm [ID DU CONTENEUR]

Commandes avancées

Effacer les conteneurs arrêtés :

docker ps -a | grep Exit | cut -d ' ' -f 1 | xargs docker rm

Effacer les images untagged (<none>) :

docker images | grep none | awk '{print $3}' | xargs docker rmi -f

Méthode 1 : mode intéractif

Pour copier des fichiers dans l'image il est nécessaire de monter un dossier. Démarrer un conteneur en mode intéractif à partir d'une image de base (système d'exploitation debian stable), en montant un dossier de la machine hôte (ex : /home/rey/Travail) dans un dossier du conteneur (ex : /opt/Travail) :

docker run -it -v /home/rey/Travail:/opt/Travail debian:stable /bin/bash

Ensuite, réaliser toutes les installations et paramétrages nécessaires :

root@29d4663f7b11:~# _
root@29d4663f7b11:~# apt-get update
root@29d4663f7b11:~# apt-get install gcc make python vim
root@29d4663f7b11:~# cp -r /opt/Travail /usr/local/.

Quitter le conteneur, puis faire un commit pour créer une image à partir du conteneur (utiliser la commande docker ps -a pour avoir la liste des containers fermés ou en cours d'exécution).

docker commit -a [AUTEUR] [ID DU CONTENEUR] [NOM DE L'IMAGE]

Exemple :

docker commit -a "Julien Rey <julien.rey@univ-paris-diderot.fr>" 29d4663f7b11 dev-registry.rpbs.univ-paris-diderot.fr/monimage
Remarque : Il faut tout de suite préciser l'adresse du registre de développement dans le nom de l'image. En cas d'oubli on peut renommer l'image à l'aide la commande docker tag.
Attention : Les dossiers montés lors du lancement du conteneur ne seront pas inclus dans le commit.

Méthode 2 (recommandée) : automatisation à l'aide d'un Dockerfile

Le Dockerfile est un fichier texte qui inclut une liste d'actions à exécuter pour construire une image.

Écriture du Dockerfile

Voici les différentes instructions à fournir :

FROM debian:wheezy
  • FROM : image de base (ubuntu, debian, etc...).
MAINTAINER Julien Rey <julien.rey@univ-paris-diderot.fr>
  • MAINTAINER : nom et mail du mainteneur de l'image.
ENV CHEMAXON_LICENSE_URL /var/www/.chemaxon/license.cxl
  • ENV : déclaration des variables d'environnement.
COPY src/programs /tmp
COPY src/FAF_PROD /usr/local/FAF-Drugs
COPY src/licence /var/www
  • COPY : copie d'un dossier de la machine locale vers l'image.
Attention : L'instruction COPY copie le contenu du dossier et non le dossier lui-même.
RUN apt-get -q -y update && \
apt-get install -q -y \ 
  python-pip \
  python-dev \
  r-base \
  • RUN : commande à exécuter lors de la construction de l'image.

Quelques autres commandes utiles :

  • ADD : copie d'un fichier de la machine locale vers l'image.
  • ENTRYPOINT : commande qui s'exécute au démarrage du conteneur.
  • CMD : commande par défaut qui s'exécute au démarrage du conteneur. La commande est écrasée si une autre est spécifiée lors du lancement du conteneur.
  • Remarque : La commande donnée par l'instruction CMD peut être utilisée comme argument de la commande donnée avec l'instruction ENTRYPOINT. Exemple:

    ENTRYPOINT ["/usr/bin/babel"]
    CMD ["--help"]
  • EXPOSE : port(s) à exposer à l'extérieur.

Exemple d'un fichier Dockerfile assez complexe qui permet l'automatisation de l'installation de paquets debian, de bibliothèques python et R, et de code source C à compiler :

FROM debian:wheezy
MAINTAINER Julien Rey 

# Création d'un repertoire pour l'utilisateur www-data (nécessaire pour Mobyle) 
RUN mkdir /var/www && \
chown 33:33 /var/www

# Copie des scripts et des fichiers d'installation
COPY src/programs /tmp
COPY src/FAF_PROD /usr/local/FAF-Drugs
COPY src/licence /var/www

# Déclaration d'une variable d'environnement
ENV CHEMAXON_LICENSE_URL /var/www/.chemaxon/license.cxl

# Don't use dash for compatibility 
RUN ln -sfn /bin/bash /bin/sh && \

# Installation de paquets debian
sed 's/main$/main contrib/' -i /etc/apt/sources.list && \
apt-get -q -y update && \
apt-get install -q -y \ 
  expect \
  fontconfig \
  g++-4.4 \
  java-package \
  libfontconfig1-dev \
  libpng12-dev \
  pkg-config \
  python-pip \
  python-dev \
  r-base && \

...

# Extraction, compilation et installation d'un programme
cd /tmp && \
tar xzf openbabel-2.2.3.tar.gz && \
cd openbabel-2.2.3 && \
./configure && \
make && \
make install && \

...

# Installation d'une bibliothèque R
cd /tmp && \
R CMD INSTALL Cairo_1.5-6.tar.gz && \

...

# Extraction, construction et installation d'une bibliothèque python
cd /tmp && \
tar xzf matplotlib-1.0.1.tar.gz && \
cd matplotlib-1.0.1 && \
python setup.py build && \
python setup.py install && \

...

# Installation de bibliothèques python avec pip
pip install "cheetah == 2.4.4" && \
pip install odict && \
pip install PIL && \
pip install "rpy2 == 2.1.2" && \
pip install Pillow && \

...

# Installation de java
cd /tmp && \
yes "" | su -c 'make-jpkg jre-7u75-linux-x64.tar.gz' nobody && \
dpkg --install oracle-j2re1.7_1.7.0+update75_amd64.deb && \

...

# Nettoyage des fichiers et des paquets non utiles au fonctionnement du conteneur
apt-get autoremove -q -y g++-4.4 make python-pip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

Construction de l'image

Taper la commande suivante :

docker build -t [NOM DE L'IMAGE] [CHEMIN VERS LE DOSSIER CONTENANT LE DOCKERFILE]

Exemple :

docker build -t dev-registry.rpbs.univ-paris-diderot.fr/fpocket .
Remarque : Il faut tout de suite préciser l'adresse du registre de développement dans le nom de l'image. En cas d'oubli on peut renommer l'image à l'aide la commande docker tag.

Autres recommandations

Écriture des fichiers de résultats

Le dossier /scratch/user de l'utilisateur est automatiquement monté lorsqu'un conteneur est appelé avec la commande drun. L'écriture des fichiers de résultats doit donc se faire obligatoirement dans un sous-dossier du dossier courant. Tout fichier écrit en dehors de ce dossier sera effacé à la fin de l'exécution du conteneur (voir ci-dessous). Il est déconseillé d'utiliser des chemins absolus.

Écriture des fichiers temporaires

Il est conseillé d'écrire les fichiers temporaires directement dans le dossier /tmp du conteneur plutôt que dans le dossier courant. Chaque conteneur est automatiquement effacé après chaque exécution avec la commande drun.

Usage du réseau

Pour des raisons de surcharge du traffic les conteneurs lancés avec la commande drun sur le cluster n'ont pas accès au réseau. Merci de prendre cet aspect en compte lors des développements.

Remarque : On peut simuler l'absence de réseau sur sa machine en ajoutant l'option --net=none à la commande docker run.

Intégration avec Mobyle

Les conteneurs appelés par l'intermédiaire du portail Mobyle sont lancés en tant qu'utilisateur www-data. Certains logiciels écrivent dans le dossier home de l'utilisateur qu'il l'a lancé (pour www-data il s'agit de /var/www). Par défaut, les images de systèmes de base telles que debian ne comporte pas de dossier /var/www, ce qui risque d'entraîner des erreurs lors du lancement de ces programmes. Pour pallier à ce problème il est nécessaire de créer le dossier /var/www et de lui donner les bons droits :

RUN mkdir /var/www && chown 33:33 /var/www

Sur le registre de développement

Rien de plus simple, taper la commande :

docker push [NOM DE L'IMAGE]

Exemple :

docker push dev-registry.rpbs.univ-paris-diderot.fr/fpocket
Remarque : L'adresse du registre de développement (dev-registry.rpbs.univ-paris-diderot.fr) doit être contenue dans le nom de l'image.
Attention : Le registre de développement est complètement ouvert en écriture et n'a pour objectif que de réaliser des tests. Un usage raisonné de la ressource est donc demandé. Merci de ne pas multiplier les images identiques en leur donnant des noms différents.

L'image sera alors visible depuis tous les noeuds du cluster de développement.

Remarque : La commande drun vérifie à chaque fois qu'elle est lancée que la version de l'image Docker présente sur le noeud est la plus récente. Il est donc normal de voir s'afficher des messages de Docker avant l'exécution d'un programme : le noeud télécharge la dernière version de l'image avant de démarrer le conteneur :

-bash-4.2$ drun opendocking babel -i protein.pdb -o protein.mol2
Pulling repository dev-registry.rpbs.univ-paris-diderot.fr/opendocking
72b3ea59f87e: Download complete 
511136ea3c5a: Download complete 
30d39e59ffe2: Download complete 
c90d655b99b2: Download complete 
a3c2a3aac44b: Download complete 
1c09cc21a2a4: Download complete 
5bb0dbdb9447: Download complete 
f6ca52397cb1: Download complete 
3271ceeb9fdd: Download complete 
b62621a5c2e4: Download complete 
36e76bea3570: Download complete
Status: Image is up to date for dev-registry.rpbs.univ-paris-diderot.fr/fpocket:latest

De ce fait il n'est pas nécessaire de mettre à jour soi-même les images sur les noeuds du cluster de développement.


Sur le registre de production

Une fois les tests effectués sur le cluster de développement et l'image validée, prendre contact avec un administrateur pour transférer l'image sur le cluster de production.

Tutoriel vidéo d'initiation à l'utilisation du portail Mobyle:


Test tutoriel Mobyle 1.5 par rpbs