7. Déploiement conteneurisé

Il existe de nombreuses façons d’utiliser les applications conteneurisées, des plus simples (simples images Docker) aux plus sophistiquées (Kubernetes, etc.).

Note

Ce type de déploiement nécessite l’installation et l’exécution de l’application docker. Consultez ce tutoriel.

Indication

Docker exécute des applications pré-packagées (alias images) qui peuvent être récupérées comme sources (Dockerfile et ressources) à construire ou déjà construites à partir de registres (privés ou publics).

Note

Les téléchargements de paquets QGIS Debian-Ubuntu nécessitent une clé d’authentification gpg valide. Veuillez vous référer aux pages d’installation <https://www.qgis.org/fr/site/forusers/alldownloads.html#debian-ubuntu>`_ pour mettre à jour le Dockerfile suivant avec la dernière empreinte de la clé

7.1. Simples images docker

Comme l’image du docker n’existe pas dans un dépôt public, vous devrez la construire. Pour ce faire, créez un dossier qgis-server et à l’intérieur de ce dossier :

  • créer un fichier Dockerfile avec ce contenu :

FROM debian:buster-slim

ENV LANG=en_EN.UTF-8


RUN apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests --allow-unauthenticated -y \
        gnupg \
        ca-certificates \
        wget \
        locales \
    && localedef -i en_US -f UTF-8 en_US.UTF-8 \
    # Add the current key for package downloading - As the key changes every year at least
    # Please refer to QGIS install documentation and replace it with the latest one
    && wget -O - https://qgis.org/downloads/qgis-2020.gpg.key | gpg --import \
    && gpg --export --armor F7E06F06199EF2F2 | apt-key add - \
    && echo "deb http://qgis.org/debian buster main" >> /etc/apt/sources.list.d/qgis.list \
    && apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests --allow-unauthenticated -y \
        qgis-server \
        spawn-fcgi \
        xauth \
        xvfb \
    && apt-get remove --purge -y \
        gnupg \
        wget \
    && rm -rf /var/lib/apt/lists/*

RUN useradd -m qgis

ENV TINI_VERSION v0.17.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini

ENV QGIS_PREFIX_PATH /usr
ENV QGIS_SERVER_LOG_STDERR 1
ENV QGIS_SERVER_LOG_LEVEL 2

COPY cmd.sh /home/qgis/cmd.sh
RUN chmod -R 777 /home/qgis/cmd.sh
RUN chown qgis:qgis /home/qgis/cmd.sh

USER qgis
WORKDIR /home/qgis

ENTRYPOINT ["/tini", "--"]

CMD ["/home/qgis/cmd.sh"]
  • créer un fichier cmd.sh avec ce contenu :

#!/bin/bash

[[ $DEBUG == "1" ]] && env

exec /usr/bin/xvfb-run --auto-servernum --server-num=1 /usr/bin/spawn-fcgi -p 5555 -n -d /home/qgis -- /usr/lib/cgi-bin/qgis_mapserv.fcgi
  • construire l’image avec:

docker build -f Dockerfile -t qgis-server ./

7.1.1. Premier lancement

Pour faire fonctionner le serveur, vous aurez besoin d’un fichier de projet QGIS. Vous pouvez utiliser l’un des vôtres ou choisir cette exemple.

Pour ce faire, créez un dossier data dans le dossier qgis-server et copiez votre fichier dedans. Pour respecter les explications suivantes, renommez-le en osm.qgs.

Maintenant, vous pouvez faire fonctionner le serveur avec :

docker network create qgis
docker run -d --rm --name qgis-server --net=qgis --hostname=qgis-server \
              -v $(pwd)/data:/data:ro -p 5555:5555 \
              -e "QGIS_PROJECT_FILE=/data/osm.qgs" \
              qgis-server

Options utilisées :

  • -d : exécuter en arrière-plan

  • –rm : supprimer le conteneur lorsqu’il est arrêté

  • –name : nom du conteneur à créer

  • –net : (précédemment créé) nom du sous-réseau

  • –hostname : nom d’hôte du conteneur, pour référence ultérieure

  • -v : dossier de données locales à monter dans le conteneur

  • -p : mappage des ports hôtes/conteneurs

  • -e : variable d’environnement à utiliser dans le conteneur

Pour vérifier, tapez docker ps | grep qgis-server et vous devriez voir une ligne avec qgis-server: :

CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS                    NAMES
4de8192da76e   qgis-server   "/tini -- /home/qgis…"   3 seconds ago   Up 2 seconds   0.0.0.0:5555->5555/tcp   qgis-server

7.1.2. Exemple fonctionnel

Comme le serveur n’accepte que les connexions fastcgi, vous avez besoin d’un serveur HTTP qui gère ce protocole. Pour ce faire, nous devons créer un simple fichier de configuration Nginx et lancer une image Nginx.

Créez un fichier nginx.conf dans le dossier courant avec ce contenu :

server {
  listen 80;
  server_name _;
  location / {
    root  /usr/share/nginx/html;
    index index.html index.htm;
  }
  location /qgis-server {
    proxy_buffers 16 16k;
    proxy_buffer_size 16k;
    gzip off;
    include fastcgi_params;
    fastcgi_pass qgis-server:5555;
  }
}

Et taper cette commande:

docker run -d --rm --name nginx --net=qgis --hostname=nginx \
              -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro -p 8080:80 \
              nginx:1.13

Pour vérifier la disponibilité des capacités du serveur, tapez dans l’url d’un navigateur http://localhost:8080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

7.1.3. Nettoyage

Pour nettoyer les images en cours, tapez :

docker stop qgis-server nginx

7.2. Docker stacks

La méthode précédente est scriptable, mais elle n’est ni facile à mettre en œuvre, ni standardisée, ni facilement gérable.

Pour travailler avec un jeu d’images Docker, vous pourriez utiliser une stack Docker gérée par un orchestrateur. Dans une pile, les images fonctionnent dans le même réseau privé, et vous pouvez démarrer/arrêter toute la pile ou déployer la pile à d’autres workers. Il existe de nombreux orchestrateurs, par exemple Swarm, Kubernetes et Mesos.

Dans ce qui suit, nous présenterons des configurations simples à des fins de test. Elles ne sont pas adaptées à la production.

7.2.1. Swarm/docker-compose

Docker a maintenant son propre orchestrateur : Swarm (compatible avec les fichiers docker-compose). Vous devez l’activer <https://docs.docker.com/get-started/orchestration/#enable-docker-swarm>`_ (la version Mac fonctionnera également avec des conteneurs Linux).

7.2.1.1. Description de la Stack

Maintenant que Swarm fonctionne, créez le service grâce au fichier (voir Deploy to Swarm) qgis-stack.yaml :

version: '3.7'

services:
  qgis-server:
    # Should use version with utf-8 locale support:
    image: qgis-server:latest
    volumes:
    - REPLACE_WITH_FULL_PATH/data:/data:ro
    environment:
    - LANG=en_EN.UTF-8
    - QGIS_PROJECT_FILE=/data/osm.qgs
    - QGIS_SERVER_LOG_LEVEL=0  # INFO (log all requests)
    - DEBUG=1                  # display env before spawning QGIS Server

  nginx:
    image: nginx:1.13
    ports:
    - 8080:80
    volumes:
    - REPLACE_WITH_FULL_PATH/nginx.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
    - qgis-server

Pour déployer (ou mettre à jour) la stack, tapez :

docker stack deploy -c qgis-stack.yaml qgis-stack

Vérifiez le statut de déploiement de la stack jusqu’à ce que vous obteniez 1/1 dans la colonne replicas :

docker stack services qgis-stack

Quelque chose comme :

ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
gmx7ewlvwsqt        qgis_nginx          replicated          1/1                 nginx:1.13          *:8080->80/tcp
l0v2e7cl43u3        qgis_qgis-server    replicated          1/1                 qgis-server:latest

Pour vérifier les capacités du serveur WMS, tapez dans un navigateur web http://localhost:8080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

7.2.1.2. Nettoyage

Pour nettoyer, tapez :

docker stack rm qgis-stack

7.2.2. Kubernetes

7.2.2.1. Installation

Si vous avez une installation Docker Desktop, l’utilisation de Kubernetes (alias k8s) est assez simple : activez k8s.

Sinon, suivez le tutoriel minikube ou microk8s pour Ubuntu.

Comme l’installation de Kubernetes peut être vraiment complexe, nous nous concentrerons uniquement sur les aspects utilisés dans cette démo. Pour de plus amples informations, consultez la documentation officielle.

7.2.2.1.1. microk8s

microk8s nécessite des étapes supplémentaires : vous devez activer le registre et marquer l’image du serveur qgis afin que Kubernetes puisse trouver les images créées.

Tout d’abord, activez le dépôt :

microk8s enable dashboard dns registry

Ensuite, vous devez étiqueter et pousser l’image vers votre dépôt nouvellement créé :

docker tag qgis-server 127.0.0.1:32000/qgis-server && docker push 127.0.0.1:32000/qgis-server

Enfin, ajoutez ou complétez le fichier /etc/docker/daemon.json pour que votre dépôt 127.0.0.1:32000 soit listé dans le champ insecure-registries :

{
  "insecure-registries": ["127.0.0.1:32000"]
}

7.2.2.2. Créer des manifests

Kubernetes décrit les objets à déployer dans les manifestes yaml. Il en existe de nombreux types différents, mais nous n’utiliserons que les déploiements (handle pods, c’est-à-dire les images de docker) et les services pour exposer les déploiements à des fins internes ou externes.

7.2.2.2.1. Déploiement des manifests

Créez un fichier deployments.yaml avec ce contenu :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: qgis-server
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      myLabel: qgis-server
  template:
    metadata:
      labels:
        myLabel: qgis-server
    spec:
      containers:
        - name: qgis-server
          image: localhost:32000/qgis-server:latest
          imagePullPolicy: IfNotPresent
          env:
            - name: LANG
              value: en_EN.UTF-8
            - name: QGIS_PROJECT_FILE
              value: /data/osm.qgs
            - name: QGIS_SERVER_LOG_LEVEL
              value: "0"
            - name: DEBUG
              value: "1"
          ports:
            - containerPort: 5555
          volumeMounts:
            - name: qgis-data
              mountPath: /data/
      volumes:
        - name: qgis-data
          hostPath:
            path: REPLACE_WITH_FULL_PATH/data

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: qgis-nginx
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      myLabel: qgis-nginx
  template:
    metadata:
      labels:
        myLabel: qgis-nginx
    spec:
      containers:
        - name: qgis-nginx
          image: nginx:1.13
          ports:
            - containerPort: 80
          volumeMounts:
            - name: nginx-conf
              mountPath: /etc/nginx/conf.d/default.conf
      volumes:
        - name: nginx-conf
          hostPath:
            path: REPLACE_WITH_FULL_PATH/nginx.conf
7.2.2.2.2. Service manifests

Créez un fichier services.yaml avec ce contenu :

apiVersion: v1
kind: Service
metadata:
  name: qgis-server
  namespace: default
spec:
  type: ClusterIP
  selector:
    myLabel: qgis-server
  ports:
    - port: 5555
      targetPort: 5555
---
apiVersion: v1
kind: Service
metadata:
  name: qgis-nginx
  namespace: default
spec:
  type: NodePort
  selector:
    myLabel: qgis-nginx
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

7.2.2.3. Déploiement des manifests

Pour déployer les images et les services dans Kubernetes, on peut utiliser le tableau de bord (cliquez sur le + en haut à droite) ou la ligne de commande.

Note

Lorsque vous utilisez la ligne de commande avec microk8s, vous devez préfixer chaque commande par « microk8s ».

Pour déployer ou mettre à jour vos manifests :

kubectl apply -k ./

Pour vérifier ce qui est actuellement déployé :

kubectl get pods,services,deployment

Vous devriez obtenir quelque chose comme: :

NAME                               READY   STATUS    RESTARTS   AGE
pod/qgis-nginx-54845ff6f6-8skp9    1/1     Running   0          27m
pod/qgis-server-75df8ddd89-c7t7s   1/1     Running   0          27m

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/Kubernetes         ClusterIP   10.152.183.1     <none>        443/TCP        5h51m
service/qgis-exec-server   ClusterIP   10.152.183.218   <none>        5555/TCP       35m
service/qgis-nginx         NodePort    10.152.183.234   <none>        80:30080/TCP   27m
service/qgis-server        ClusterIP   10.152.183.132   <none>        5555/TCP       27m

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/qgis-nginx    1/1     1            1           27m
deployment.apps/qgis-server   1/1     1            1           27m

Pour lire les journaux nginx/qgis, tapez :

kubectl logs -f POD_NAME

Pour vérifier les capacités du serveur WMS, tapez dans un navigateur web http://localhost:30080/qgis-server/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

7.2.2.4. Nettoyage

Pour nettoyer, tapez :

kubectl delete -n default service/qgis-server service/qgis-nginx deployment/qgis-nginx deployment/qgis-server

7.3. Déploiement en Cloud

La gestion de votre propre grappe de serveurs pour assurer le déploiement d’applications conteneurisées est une tâche complexe. Vous devez gérer de multiples questions, telles que le matériel, la bande passante et la sécurité à différents niveaux.

Les solutions de déploiement dans le Cloud peuvent être une bonne alternative lorsque vous ne voulez pas vous concentrer sur la gestion de l’infrastructure.

Un déploiement dans le Cloud peut utiliser des mécanismes propriétaires, mais ils sont également compatibles avec les étapes expliquées précédemment (docker images and stack management).

7.3.1. Cas d’utilisation avec AWS

Avec Amazon AWS, grâce aux fonctionnalités de l’ECS (Elastic Container Service) <https://console.aws.amazon.com/ecs/home>`_, vous pouvez utiliser docker-compose ou Kubernetes pour gérer votre stack. Vous devrez créer un registre d’images pour que vos images personnalisées soient accessibles.

Pour utiliser les mêmes fonctionnalités que docker-compose, vous devez installer le client ecs-cli et avoir les permissions / rôles. Ensuite, à l’aide des commandes ecs-cli compose (voir le manuel ecs-cli compose <https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cmd-ecs-cli-compose.html>`_ et le tutoriel ecs-cli), vous pouvez réutiliser la description de stack.

Pour utiliser Kubernetes, vous pouvez utiliser la console web AWS ou l’outil en ligne de commande eksctl et avoir les permissions / rôles appropriés. Ensuite, avec un environnement kubectl bien configuré, vous pouvez réutiliser les Kubernetes manifests.