##Workshop  --- ## Sommaire - Concept et théorique de Docker  - Conception d'une image et déploiement des containers  - Orchestration  - Mise en place d'une usine logiciel WebSIG  - Load Balancing et SWARM  --- ## Concept et théorique de Docker  Docker est un logiciel libre (sous licence Apache 2.0) à mi-chemin entre la virtualisation applicative et l'automatisation. Il permet de manipuler des conteneurs de logiciels. Il complète le conteneur Linux LXC en isolant les processus les uns des autres pour créer une virtualisation de haut niveau. Dans l'esprit docker: un processus = un conteneur. Contrairement aux autres systèmes de (para) virtualisation, Docker n’embarque pas un système d’exploitation invité mais ne s’occupe que de la partie haut niveau. Il utilise le noyau de l'hôte et ne fait fonctionner que le strict nécessaire sur les invités. --- ##Fonctionnement de Docker vs virtualisation  Docker c'est aussi un dépôt d'images à partir duquel vous pouvez télécharger et partager des applications sans avoir à réinventer la roue. https://hub.docker.com/ --- ##Exemple d'architecture d'un serveur WebSIG sous Docker  L'hôte héberge quelques services, Docker et les fichiers de données persistantes. L'ensemble des applications sont containerisées, permettant souplesse et rapidité d'installation. --- ##Installation de docker linux ubuntu/Debian .exercise[ ```bash sudo apt-get update sudo apt-get install curl curl -fsSL https://get.docker.com/ | sh sudo systemctl enable docker sudo service docker start sudo groupadd docker sudo usermod -aG docker $USER ``` ] https://docs.docker.com/engine/installation/ --- ##Commandes essentielles de Docker: images - Construire l'image via mon dépôt github (permet de voir toute l'installation, debug): ` docker build -t docker-lizmap git://github.com/jancelin/docker-lizmap` - Construire l'image venant de DockerHub: `docker pull jancelin/docker-lizmap` - Recherche sur DockerHub: `docker search lizmap` - Lister les images chargés: `docker images` - Supprimer une image: `docker rmi jancelin/docker-lizmap` https://docs.docker.com/engine/reference/commandline/#the-docker-commands --- ##Commandes essentielles de Docker: container - Démarrer une image, attribuer un port, lier un dossier en lecture: `docker run --restart="always" --name "websig-lizmap" -p 8081:80 -d -v /your_qgis_folder:/home:ro jancelin/docker-lizmap` - Lister les containers: `docker ps -a ` - Démarrer un container: `docker start name_container` - Arrêter container:`docker stop name_container` - Supprime le container:`docker rm name_container` - Rentrer dans un container: `docker exec -it jancelin/docker-lizmap bash` https://docs.docker.com/engine/reference/commandline/#the-docker-commands https://docs.docker.com/v1.8/reference/commandline/run/ --- ##Jouer avec un premier container: un service web "Hello world" .exercise[ ```bash docker run --name "hello" -p 8081:80 -d eeacms/hello ``` - Que c'est t'il passé? ```bash docker images docker ps ``` - Allez à: http://localhost:8081 ```bash docker stop hello && docker rm hello docker ps ``` ] source: https://hub.docker.com/r/eeacms/hello/ --- ##Conception d'une image et déploiement des containers  - Création du Dockerfile: L'écriture d'un Dockerfile ressemble un peu à celle d'une recette de cuisine: incorporer ça, faire ça, incorporer autre chose, faire cette opération et cette autre opération.  --- ##Mots clefs de base pour la création d'un container 1/2  - FROM permet de définir depuis quelle base votre image ve être créée - MAINTAINER permet de définir l'auteur de l'image et s'écrit de la manière suivante Nom
- RUN permet de lancer une commande, mais aura aussi pour effet de créer une image intermédiaire. - ADD permet de copier un fichier depuis la machine hôte ou depuis une URL - EXPOSE permet d'exposer un port du container vers l'extérieur --- ##Mots clefs de base pour la création d'un container 2/2  - CMD détermine la commande qui sera exécutée lorsque le container démarrera - ENTRYPOINT permet d'ajouter une commande qui sera exécutée par défaut, et ce, même si on choisit d'exécuter une commande différente de la commande standard - WORKDIR permet de définir le dossier de travail pour toutes les autres commandes (par exemple RUN, CMD, ENTRYPOINT et ADD) - ENV permet de définir des variables d'environnements qui pourront ensuite être modifiées grâce au paramètre de la commande run --env
=
. - VOLUMES permet de créer un point de montage qui permettra de persister les données. On pourra alors choisir de monter ce volume dans un dossier spécifique en utilisant la commande run -v : --- ##Mon premier Container  - Conception d'un serveur web fonctionnel (apache) pour publier mes cartes (Qgis2web)   https://plugins.qgis.org/plugins/qgis2web/ .exercise[ - Pour publier une carte web nous avons besoin de Qgis et du plugin Qgis2Web (extension --> installer une extension --> qgis2web) - Créez un projet sous qgis avec une couche et un fond openstreetmap (extension --> installer une extension --> OpenLayers Plugin) - Lancer le plugin Qgis2Web et enregistrer dans le dossier de votre choix. - Si vous ne savez pas faire, vous copierez une démo un peu plus tard. ] --- ##Let's go  .exercise[ - Se connecter au serveur avec ssh ```bash ssh geomatik@ip_serveur ``` - Rentrer dans son répertoire ```bash cd 1 ``` - Copier le répertoire créé avec Qgis2Web dans ce dossier ```bash cp -r /home/geomatik/qgis2web/ /home/geomatik/1 ``` - Créer un fichier Dockerfile ```bash nano Dockerfile ``` ] --- ##Editer le Dockerfile  .exercise[ - Copier le contenu et coller dans le Dockerfile ```bash FROM debian:jessie MAINTAINER Julien ANCELIN RUN apt-get update && apt-get -y install apache2 && apt-get clean && rm -rf /var/lib/apt/lists/* ENV APACHE_RUN_USER www-data ENV APACHE_RUN_GROUP www-data ENV APACHE_LOG_DIR /var/log/apache2 RUN /usr/sbin/a2ensite default-ssl RUN /usr/sbin/a2enmod ssl VOLUME /var/www/html EXPOSE 80 EXPOSE 443 CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] ``` - Sauvegarder et sortir de l'édition ```bash ctrl o + ctrl x ``` ] --- ##Construction de l'image .exercise[ - Comme nous n'utilisons pas une image du DockerHub il faut la construire en local ( `PULL` vs `BUILD` ) ```bash docker build -t apache1 /home/geomatik/1 ``` - Vous observez grâce à `build` le détail de l'installation, pratique pour le debug... - Vous optenez un `Successfully built` à la fin de la construction. - Visualiser les caractéristiques de votre image: `docker images` ] --- ##Lancer le container avec ses cartes .exercise[ - Nous allons maintenant créer la phrase de lancement du container `RUN` - attribuer un nom: `--name "qgis2web"` - définir que notre site web sera sur le port 8081 ( localhost:8081): `-p 8081:80` - lier notre dossier qgis2web : `-v /home/geomatik/1/qgis2web/:/var/www/html/` - lancer en tache de fond : `-d` - utiliser l'image créé comme référence: `apache1` - et tout compiler en une phrase: ```bash docker run --name "qgis2web81" -p 8081:80 -v /home/geomatik/1/qgis2web/:/var/www/html/ -d apache1 ``` - Pour connaitre l'état du container lancer un `docker ps` - se rendre sur http://localhost:8081 et voir le résultat ] ref: https://github.com/jancelin/workshop_docker_GIS/blob/master/apache/README.md --- ## Multiplier les containers - L'avantage de Docker et que l'on peut créer des containers identiques ou diversifiés très rapidement. .exercise[ - créer un deuxième container qgis2web avec un jeux de données différent. - Copier le deuxième répertoire créé avec Qgis2Web dans ce dossier ```bash cp -r /home/geomatik/qgis2web1/ /home/geomatik/1 ``` - Changer quelques paramètres du `RUN`: le port (impossible de lancer 2 containers sur le même port) et le dossier lié ```bash docker run --name "qgis2web82" -p 8082:80 -v /home/geomatik/1/qgis2web1/:/var/www/html/ -d apache1 ``` - http://localhost:8081 http://localhost:8082 ] --- ##Un peu de ménage avant de passer à la suite - On se fait vite prendre au jeu de construire des containers, plein de containers... .exercise[ - Arréter et supprimer tous les containers. - Méthode longue, il faut écrire tout les noms: ```bash docker stop qgis2web81 qgis2web82 docker rm qgis2web81 qgis2web82 ``` - Méthode plus simple car nous gérons tout les containers d'une images: ```bash docker ps -a | awk '{ print $1,$2 }' | grep apache1 | awk '{print $1 }' | xargs -I {} docker stop {} docker ps -a | awk '{ print $1,$2 }' | grep apache1 | awk '{print $1 }' | xargs -I {} docker rm {} ``` ] --- ##Orchestration  - La gestion de la création, l'ordonnancement et le lancement des containers est fastidieuse car il faut le faire manuellement et respecter chaque étape. **C’est là que docker-compose vous simplifie la vie.** - En se basant sur un fichier docker-compose.yml contenant la configuration de votre empilement, docker-compose va créer, lancer, ouvrir les ports, créer les volumes et lier vos containers tout seul. .exercise[ - installation de docker-compose ```bash sudo apt-get install python-pip sudo pip install docker-compose ``` ] https://docs.docker.com/compose/install/ --- ##Fichier docker-compose.yml - Le fichier Compose est un fichier YAML définissant les services, les réseaux et les volumes. .exercise[ - Créer le docker-compose.yml ```bash nano docker-compose.yml version: '2' services: qgis2web81: image: apache1 restart: always ports: - 8081:80 volumes: - "/home/geomatik/1/qgis2web/:/var/www/html/" ``` ] --- ##Lancer le container .exercise[ - Une commande permet de lire le docker-compose.yml et de le jouer, si une modification est faite sur le fichier elle est appliqué aux containers. ```bash docker-compose up -d ``` - Visualiser le résultat http://localhost:8081 - Visualiser l'état du container: `docker-compose ps` - Arrêter un container: `docker-compose stop qgis2web1` - Supprimer un container: `docker-compose rm qgis2web1` - Tuer tout les containers: `docker-compose kill` - Supprimer tout les containers: `docker-compose rm` - Toutes les commandes: https://docs.docker.com/compose/reference/ ] --- ## Orchestrer tout ses services .exercise[ - rajouter tout les run dans le docker-compose.yml ```bash version: '2' services: qgis2web81: image: apache1 restart: always ports: - 8081:80 volumes: - /home/geomatik/1/qgis2web/:/var/www/html/ qgis2web82: image: apache1 restart: always ports: - 8082:80 volumes: - /home/geomatik/1/qgis2web1/:/var/www/html/ ``` ] --- ##Mise en place d'une usine logiciel WebSIG  **Marche à suivre:** - 1.Concevoir une architecture Logiciel adapté à son besoin. - 2.Ne pas réinventer la roue et utiliser des images fiables du DockerHub: https://hub.docker.com/ - 3.Créer une arborescence de fichier stable et fonctionelle. - 4.Concevoir son docker-compose.yml. - 5.Reprendre une vie normale et travailler avec ses outils. --- ## Choix des images  - Postgesql Postgis 9.5-2.2 : https://hub.docker.com/r/kartoza/postgis/ - qgis-serveur Lizmap: https://hub.docker.com/r/jancelin/docker-lizmap/ - Rstudio : https://hub.docker.com/r/rocker/rstudio/ **En option** - Owncloud : https://hub.docker.com/_/owncloud/ - Gitlab : https://hub.docker.com/r/gitlab/gitlab-ce/  --- ##Arborescence  .exercise[ - Créer les dossiers pour les fichiers permanents ```bash mkdir /home/geomatik/1/postgres_data mkdir /home/geomatik/1/lizmap/lizmap_project mkdir /home/geomatik/1/lizmap/lizmap_var mkdir /home/geomatik/1/rstudio ``` ] --- ##Docker-compose.yml 1/2 https://github.com/jancelin/workshop_docker_GIS/blob/master/docker-compose.yml .exercise[ ```bash version: '2' services: postgis: image: kartoza/postgis:9.5-2.2 restart: always ports: - 5432:5432 volumes: - /home/geomatik/1/postgres_data:/var/lib/postgresql environment: - POSTGRES_USER=geomatik - POSTGRES_PASS=geomatik - ALLOW_IP_RANGE=0.0.0.0/0 ``` ] --- ##Docker-compose.yml 2/2 .exercise[ ```bash lizmap: image: jancelin/docker-lizmap:3-2.14LTR restart: always ports: - 80:80 volumes: - /home/geomatik/1/lizmap/lizmap_project:/home - /home/geomatik/1/lizmap/lizmap_var:/var/www/websig/lizmap/var rstudio: image: rocker/rstudio restart: always ports: - 8787:8787 volumes: - /home/geomatik/1/rstudio:/home/geomatik environment: - USER=geomatik - PASSWORD=geomatik ``` ] --- ##Lancer .exercise[ - Lancer ```bash docker-compose up -d ``` ] --- ##Personaliser une image .exercise[ - install.packages("RPostgreSQL") ne fonctionne pas dans Rstudio. - identifier et Personaliser un container et son image: ```bash docker ps -a docker exec -it 1_rstudio_1 bash ``` - Editer le container ```bash apt-get update apt-get -t unstable install libpq-dev exit ``` - Commit l'image ```bash docker-compose stop rstudio docker commit 1_rstudio_1 rocker/rstudio docker-compose up -d rstudio ``` ] --- ##Ajouter Gitlab et Owncloud .exercise[ - Pour avoir un environnement complet de dev avec Owncloud et Gitlab en plus - rajouter 2 dossiers et quelques sous dossiers: ```bash mkdir /home/geomatik/1/owncloud mkdir /home/geomatik/1/owncloud/apps mkdir /home/geomatik/1/owncloud/config mkdir /home/geomatik/1/owncloud/data mkdir /home/geomatik/1/gitlab mkdir /home/geomatik/1/gitlab/config mkdir /home/geomatik/1/gitlab/logs mkdir /home/geomatik/1/data ``` ] --- ##Docker-compose.yml 1/2 .exercise[ - Rajouter au docker-compose.yml ```bash owncloud: image: owncloud restart: always ports: - 8080:80 volumes: - "/home/geomatik/1/owncloud/apps:/var/www/html/apps" - "/home/geomatik/1/owncloud/config:/var/www/html/config" - "/home/geomatik/1/owncloud/data:/var/www/html/data" mysql: image: mariadb restart: always environment: MYSQL_ROOT_PASSWORD: geomatik ``` ] --- ##Docker-compose.yml 2/2 .exercise[ ```bash gitlab: image: gitlab/gitlab-ce:latest restart: always ports: - '90:80' - '443:443' - '25:22' volumes: - '/home/geomatik/1/gitlab/config:/etc/gitlab' - '/home/geomatik/1/gitlab/logs:/var/log/gitlab' - '/home/geomatik/1/gitlab/data:/var/opt/gitlab' ``` - Et up: ```bash docker-compose up -d ``` ] --- ##Initialisation owncloud 1/2 .exercise[ ```bash # https://hub.docker.com/_/owncloud/ # ownCloud with MariaDB/MySQL # # Access via "http://localhost:8080" (or "http://$(docker-machine ip):8080" if using docker-machine) # # During initial ownCloud setup, select "Storage & database" --> "Configure the database" --> "MySQL/MariaDB" # Database user: root # Database password: geomatik # Database name: geomatik # Database host: replace "localhost" with "mysql" ``` ] --- ##Initialisation owncloud 2/2 .exercise[ - Une fois que Owncloud est fonctionel, changer le dossier lié pour les projets Lizmap dans le docker-compose.yml ```bash lizmap: image: jancelin/docker-lizmap:3-2.14LTR restart: always ports: - 80:80 volumes: - "/home/geomatik/1/owncloud/data/geomatik/files/lizmap:/home" - "/home/geomatik/1/lizmap_var:/var/www/websig/lizmap/var" - "/home/geomatik/1/lizmap_tmp:/tmp" ``` - Et up: ```bash docker-compose up -d ``` ] --- ##Load Balancing et Swarm  - Docker-Compose Docker propose depuis longtemps déjà docker-compose qui offre la possibilité de “composer” un ensemble de container sur une seule et même machine, mais également de “scaler” les containers toujours sur un même serveur. - Docker Swarm Mais comment orchestrer un ensemble de containers non plus sur un seul serveur, mais répartis sur plusieurs serveurs ? Docker propose son alternative en améliorant la version existante de Docker Swarm. --- ##Load Balancing sur un seul serveur - La réecriture d’URL sur une seule machine Comment gérer la rééecriture d'URL dans docker entre le proxy porte d'entrée et les microservices de destination.  --- ##Docker-compose et Load Balancing sur un seul serveur - En terme de proxy, le premier qui vient à l’esprit est HAProxy. Il existe aussi træfik et nginx. .exercise[ 1/2 ```bash version: '2' services: lb: image: dockercloud/haproxy links: - qgiserver volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - MONITOR_PORT ports: - 8900:80 ``` ] --- ##Docker-compose et Load Balancing sur un seul serveur .exercise[ 2/2 ```bash qgiserver: image: jancelin/qgis-server:2.14LTR restart: always volumes: - "/home/qgis_files:/home" expose: - 80 ``` - up ```bash docker-compose up -d lb ``` - scale (ex:15 qgis-sever) ```bash docker-compose scale qgiserver=15 ``` ] --- ##Docker-compose et Load Balancing sur un seul serveur .exercise[ - Tester si qgis-server fonctionne > http://localhost:8900/cgi-bin/qgis_mapserv.fcgi?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities - Pour voir les statistiques récupérer l'IP interne du container: ```bash docker ps -a ``` >http://internal_lb_ip:1936 >ex: http://172.18.0.2:1936 > login: stats > password: stats ] --- ##Swarm - Docker Swarm est l’outil proposé par Docker pour assurer la gestion de clusters Docker, le routage, la scalabilité,... - L'exemple sera déployé sur un cluster de 4 Raspberry Pi avec Hypriot Docker Image: http://blog.hypriot.com/downloads/  --- ##Swarm .exercise[ - Sur chaque SD flasher l'Hypriot Image et modifier le hostname dans /boot/device-init.yaml: hostname: gp1 - Sous ubuntu, créer une connexion ethernet où: > tout les utilisateurs peuvent se connecter > ipv4: automatique DHCP - brancher le cluster Raspberry en ethernet au pc et lancer un arp -a pour connaître les ip des noeuds - utiliser le docker-compose.yml de GeoPoppy sur le premier noeud (postgis + lizmap): https://github.com/jancelin/geo-poppy/blob/master/docker-compose.yml - Pour l'exemple créons 4 projets qgis identiques et changeons la symobologie pour avoir une couleur différente de polygones par projet. - Copier un .qgs par raspberry dans le dossier /home/GeoPoppy/lizmap/project (le créer si besoin) - Utiliser le plugin lizmap pour créer le .qgs.cfg et choissant l'option image non tuilée. - Dans le back-office de lizmap changer l'adresse de qgis-server par l'adresse d'un des noeud: ex: http://10.42.0.25:8200/cgi-bin/qgis_mapserv.fcgi ] --- ##Swarm .exercise[ - initialiser le cluster ```bash docker swarm init ``` - ça renvoie un truc du genre: ```bash Swarm initialized: current node (node-master) is now a manager. To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-4kwouczydosn9b14p2f0c76fogmtojsgne3rt45odqwj1ma61h-bhpp9xvq18evjsrpp2h7ecuqb \ 10.42.0.95:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. ``` - Ajouter à chaque noeud la commande donnée précédement par docker - Visualiser les noeuds à partir du noeud manager: ```bash docker node ls ``` ] --- ##Swarm - Avec Docker Network, nous disposerons d’une interface standardisée de gestion d’un réseau de conteneurs .exercise[ - Initialiser une connexion network interne: ```bash docker network create -d overlay mynet ``` -Visualiser les networks ```bash docker network ls ``` ] --- ##Swarm .exercise[ - Lancer son service sur les noeuds ```bash docker service create --replicas 8 \ --mount type=bind,source=/home/GeoPoppy/lizmap/project,destination=/home \ --network mynet \ --name qgiserver -p 8200:80 \ jancelin/geopoppy:qgis-server2.14LTR ``` ] --- ##Swarm - Visualiser le résultat: http://gp1.local  --- ##Swarm .exercise[ - Profiter d'une interface graphique pour visualiser les noeuds: ```bash docker run -it -d --restart="always" --name "visualizer" -p 8080:8080 -v /var/run/docker.sock:/var/run/docker.sock alexellis2/visualizer-arm:latest ``` - et visualiser: http://gp1.local:8080  ] --- # Merci!
Questions? ## [@complementterre](https://twitter.com/complementterre)