One place for hosting & domains

      accéder

      Comment accéder aux caméras Avant et Arrière avec getUserMedia() de JavaScript.


      Introduction

      Le HTML5 a permis l’introduction d’API donnant accès aux composants matériels des appareils, y compris de l’API MediaDevices. Cette API permet d’accéder à des périphériques d’entrée média comme l’audio et la vidéo.

      Avec l’aide de cette API, les développeurs peuvent accéder à des appareils audio et vidéo pour diffuser et afficher des flux vidéo en direct dans le navigateur. Dans ce tutoriel, vous accéderez au flux vidéo à partir de l’appareil de l’utilisateur et l’afficherez dans le navigateur à l’aide du getUserMedia méthode.

      L’API getUserMedia utilise les périphériques d’entrée média pour produire un MediaStream. Ce MediaStream contient les types de médias demandés, qu’ils soient audio ou vidéo. Grâce au flux renvoyé par l’API, les flux vidéo peuvent être affichés sur le navigateur, ce qui est utile pour la communication en temps réel sur le navigateur.

      Lorsqu’il est utilisé avec l’ API MediaStream Recording, vous pouvez enregistrer et stocker des données médias saisies sur le navigateur. Cette API ne fonctionne que sur les origines sécurisées (comme les autres API nouvellement introduites), mais elle fonctionne également sur localhost et sur les URL des fichiers.

      Conditions préalables

      • Une connaissance de base de JavaScript. Si vous ne connaissez pas JavaScript, essayez de consulter la série Comment coder en JavaScript.

      Ce tutoriel explique d’abord les concepts et présente des exemples avec Codepen. Dans la dernière étape, vous créerez un flux vidéo fonctionnel pour le navigateur.

      Étape 1 – Vérification de la prise en charge de l’appareil

      Tout d’abord, vous verrez comment vérifier si le navigateur de l’utilisateur prend en charge l’API mediaDevices. Cette API existe dans le navigateur et contient l’état actuel et l’identité de l’agent utilisateur. Le contrôle est effectué à l’aide du code suivant, qui peut être collé dans Codepen :

      if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {
        console.log("Let's get this party started")
      }
      

      Tout d’abord, cela permet de vérifier si l’API mediaDevices existe dans le navigateur et vérifie ensuite si l’API getUserMedia est disponible dans le mediaDevices. Si cela revient comme true, vous pouvez commencer.

      Étape 2 – Demander la permission de l’utilisateur

      Après avoir confirmé la prise en charge de getUserMedia par le navigateur, vous devez demander l’autorisation d’utiliser les périphériques de saisie des médias sur l’agent utilisateur. Généralement, après qu’un utilisateur ait accordé sa permission, une Promise est renvoyée, qui se transforme en flux média. Cette Promise n’est pas renvoyée lorsque la permission est refusée par l’utilisateur, ce qui bloque l’accès à ces appareils.

      Collez la ligne suivante dans le Codepen pour demander l’autorisation :

      navigator.mediaDevices.getUserMedia({video: true})
      

      L’objet fourni comme argument pour la méthode getUserMedia est appelé constraints. Cela permet de déterminer les périphériques d’entrée média auxquels vous demandez l’autorisation d’accéder. Par exemple, si l’objet contient audio : true, l’utilisateur(rice) sera invité(e) à accorder l’accès au dispositif d’entrée audio.

      Étape 3 – Comprendre les contraintes des médias

      Cette section couvrira le concept général de constraints. L’objet constraints est un objet MediaStreamConstraints qui spécifie les types de médias à demander et les exigences de chaque type de média. Vous pouvez spécifier les exigences pour le flux demandé en utilisant l’objet constraints comme la résolution du flux à utiliser (avant, arrière).

      Vous devez préciser soit audio ou vidéo lors de la demande. Une erreur NotFoundError sera renvoyée si les types de médias demandés ne peuvent être trouvés sur le navigateur de l’utilisateur.

      Si vous avez l’intention de demander un flux vidéo d’une résolution de 1280 x 720, vous pouvez mettre à jour l’objet constraints pour qu’il ressemble à ceci :

      {
        video: {
          width: 1280,
          height: 720,
        }
      }
      

      Avec cette mise à jour, le navigateur essaiera de correspondre aux paramètres de qualité spécifiés pour le flux. Si l’appareil vidéo ne peut pas fournir cette résolution, le navigateur renvoie les autres résolutions disponibles.

      Pour garantir que le navigateur renvoie une résolution qui ne soit pas inférieure à celle fournie, vous devrez utiliser la propriété min. Voici comment vous pourriez mettre à jour l’objet constraints pour inclure la propriété min :

      {
        video: {
          width: {
            min: 1280,
          },
          height: {
            min: 720,
          }
        }
      }
      

      Cela permettra de garantir que la résolution de flux renvoyée sera au moins 1280 x 720. Si cette exigence minimale ne peut pas être respectée, la Promise sera rejetée avec une OverconstrainedError.

      Dans certains cas, vous pouvez être préoccupé(e) par la sauvegarde des données et avoir besoin que le flux ne dépasse pas une résolution donnée. Cela peut s’avérer utile lorsque l’utilisateur est sur un plan limité. Pour activer cette fonctionnalité, mettez à jour l’objet constraints pour qu’il contienne un champ max :

      {
        video: {
          width: {
            min: 1280,
            max: 1920,
          },
          height: {
            min: 720,
            max: 1080
          }
        }
      }
      

      Avec ces paramètres, le navigateur veillera à ce que le flux de retour ne soit pas inférieur à 1280 x 720 et ne dépasse pas 1920 x 1080.

      D’autres termes peuvent être utilisés, notamment exact et ideal. Le paramètre ideal est généralement utilisé avec les propriétés min et max pour trouver le meilleur paramètre possible le plus proche des valeurs idéales fournies.

      Vous pouvez mettre à jour les constraints pour utiliser le mot-clé ideal :

      {
        video: {
          width: {
            min: 1280,
            ideal: 1920,
            max: 2560,
          },
          height: {
            min: 720,
            ideal: 1080,
            max: 1440
          }
        }
      }
      

      Pour indiquer au navigateur d’utiliser la caméra avant ou arrière (sur les appareils mobiles) sur les appareils, vous pouvez spécifier une propriété facingMode dans l’objet video :

      {
        video: {
          width: {
            min: 1280,
            ideal: 1920,
            max: 2560,
          },
          height: {
            min: 720,
            ideal: 1080,
            max: 1440
          },
          facingMode: 'user'
        }
      }
      

      Ce paramètre permet d’utiliser la caméra frontale à tout moment dans tous les appareils. Pour utiliser la caméra arrière sur les appareils mobiles, vous pouvez modifier la propriété facingMode à environment.

      {
        video: {
          ...
          facingMode: {
            exact: 'environment'
          }
        }
      }
      

      Étape 4 – Utiliser la méthode enumerateDevices

      Lorsque la méthode enumerateDevices est appelée, elle renvoie tous les supports d’entrée disponibles sur le PC de l’utilisateur.

      Avec cette méthode, vous pouvez fournir à l’utilisateur des options sur le périphérique d’entrée à utiliser pour la diffusion de contenu audio ou vidéo en continu. Cette méthode renvoie une Promise résolue en un tableau MediaDeviceInfo contenant des informations sur chaque appareil.

      Un exemple d’utilisation de cette méthode est présenté dans l’extrait ci-dessous :

      async function getDevices() {
        const devices = await navigator.mediaDevices.enumerateDevices();
      }
      

      Un exemple de réponse pour chacun des dispositifs ressemblerait à ce qui suit :

      {
        deviceId: "23e77f76e308d9b56cad920fe36883f30239491b8952ae36603c650fd5d8fbgj",
        groupId: "e0be8445bd846722962662d91c9eb04ia624aa42c2ca7c8e876187d1db3a3875",
        kind: "audiooutput",
        label: "",
      }
      

      Remarque : une étiquette ne sera pas renvoyée si un flux n’est pas disponible ou si l’utilisateur a accordé des autorisations d’accès au dispositif.

      Étape 5 – Afficher le flux vidéo sur le navigateur

      Vous êtes passé(e) par le processus de demande et d’obtention de l’accès aux appareils multimédias, vous avez configuré des contraintes pour inclure les résolutions requises et vous avez sélectionné la caméra dont vous aurez besoin pour enregistrer la vidéo.

      Après avoir parcouru toutes ces étapes, vous voudrez au moins voir si le flux est diffusé en fonction des paramètres configurés. Pour ce faire, vous utiliserez l’élément <vidéo> pour afficher le flux vidéo sur le navigateur.

      Comme mentionné précédemment, la méthode getUserMedia renvoie une Promise qui peut être résolue en un flux. Le flux renvoyé peut être converti en une URL objet en utilisant la méthode createObjectURL. Cette URL sera définie comme une source vidéo.

      Vous allez créer une courte démo dans laquelle nous laissons l’utilisateur choisir parmi la liste des appareils vidéo disponibles avec la méthode enumerateDevices.

      Ceci est une méthode navigateur.mediaDevices. Elle énumère les périphériques médias disponibles, tels que les microphones et les caméras. Elle renvoie une Promise résolvable à un ensemble d’objets détaillant les périphériques médias disponibles.

      Créez un fichier index.html et mettez à jour le contenu avec le code ci-dessous :

      index.html

      <!doctype html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport"
                content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
          <meta http-equiv="X-UA-Compatible" content="ie=edge">
          <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
          <link rel="stylesheet" href="style.css">
          <title>Document</title>
      </head>
      <body>
      <div class="display-cover">
          <video autoplay></video>
          <canvas class="d-none"></canvas>
      
          <div class="video-options">
              <select name="" id="" class="custom-select">
                  <option value="">Select camera</option>
              </select>
          </div>
      
          <img class="screenshot-image d-none" alt="">
      
          <div class="controls">
              <button class="btn btn-danger play" title="Play"><i data-feather="play-circle"></i></button>
              <button class="btn btn-info pause d-none" title="Pause"><i data-feather="pause"></i></button>
              <button class="btn btn-outline-success screenshot d-none" title="ScreenShot"><i data-feather="image"></i></button>
          </div>
      </div>
      
      <script src="https://unpkg.com/feather-icons"></script>
      <script src="script.js"></script>
      </body>
      </html>
      

      Dans l’extrait ci-dessus, vous avez mis en place les éléments dont vous aurez besoin et quelques contrôles pour la vidéo. Un bouton permettant de prendre des captures d’écran du flux vidéo en cours est également inclus.

      Maintenant, mettons un peu de style dans ces éléments.

      Créez un fichier style.css et copiez les styles suivants dans celui-ci. Bootstrap a été inclus pour réduire la quantité de CSS que vous devrez écrire pour faire fonctionner les composants.

      style.css

      .screenshot-image {
          width: 150px;
          height: 90px;
          border-radius: 4px;
          border: 2px solid whitesmoke;
          box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);
          position: absolute;
          bottom: 5px;
          left: 10px;
          background: white;
      }
      
      .display-cover {
          display: flex;
          justify-content: center;
          align-items: center;
          width: 70%;
          margin: 5% auto;
          position: relative;
      }
      
      video {
          width: 100%;
          background: rgba(0, 0, 0, 0.2);
      }
      
      .video-options {
          position: absolute;
          left: 20px;
          top: 30px;
      }
      
      .controls {
          position: absolute;
          right: 20px;
          top: 20px;
          display: flex;
      }
      
      .controls > button {
          width: 45px;
          height: 45px;
          text-align: center;
          border-radius: 100%;
          margin: 0 6px;
          background: transparent;
      }
      
      .controls > button:hover svg {
          color: white !important;
      }
      
      @media (min-width: 300px) and (max-width: 400px) {
          .controls {
              flex-direction: column;
          }
      
          .controls button {
              margin: 5px 0 !important;
          }
      }
      
      .controls > button > svg {
          height: 20px;
          width: 18px;
          text-align: center;
          margin: 0 auto;
          padding: 0;
      }
      
      .controls button:nth-child(1) {
          border: 2px solid #D2002E;
      }
      
      .controls button:nth-child(1) svg {
          color: #D2002E;
      }
      
      .controls button:nth-child(2) {
          border: 2px solid #008496;
      }
      
      .controls button:nth-child(2) svg {
          color: #008496;
      }
      
      .controls button:nth-child(3) {
          border: 2px solid #00B541;
      }
      
      .controls button:nth-child(3) svg {
          color: #00B541;
      }
      
      .controls > button {
          width: 45px;
          height: 45px;
          text-align: center;
          border-radius: 100%;
          margin: 0 6px;
          background: transparent;
      }
      
      .controls > button:hover svg {
          color: white;
      }
      

      L’étape suivante consiste à ajouter des fonctionnalités à la démo. En utilisant la méthode enumerateDevices vous obtiendrez les appareils vidéo disponibles et vous les paramèterez comme options au sein de l’élément de sélection. Créez un fichier appelé script.js et mettez-le à jour avec l’extrait suivant :

      script.js

      feather.replace();
      
      const controls = document.querySelector('.controls');
      const cameraOptions = document.querySelector('.video-options>select');
      const video = document.querySelector('video');
      const canvas = document.querySelector('canvas');
      const screenshotImage = document.querySelector('img');
      const buttons = [...controls.querySelectorAll('button')];
      let streamStarted = false;
      
      const [play, pause, screenshot] = buttons;
      
      const constraints = {
        video: {
          width: {
            min: 1280,
            ideal: 1920,
            max: 2560,
          },
          height: {
            min: 720,
            ideal: 1080,
            max: 1440
          },
        }
      };
      
      const getCameraSelection = async () => {
        const devices = await navigator.mediaDevices.enumerateDevices();
        const videoDevices = devices.filter(device => device.kind === 'videoinput');
        const options = videoDevices.map(videoDevice => {
          return `<option value="${videoDevice.deviceId}">${videoDevice.label}</option>`;
        });
        cameraOptions.innerHTML = options.join('');
      };
      
      play.onclick = () => {
        if (streamStarted) {
          video.play();
          play.classList.add('d-none');
          pause.classList.remove('d-none');
          return;
        }
        if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) {
          const updatedConstraints = {
            ...constraints,
            deviceId: {
              exact: cameraOptions.value
            }
          };
          startStream(updatedConstraints);
        }
      };
      
      const startStream = async (constraints) => {
        const stream = await navigator.mediaDevices.getUserMedia(constraints);
        handleStream(stream);
      };
      
      const handleStream = (stream) => {
        video.srcObject = stream;
        play.classList.add('d-none');
        pause.classList.remove('d-none');
        screenshot.classList.remove('d-none');
        streamStarted = true;
      };
      
      getCameraSelection();
      

      Dans l’extrait ci-dessus, il y a deux choses qui se passent. Décomposons celles-ci :

      1. feather.replace() : cette méthode d’appel instancie feather qui est un ensemble d’icônes pour le développement web.
      2. La variable constraints contient la configuration initiale du flux. Elle sera étendue pour inclure le périphérique média choisi par l’utilisateur.
      3. getCameraSelection : cette fonction appelle la méthode enumerateDevices. Ensuite, vous filtrez le tableau à partir de la Promise résolue et sélectionnez les périphériques d’entrée vidéo À partir des résultats filtrés, vous créez <option> pour l’élément <select>.
      4. L’appel de la méthode getUserMedia se fait à l’intérieur de l’écouteur onclick du bouton de lecture. Ici, vous vérifierez si cette méthode est prise en charge par le navigateur de l’utilisateur avant de lancer le flux.
      5. Ensuite, vous appellerez la fonction startStream qui prend un argument constraints. Elle appelle la méthode getUserMedia avec les constraints fournies.handleStream est appelé en utilisant le flux de la Promise résolue Cette méthode fixe le flux renvoyé à l’élément vidéo srcObject.

      Ensuite, vous ajouterez des écouteurs de clics aux boutons de commande de la page pour faire une pause, arrêter et faire des captures d'écran. De plus, vous ajouterez un auditeur à l’élément <select> pour mettre à jour les contraintes de flux avec le périphérique vidéo sélectionné.

      Mettez à jour le fichier script.js avec le code ci-dessous :

      script.js

      ...
      cameraOptions.onchange = () => {
        const updatedConstraints = {
          ...constraints,
          deviceId: {
            exact: cameraOptions.value
          }
        };
        startStream(updatedConstraints);
      };
      
      const pauseStream = () => {
        video.pause();
        play.classList.remove('d-none');
        pause.classList.add('d-none');
      };
      
      const doScreenshot = () => {
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        canvas.getContext('2d').drawImage(video, 0, 0);
        screenshotImage.src = canvas.toDataURL('image/webp');
        screenshotImage.classList.remove('d-none');
      };
      
      pause.onclick = pauseStream;
      screenshot.onclick = doScreenshot;
      

      Maintenant, lorsque vous ouvrez l’index.html dans le navigateur, cliquer le bouton Play permet de lancer le flux.

      Voici une démo complète :

      Conclusion

      Ce tutoriel a introduit l’API getUserMedia. C’est un ajout intéressant à HTML5, qui facilite le processus de capture des médias sur le web.

      L’API prend un paramètre (constraints) qui peut être utilisé pour configurer l’accès aux périphériques d’entrée audio et vidéo. Il peut également être utilisé pour spécifier la résolution vidéo requise pour votre application.

      Vous pouvez étendre la démo pour donner à l’utilisateur la possibilité de sauvegarder les captures d’écran réalisées, ainsi que d’enregistrer et de stocker des données vidéo et audio à l’aide de l’API MediaStream Recording.



      Source link

      Cómo acceder remotamente a aplicaciones GUI usando Docker y Caddy en Ubuntu 18.04


      El autor seleccionó la Free and Open Source Fund para recibir una donación como parte del programa Write for DOnations.

      Introducción

      Aún con la creciente popularidad de los servicios en la nube, la necesidad de ejecutar aplicaciones nativas sigue existiendo.

      Con noVNC y TigerVNC, puede ejecutar aplicaciones nativas dentro de un contenedor Docker y acceder a ellas remotamente usando un navegador web. Adicionalmente, puede ejecutar su aplicación en un servidor con más recursos del sistema de los que pueda tener disponibles localmente, lo que puede proporcionar mayor flexibilidad cuando se ejecutan grandes aplicaciones.

      En este tutorial, pondrá en un contendor Mozilla Thunderbird, un cliente de correo electrónico, usando Docker. Tras ello, lo protegerá y proporcionará acceso remoto usando el servidor web Caddy.

      Cuando haya terminado, podrá acceder a Thunderbird desde cualquier dispositivo usando únicamente un navegador web. Opcionalmente, podrá acceder localmente a los archivos usando WebDAV. También tendrá una imagen Docker completamente autocontenida que puede ejecutar en cualquier lugar.

      Requisitos previos

      Antes de iniciar esta guía, necesitará lo siguiente:

      Paso 1: Crear la configuración supervisord

      Ahora que su servidor está ejecutándose y Docker está instalado, está listo para comenzar a configurar el contenedor de su aplicación. Ya que su contenedor consta de varios componentes, deberá usar un administrador de procesos para iniciarlos y monitorizarlos. Aquí usará supervisord. supervisord es un gestor de procesos escrito en Python que se utiliza a menudo para organizar contenedores complejos.

      Primero, cree y entre en un directorio llamado thunderbird para su contenedor.

      • mkdir ~/thunderbird
      • cd ~/thunderbird

      Ahora cree y abra un archivo llamado supervisord.conf usando nano o su editor preferido:

      Ahora añada este primer bloque de código en supervisord.conf, lo que definirá las opciones globales para supervisord:

      ~/thunderbird/supervisord.conf

      [supervisord]
      nodaemon=true
      pidfile=/tmp/supervisord.pid
      logfile=/dev/fd/1
      logfile_maxbytes=0
      

      En este bloque, está configurando supervisord. Deberá establecer nodaemon a true porque se ejecutará dentro de un contenedor Docker como el punto de entrada. Por tanto, querrá que permanezca en ejecución en primer plano. También configura pidfile a una ruta accesible por un usuario non-root (más sobre esto más tarde), y logfile to stdout para que pueda ver los registros.

      A continuación, añada otro bloque de código pequeño a supervisord.conf. Este bloque inicia TigerVNC que es un servidor VNC/X11 combinado:

      ~/thunderbird/supervisord.conf

      ...
      [program:x11]
      priority=0
      command=/usr/bin/Xtigervnc -desktop "Thunderbird" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      En este bloque, está configurando el servidor X11. X11 es un protocolo de servidor de visualización, que es lo que permite que se ejecuten las aplicaciones GUI. Tenga en cuenta que en el futuro se sustituirá con Wayland, pero el acceso remoto aún está en desarrollo.

      Para este contenedor, está usando TigerVNC y está integrado en el servidor VNC. Esto tiene varias ventajas sobre el uso de un servidor X11 y VNC:

      • Tiempo de respuesta más rápido, ya que el dibujo de la GUI se realiza directamente en el servidor VNC en vez de hacerse en un framebuffer intermedio (la memoria que almacena los contenidos de la pantalla).
      • Cambio de tamaño automático de la pantalla, que permite a la aplicación remota cambiar de tamaño automáticamente para que se ajuste al cliente (en este caso, la ventana de su navegador web).

      Si lo desea, puede cambiar el argumento para la opción -desktop desde Thunderbird a otra cosa que elija. El servidor mostrará su opción como el título de la página web usada para acceder a su aplicación.

      Ahora, vamos a añadir un tercer bloque de código a supervisord.conf para iniciar easy-novnc:

      ~/thunderbird/supervisord.conf

      ...
      [program:easy-novnc]
      priority=0
      command=/usr/local/bin/easy-novnc --addr :8080 --host localhost --port 5900 --no-url-password --novnc-params "resize=remote"
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      En este bloque, está configurando easy-novnc, un servidor independiente que ofrece un envoltorio alrededor de noVNC. Este servidor realiza dos funciones. Primero, proporciona una página sencilla de conexión que le permite configurar opciones para la conexión, y le permite establecer las predeterminadas. Segundo, realiza proxy a VNC sobre WebSocket, lo que permite el acceso a través de un navegador web ordinario.

      Normalmente, el cambio de tamaño se realiza en el lado del cliente (es decir, escala de imagen), pero está usando la opción resize=remote para aprovechar los ajustes de resolución remota de TigerVNC. Esto también proporciona una menor latencia en dispositivos más lentos, como Chromebooks de gama baja:

      Nota: Este tutorial utiliza easy-novnc. Si lo desea, puede usar websockfy y un servidor web independiente. La ventaja de easy-novnc es que el uso de memoria y el tiempo de inicio es significativamente menor que si fuese auto-contenido. easy-novnc también proporciona una página conexión más limpia que la de noVNC predeterminado, y permite establecer opciones predeterminadas que son útiles para esta configuración (como resize=remote).

      Ahora añada el siguiente bloque a su configuración para iniciar OpenBox, el gestor de ventanas:

      ~/thunderbird/supervisord.conf

      ...
      [program:openbox]
      priority=1
      command=/usr/bin/openbox
      environment=DISPLAY=:0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      En este bloque, está configurando OpenBox, un gestor de ventanas X11 ligero. Podría omitir este paso, pero sin él no tendría las barras de título o podría cambiar el tamaño de las ventanas.

      Finalmente, vamos a añadir el último bloque a supervisord.conf, que iniciará la aplicación principal:

      ~/thunderbird/supervisord.conf

      ...
      [program:app]
      priority=1
      environment=DISPLAY=:0
      command=/usr/bin/thunderbird
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      En este bloque final, está configurando priority a 1 para garantizar que Thunderbird se inicia tras TigerVNC, o encontrará una condición de carrera o fallaría aleatoriamente al inicio. También configuramos autorestart=true para que vuelva a abrir automáticamente la aplicación si se cierra por error. La variable de entorno DISPLAY indica a la aplicación que se muestre en el servidor VNC que configuró anteriormente.

      Este es el aspecto que tendrá su supervisord.conf completado:

      ~/thunderbird/supervisord.conf

      [supervisord]
      nodaemon=true
      pidfile=/tmp/supervisord.pid
      logfile=/dev/fd/1
      logfile_maxbytes=0
      
      [program:x11]
      priority=0
      command=/usr/bin/Xtigervnc -desktop "Thunderbird" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      
      [program:easy-novnc]
      priority=0
      command=/usr/local/bin/easy-novnc --addr :8080 --host localhost --port 5900 --no-url-password --novnc-params "resize=remote"
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      
      [program:openbox]
      priority=1
      command=/usr/bin/openbox
      environment=DISPLAY=:0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      
      [program:app]
      priority=1
      environment=DISPLAY=:0
      command=/usr/bin/thunderbird
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      Si desea poner una aplicación diferente en contenedor, sustituya /usr/bin/thunderbird con la ruta al ejecutable de su aplicación. De lo contrario, estará listo para configurar el menú principal de su GUI.

      Paso 2: Configurar el menú de OpenBox

      Ahora que su gestor de procesos está configurado, vamos a configurar el menú de OpenBox. Este menú nos permite abrir aplicaciones dentro del contenedor. También incluiremos un monitor de terminal y procesos para depurar si es necesario.

      Dentro del directorio de la aplicación, utilice nano o su editor de texto favorito para crear y abrir un nuevo archivo llamado menu.xml:

      • nano ~/thunderbird/menu.xml

      Ahora añada el siguiente código a menu.xml:

      ~/thunderbird/menu.xml

      <?xml version="1.0" encoding="utf-8"?>
      <openbox_menu xmlns="http://openbox.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openbox.org/ file:///usr/share/openbox/menu.xsd">
          <menu id="root-menu" label="Openbox 3">
              <item label="Thunderbird">
                  <action name="Execute">
                      <execute>/usr/bin/thunderbird</execute>
                  </action>
              </item>
              <item label="Terminal">
                  <action name="Execute">
                      <execute>/usr/bin/x-terminal-emulator</execute>
                  </action>
              </item>
              <item label="Htop">
                  <action name="Execute">
                      <execute>/usr/bin/x-terminal-emulator -e htop</execute>
                  </action>
              </item>
          </menu>
      </openbox_menu>
      

      Este archivo XML contiene los elementos del menú que aparecerán cuando haga clic con el botón derecho sobre el escritorio. Cada elemento consta de una etiqueta y una acción.

      Si desea añadir al contenedor una aplicación diferente, sustituya /usr/bin/thunderbird con la ruta al ejecutable de su aplicación y cambie la etiqueta del elemento.

      Paso 3: Crear el Dockerfile

      Ahora que OpenBox está configurado, creará el Dockerfile, que une todo.

      Crear un Dockerfile en el directorio de su contenedor:

      • nano ~/thunderbird/Dockerfile

      Para comenzar, vamos a añadir algún código para crear easy-novnc:

      ~/thunderbird/Dockerfile

      FROM golang:1.14-buster AS easy-novnc-build
      WORKDIR /src
      RUN go mod init build && 
          go get github.com/geek1011/[email protected] && 
          go build -o /bin/easy-novnc github.com/geek1011/easy-novnc
      

      En la primera etapa, está creando easy-novnc. Esto se hace en una etapa independiente para mayor simplificada y para ahorrar espacio; no necesita toda la cadena de herramientas de go en su imagen final. Observe @v1.1.0 en el comando de compilación. Esto garantiza que el resultado sea determinista, lo cual es importante porque Docker captura el resultado de cada paso. Si no hubiese especificado una versión explícita, Docker haría referencia a la versión más reciente de easy-novnc en el momento en que se compiló la imagen por primera vez. Además, desea garantizar que descarga una versión específica de easy-novnc, en el caso de que se realicen cambios de ruptura en la interfaz CLI.“”“”

      Ahora vamos a crear la segunda etapa que será la imagen final. Aquí usará Debian 10 (buster) como imagen base. Observe que dado que se está ejecutando en un contenedor, funcionará independientemente de la distribución que esté ejecutando en su servidor.

      A continuación, añada el siguiente bloque a su Dockerfile:

      ~/thunderbird/Dockerfile

      ...
      FROM debian:buster
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends openbox tigervnc-standalone-server supervisor gosu && 
          rm -rf /var/lib/apt/lists && 
          mkdir -p /usr/share/desktop-directories
      

      En esta instrucción, está instalando Debian 10 como su imagen base y luego instalando el mínimo necesario para ejecutar aplicaciones GUI en su contenedor. Observe que ejecuta apt-get update como parte de la misma instrucción para evitar problemas de captura desde Docker. Para ahorrar espacio, también está eliminando las listas de paquetes descargadas posteriormente (los paquetes en caché en sí mismos se eliminan por defecto). Está creando /usr/share/desktop-directories porque algunas aplicaciones dependen de que exista el directorio.

      Vamos a añadir otro bloque de código pequeño:

      ~/thunderbird/Dockerfile

      ...
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends lxterminal nano wget openssh-client rsync ca-certificates xdg-utils htop tar xzip gzip bzip2 zip unzip && 
          rm -rf /var/lib/apt/lists
      

      En esta instrucción, está instalando algunas utilidades y paquetes útiles de uso general. Son interesantes xdg-utils (que proporciona los comandos base usados por las aplicaciones de escritorio en Linux) y ca-certificates (que instala los certificados raíz para permitirnos acceder a los sitios HTTPS).

      Ahora, podemos añadir las instrucciones para la aplicación principal:

      ~/thunderbird/Dockerfile

      ...
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends thunderbird && 
          rm -rf /var/lib/apt/lists
      

      Como antes, aquí estamos instalando la aplicación. Si añade una aplicación diferente al contenedor, puede sustituir estos comandos con los necesarios para instalar su aplicación específica. Algunas aplicaciones requerirán un poco más de trabajo para ejecutarse dentro de Docker. Por ejemplo, si está instalando una aplicación que utiliza Chrome, Chromium o QtWebEngine, deberá usar el argumento de línea de comando --no-sandbox porque no será compatible en Docker.

      A continuación, vamos a comenzar añadiendo las instrucciones para añadir las últimas líneas al contenedor:

      ~/thunderbird/Dockerfile

      ...
      COPY --from=easy-novnc-build /bin/easy-novnc /usr/local/bin/
      COPY menu.xml /etc/xdg/openbox/
      COPY supervisord.conf /etc/
      EXPOSE 8080
      

      Aquí está añadiendo los archivos de configuración que creó anteriormente a la imagen y copiando el binario easy-novnc de la primera etapa.

      Este siguiente bloque de código crea el directorio de datos y añade un usuario dedicado para su aplicación. Esto es importante porque algunas aplicaciones no se ejecutan como root. También es una buena práctica no ejecutar aplicaciones como root, incluso en un contenedor.

      ~/thunderbird/Dockerfile

      ...
      RUN groupadd --gid 1000 app && 
          useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && 
          mkdir -p /data
      VOLUME /data
      

      Para garantizar un UID/GID consistente para los archivos, está estableciendo explícitamente ambos a 1000. También está montando un volumen sobre el directorio de datos para garantizar que persiste entre los reinicios.

      Finalmente, vamos a añadir las instrucciones para iniciar todo:

      ~/thunderbird/Dockerfile

      ...
      CMD ["sh", "-c", "chown app:app /data /dev/stdout && exec gosu app supervisord"]
      

      Al establecer el comando predeterminado a supervisord, el administrador iniciará los procesos requeridos para ejecutar su aplicación. En este caso, está usando CMD en vez de ENTRYPOINT. En la mayoría de los casos, no supondría una diferencia, pero usar CMD es mejor para este fin por algunos motivos. Primero, supervisord no toma ningún argumento que sería relevante para nosotros, y si proporciona argumentos al contenedor, sustituye CMD y se anexan a ENTRYPOINT. Segundo, usar CMD nos permite proporcionar un comando completamente diferente (que se será ejecutado por /bin/sh -c) cuando se pasan argumentos al contenedor, lo que hace que la depuración sea más fácil.

      Y finalmente, deberá ejecutar chown como raíz antes de iniciar supervisord para evitar problemas de permisos sobre el volumen de datos y para permitir que se abran los procesos secundarios stdout. Esto también significa que deberá usar gosu en vez de la instrucción USER para cambiar al usuario.

      Este es el aspecto que tendrá su archivo Dockerfile completado:

      ~/thunderbird/Dockerfile

      FROM golang:1.14-buster AS easy-novnc-build
      WORKDIR /src
      RUN go mod init build && 
          go get github.com/geek1011/[email protected] && 
          go build -o /bin/easy-novnc github.com/geek1011/easy-novnc
      
      FROM debian:buster
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends openbox tigervnc-standalone-server supervisor gosu && 
          rm -rf /var/lib/apt/lists && 
          mkdir -p /usr/share/desktop-directories
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends lxterminal nano wget openssh-client rsync ca-certificates xdg-utils htop tar xzip gzip bzip2 zip unzip && 
          rm -rf /var/lib/apt/lists
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends thunderbird && 
          rm -rf /var/lib/apt/lists
      
      COPY --from=easy-novnc-build /bin/easy-novnc /usr/local/bin/
      COPY menu.xml /etc/xdg/openbox/
      COPY supervisord.conf /etc/
      EXPOSE 8080
      
      RUN groupadd --gid 1000 app && 
          useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && 
          mkdir -p /data
      VOLUME /data
      
      CMD ["sh", "-c", "chown app:app /data /dev/stdout && exec gosu app supervisord"]
      

      Guarde y cierre su Dockerfile. Ahora estamos listos para crear y ejecutar nuestro contenedor, y luego acceder a Thunderbird – una aplicación GUI.

      Paso 4: Crear y ejecutar el contenedor

      El siguiente paso es crear su contenedor y configurarlo para que se ejecute al inicio. También configurará un volumen para conservar los datos de la aplicación entre reinicios y actualizaciones.

      Primero, cree su contenedor. Asegúrese de ejecutar estos comandos en el directorio ~/thunderbird:

      • docker build -t thunderbird .

      Ahora cree una nueva red que será compartida entre los contenedores de la aplicación:

      • docker network create thunderbird-net

      A continuación, cree un volumen para almacenar los datos de la aplicación:

      • docker volume create thunderbird-data

      Finalmente, ejecútelo para que se reinicie automáticamente:

      • docker run --detach --restart=always --volume=thunderbird-data:/data --net=thunderbird-net --name=thunderbird-app thunderbird

      Tenga en cuenta que si lo desea, puede sustituir thunderbird-app tras la opción --nombre con un nombre diferente. Sea cual sea su elección, su aplicación ahora está en contenedor y ejecutándose. Ahora vamos a usar el servidor web Caddy para protegerla y conectar remotamente a ella.

      Paso 5: Configurar Caddy

      En este paso, configurará el servidor web Caddy para proporcionar autenticación y, opcionalmente, acceso remoto a los archivos sobre WebDAV. Para mayor simplicidad, y para permitirle usarlo con su proxy inverso existente, lo ejecutará en otro contenedor.

      Cree un nuevo directorio y muévalo dentro:

      Ahora cree un nuevo Dockerfile usando nano o su editor preferido:

      Luego, añada las siguientes directivas:

      ~/caddy/Dockerfile

      FROM golang:1.14-buster AS caddy-build
      WORKDIR /src
      RUN echo 'module caddy' > go.mod && 
          echo 'require github.com/caddyserver/caddy/v2 v2.0.0' >> go.mod && 
          echo 'require github.com/mholt/caddy-webdav v0.0.0-20200523051447-bc5d19941ac3' >> go.mod
      RUN echo 'package main' > caddy.go && 
          echo 'import caddycmd "github.com/caddyserver/caddy/v2/cmd"' >> caddy.go && 
          echo 'import _ "github.com/caddyserver/caddy/v2/modules/standard"' >> caddy.go && 
          echo 'import _ "github.com/mholt/caddy-webdav"' >> caddy.go && 
          echo 'func main() { caddycmd.Main() }' >> caddy.go
      RUN go build -o /bin/caddy .
      
      FROM debian:buster
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends gosu && 
          rm -rf /var/lib/apt/lists
      
      COPY --from=caddy-build /bin/caddy /usr/local/bin/
      COPY Caddyfile /etc/
      EXPOSE 8080
      
      RUN groupadd --gid 1000 app && 
          useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && 
          mkdir -p /data
      VOLUME /data
      
      WORKDIR /data
      CMD ["sh", "-c", "chown app:app /data && exec gosu app /usr/local/bin/caddy run -adapter caddyfile -config /etc/Caddyfile"]
      

      Este Dockerfile crea Caddy con el complemento WebDAV habilitado, y luego lo abre en el puerto 8080 con Caddyfile en /etc/Caddyfile. Guarde y cierre el archivo.

      A continuación, configurará el servidor web Caddy. Cree un archivo llamado Caddyfile en el directorio que acaba de crear:

      Ahora añada el siguiente bloque de código a su Caddyfile:

      ~/caddy/Caddyfile

      {
          order webdav last
      }
      :8080 {
          log
          root * /data
          reverse_proxy thunderbird-app:8080
      
          handle /files/* {
              uri strip_prefix /files
              file_server browse
          }
          redir /files /files/
      
          handle /webdav/* {
              uri strip_prefix /webdav
              webdav
          }
          redir /webdav /webdav/
      
          basicauth /* {
              {env.APP_USERNAME} {env.APP_PASSWORD_HASH}
          }
      }
      

      Este Caddyfile realiza proxy el directorio raíz al contenedor thunderbird-app que creó en el Paso 4 (Docker lo resuelve a la IP correcta). También servirá como un navegador de archivo basado en web solo lectura en /files y para ejecutar el servidor WebDAV en /webdav que puede montar localmente para acceder a sus archivos. El nombre de usuario y la contraseña se leen desde las variables de entorno APP_USERNAME y APP_PASSWORD_HASH.

      Ahora cree el contenedor:

      • docker build -t thunderbird-caddy .

      Caddy v.2 requiere que haga hash a su contraseña deseada. Ejecute el siguiente comando y recuerde sustituir mypass con una contraseña fuerte que elija:

      • docker run --rm -it thunderbird-caddy caddy hash-password -plaintext 'mypass'

      Este comando dará como resultado una cadena de caracteres. Copie esto a su portapapeles para prepararse para ejecutar el siguiente comando.

      Ahora está listo para ejecutar el contenedor. Asegúrese de sustituir myuser con un nombre de usuario que elija, y sustituya mypass-hash con el resultado del comando que ejecutó en el paso anterior. Puede cambiar también el puerto (8080 aquí) para acceder a su servidor en un puerto diferente:

      • docker run --detach --restart=always --volume=thunderbird-data:/data --net=thunderbird-net --name=thunderbird-web --env=APP_USERNAME="myuser" --env=APP_PASSWORD_HASH="mypass-hash" --publish=8080:8080 thunderbird-caddy

      Ahora está listo para acceder y probar nuestra aplicación.

      Paso 6: Probar y administrar la aplicación

      Vamos a acceder a su aplicación y a asegurarnos de que está funcionando.

      Primero, abra http://your_server_ip:8080 en un navegador web, inicie sesión con las credenciales que seleccionó anteriormente y haga clic en Connect.

      Página de conexión de NoVNC

      Ahora debería poder interactuar con la aplicación, y debería cambiar de tamaño automáticamente para que se adapte a la ventana de su navegador.

      Menú principal de Thunderbird

      Si hace clic con el botón derecho en el escritorio en negro, debería ver un menú que le permite acceder a un terminal. Si hace clic en el centro, debería ver una lista de ventanas.

      Clic derecho en NoVNC

      Ahora abra http://your_server_ip:8080/files/ en un navegador web. Debería poder acceder a sus archivos.

      Archivo de acceso webdav a NoVNC

      Opcionalmente, puede intentar montar http://your_server_ip:8080/webdav/ en un cliente WebDAV. Debería poder acceder y modificar sus archivos directamente. Si utiliza la opción Asignar unidad de red en Windows Explorer, necesitará usar un proxy inverso para añadir HTTPS o establecer HKLMSYSTEMCurrentControlSetServicesWebClientParametersBasicAuthLevel​​​ a DWORD:2.

      En cualquier caso, su aplicación GUI nativa está ahora lista para su uso remoto.

      Conclusión

      Ahora ha configurado correctamente un contenedor Docker para Thunderbird y a continuación, usando Caddy, ha configurado el acceso a él a través de un navegador web. Si alguna vez necesita actualizar su aplicación, detenga los contenedores, ejecute docker rm thunderbird-app thunderbird-web, vuelva a crear las imágenes, y vuelva a ejecutar los comandos docker run de los pasos anteriores. Sus datos se conservarán, ya que se almacenan en un volumen.

      Si desea obtener más información sobre los comandos Docker básicos, puede leer este tutorial o esta hoja de trucos. Para un uso a más largo plazo, quizá desee considerar habilitar HTTPS (esto requiere un dominio) para mayor seguridad.

      Además, si está implementando más de una aplicación, es posible que desee usar Docker Compose o Kubernetes en vez de iniciar cada contenedor manualmente. Y recuerde, este tutorial puede servir como base para ejecutar cualquier otra aplicación Linux en su servidor, incluyendo:

      • Wine, una capa de compatibilidad para ejecutar aplicaciones Windows en Linux.
      • GIMP, un editor de imágenes de código abierto.
      • Cutter, una plataforma de ingeniería inversa de código abierto:

      Esta última opción demuestra el gran potencial de usar contendores y acceder remotamente a aplicaciones GUI. Con esta configuración, puede usar un servidor con una potencia de computación considerablemente mayor que si utilizase localmente herramientas que consumen muchos recursos como Cutter.



      Source link

      Comment accéder à distance aux applications GUI en utilisant Docker et Caddy sur Ubuntu 18.04


      L’auteur a choisi le Free and Open Source Fund pour recevoir un don dans le cadre du programme Write for Donations.

      Introduction

      Même avec la popularité croissante des services cloud, le besoin d’exécuter des applications natives existe toujours.

      En utilisant noVNC et TigerVNC,vous pouvez exécuter des applications natives dans un conteneur Docker et y accéder à distance à l’aide d’un navigateur web. En outre, vous pouvez exécuter votre application sur un serveur disposant de plus de ressources système que celles dont vous disposez localement, ce qui peut offrir une plus grande flexibilité lors de l’exécution de grandes applications.

      Dans ce tutoriel, vous allez conteneuriser Mozilla Thunderbird, un client de messagerie électronique, en utilisant Docker. Ensuite, vous le sécuriserez et lui donnerez un accès à distance en utilisant le serveur web de Caddy.

      Lorsque vous aurez terminé, vous pourrez accéder à Thunderbird depuis n’importe quel appareil en utilisant simplement un navigateur web. En option, vous pourrez également accéder localement aux fichiers de ce site en utilisant WebDAV. Vous aurez également une image de Docker entièrement autonome que vous pourrez exécuter n’importe où.

      Conditions préalables

      Avant de commencer ce guide, vous aurez besoin de ce qui suit :

      Étape 1 &mdash ; Créer la Configuration de supervisord

      Maintenant que votre serveur fonctionne et que Docker est installé, vous êtes prêt à commencer à configurer le conteneur de votre application. Comme votre conteneur est constitué de plusieurs composants, vous devez utiliser un gestionnaire de processus pour les lancer et les surveiller. Ici, vous utiliserez supervisord. supervisord est un gestionnaire de processus écrit en Python qui est souvent utilisé pour orchestrer des conteneurs complexes. 

      Tout d’abord, créez et entrez un répertoire appelé thunderbird pour votre conteneur : 

      • mkdir ~/thunderbird
      • cd ~/thunderbird

      Maintenant, créez et ouvrez un fichier appelé supervisord.conf utilisant nano ou votre éditeur préféré :

      Ajoutez maintenant ce premier bloc de code dans supervisord.conf, qui définira les options globales de supervisord :

      ~/thunderbird/supervisord.conf

      [supervisord]
      nodaemon=true
      pidfile=/tmp/supervisord.pid
      logfile=/dev/fd/1
      logfile_maxbytes=0
      

      Dans ce bloc, vous configurez supervisord lui-même. Vous devez mettre nodaemon sur true parce qu’il sera placé à l’intérieur d’un conteneur Docker comme point d’entrée. Par conséquent, vous voulez qu’il reste au premier plan. Vous mettez également en place pidfile vers un chemin accessible par un non-root user (nous y reviendrons plus tard), et logfile vers stdout pour que vous puissiez voir les journaux. 

      Ensuite, ajoutez un autre petit bloc de code à supervisord.conf. Ce bloc démarre TigerVNC, qui est un serveur combiné VNC/X11 :

      ~/thunderbird/supervisord.conf

      ...
      [program:x11]
      priority=0
      command=/usr/bin/Xtigervnc -desktop "Thunderbird" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      Dans ce bloc, vous configurez le serveur X11. X11 est un protocole de serveur d’affichage, qui permet aux applications graphiques de s’exécuter. Notez qu’à l’avenir il sera remplacé par Wayland, mais l’accès à distance est encore en développement.

      Pour ce conteneur, vous utilisez TigerVNC et son serveur VNC intégré. Cela présente un certain nombre d’avantages par rapport à l’utilisation d’un serveur X11 et VNC séparé :

      • Temps de réponse plus rapide, car le dessin de l’interface graphique est fait directement sur le serveur VNC plutôt que d’être fait sur un framebuffer intermédiaire (la mémoire qui stocke le contenu de l’écran).
      • Le redimensionnement automatique de l’écran, qui permet à l’application distante de se redimensionner automatiquement en fonction du client (dans ce cas, la fenêtre de votre navigateur web).

      Si vous le souhaitez, vous pouvez changer l’argument pour l’option -desktop de Thunderbird à quelque chose d’autre de votre choix. Le serveur affichera votre choix comme titre de la page web utilisée pour l’accès à votre application.

      Maintenant, ajoutons un troisième bloc de code à supervisord.conf pour démarrer easy-novnc : 

      ~/thunderbird/supervisord.conf

      ...
      [program:easy-novnc]
      priority=0
      command=/usr/local/bin/easy-novnc --addr :8080 --host localhost --port 5900 --no-url-password --novnc-params "resize=remote"
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      Dans ce bloc, vous mettez en place easy-novncun serveur autonome qui fournit une wrapper autour de noVNC Ce serveur joue deux rôles. Tout d’abord, il fournit une page de connexion simple qui vous permet de configurer des options pour la connexion, et vous permet de définir des options par défaut. Deuxièmement, il permet à VNC de se substituer à WebSocket, qui permet d’y accéder au moyen d’un navigateur web ordinaire. 

      Habituellement, le redimensionnement se fait du côté client (c’est-à-dire la mise à l’échelle de l’image), mais vous utilisez l’option resize=remote pour profiter pleinement des ajustements de la résolution à distance de TigerVNC. Cela permet également de réduire la latence sur les appareils plus lents, tels que les Chromebooks bas de gamme :

      Note : Ce tutoriel utilise easy-novnc. Si vous le souhaitez, vous pouvez utiliser websockify et un serveur web séparé à la place. L’avantage d’easy-novnc est que l’utilisation de la mémoire et le temps de démarrage sont nettement plus faibles et que c’est autonome. easy-novnc fournit également une page de connexion plus propre que celle par défaut de noVNC et permet de définir des options par défaut qui sont utiles pour cette configuration (telles que resize=remote).

      Ajoutez maintenant le bloc suivant à votre configuration pour lancer OpenBox, le gestionnaire de fenêtres :

      ~/thunderbird/supervisord.conf

      ...
      [program:openbox]
      priority=1
      command=/usr/bin/openbox
      environment=DISPLAY=:0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      Dans ce bloc, vous mettez en place OpenBox, un gestionnaire léger de fenêtres X11. Vous pouvez sauter cette étape, mais sans elle, vous n’auriez pas de barres de titre ou ne pourriez pas redimensionner les fenêtres.

      Enfin, ajoutons le dernier bloc à supervisord.conf, qui lancera l’application principale : 

      ~/thunderbird/supervisord.conf

      ...
      [program:app]
      priority=1
      environment=DISPLAY=:0
      command=/usr/bin/thunderbird
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      Dans ce dernier bloc, vous fixez la priorité à 1 pour s’assurer que Thunderbird se lance après TigerVNC, sinon il rencontrerait une condition de course et ne démarrerait pas au hasard. Nous avons également réglé autorestart=true pour rouvrir automatiquement l’application si elle se ferme par erreur. La variable d’environnement DISPLAY indique à l’application de s’afficher sur le serveur VNC que vous avez configuré précédemment.

      Voici ce à quoi votre supervisord.conf complété ressemblera : 

      ~/thunderbird/supervisord.conf

      [supervisord]
      nodaemon=true
      pidfile=/tmp/supervisord.pid
      logfile=/dev/fd/1
      logfile_maxbytes=0
      
      [program:x11]
      priority=0
      command=/usr/bin/Xtigervnc -desktop "Thunderbird" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      
      [program:easy-novnc]
      priority=0
      command=/usr/local/bin/easy-novnc --addr :8080 --host localhost --port 5900 --no-url-password --novnc-params "resize=remote"
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      
      [program:openbox]
      priority=1
      command=/usr/bin/openbox
      environment=DISPLAY=:0
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      
      [program:app]
      priority=1
      environment=DISPLAY=:0
      command=/usr/bin/thunderbird
      autorestart=true
      stdout_logfile=/dev/fd/1
      stdout_logfile_maxbytes=0
      redirect_stderr=true
      

      Si vous voulez conteneuriser une autre demande, remplacez /usr/bin/thunderbird avec le chemin d’accès à l’exécutable de votre application. Sinon, vous êtes maintenant prêt à configurer le menu principal de votre interface graphique.

      Maintenant que votre gestionnaire de processus est configuré, mettons en place le menu de l’OpenBox. Ce menu nous permet de lancer des applications à l’intérieur du conteneur. Nous inclurons également un terminal et un moniteur de processus pour le débogage, si nécessaire.

      Dans le répertoire de votre candidature, utilisez nano ou votre éditeur de texte préféré pour créer et ouvrir un nouveau fichier appelé menu.xml: 

      • nano ~/thunderbird/menu.xml

      Ajoutez maintenant le code suivant à menu.xml:

      ~/thunderbird/menu.xml

      <?xml version="1.0" encoding="utf-8"?>
      <openbox_menu xmlns="http://openbox.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openbox.org/ file:///usr/share/openbox/menu.xsd">
          <menu id="root-menu" label="Openbox 3">
              <item label="Thunderbird">
                  <action name="Execute">
                      <execute>/usr/bin/thunderbird</execute>
                  </action>
              </item>
              <item label="Terminal">
                  <action name="Execute">
                      <execute>/usr/bin/x-terminal-emulator</execute>
                  </action>
              </item>
              <item label="Htop">
                  <action name="Execute">
                      <execute>/usr/bin/x-terminal-emulator -e htop</execute>
                  </action>
              </item>
          </menu>
      </openbox_menu>
      

      Ce fichier XML contient les éléments de menu qui apparaîtront lorsque vous ferez un clic droit sur le bureau. Chaque élément est constitué d’une étiquette et d’une action.

      Si vous voulez conteneuriser une autre demande, remplacez /usr/bin/thunderbird avec le chemin d’accès à l’exécutable de votre application et modifiez le label de l’article. 

      Étape 3 &mdash ; Créer le Dockerfile

      Maintenant que l’OpenBox est configurée, vous allez créer le Dockerfile, qui relie tout.

      Créez un Dockerfile dans le répertoire de votre conteneur :

      • nano ~/thunderbird/Dockerfile

      Pour commencer, ajoutons un peu de code pour élaborer easy-novnc: 

      ~/thunderbird/Dockerfile

      FROM golang:1.14-buster AS easy-novnc-build
      WORKDIR /src
      RUN go mod init build && 
          go get github.com/geek1011/[email protected] && 
          go build -o /bin/easy-novnc github.com/geek1011/easy-novnc
      

      Dans un premier temps, vous construisez easy-novnc. Cela se fait dans une étape séparée pour des raisons de simplicité et de gain d’espace &mdash ; vous n’avez pas besoin de toute la chaîne d’outils Go dans votre image finale. Notez le @v1.1.0 dans la commande de construction. Cela garantit que le résultat est déterministe, ce qui est important car Docker met en cache le résultat de chaque étape. Si vous n’aviez pas spécifié de version explicite, Docker ferait référence à la dernière version d’easy-novnc au moment où l’image a été construite pour la première fois. En outre, vous voulez vous assurer que vous téléchargez une version spécifique de easy-novnc, au cas où des modifications de rupture seraient apportées à l’interface CLI. 

      Créons maintenant la deuxième étape, qui deviendra l’image finale. Ici, vous utiliserez Debian 10 (buster) comme image de base. Notez que, comme il s’exécute dans un conteneur, il fonctionnera quelle que soit la distribution que vous utilisez sur votre serveur.

      Ensuite, ajoutez le bloc suivant à votre Dockerfile: 

      ~/thunderbird/Dockerfile

      ...
      FROM debian:buster
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends openbox tigervnc-standalone-server supervisor gosu && 
          rm -rf /var/lib/apt/lists && 
          mkdir -p /usr/share/desktop-directories
      

      Dans cette instruction, vous installez Debian 10 comme image de base, puis vous installez le strict minimum requis pour exécuter des applications graphiques dans votre conteneur. Notez que vous exécutez apt-get update dans le cadre de la même instruction, pour éviter les problèmes de mise en cache de Docker. Pour gagner de la place, vous supprimez également les listes de paquets téléchargées par la suite (les paquets mis en cache sont eux-mêmes supprimé par défaut). Vous créez également /usr/share/desktop-directories car certaines applications dépendent du répertoire existant.

      Ajoutons un autre petit bloc de code :

      ~/thunderbird/Dockerfile

      ...
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends lxterminal nano wget openssh-client rsync ca-certificates xdg-utils htop tar xzip gzip bzip2 zip unzip && 
          rm -rf /var/lib/apt/lists
      

      Dans cette instruction, vous installez des utilitaires et des paquets utiles à usage général. Les points suivants présentent un intérêt particulier xdg-utils (qui fournit les commandes de base utilisées par les applications de bureau sous Linux) et ca-certificates (qui installe les certificats racine pour nous permettre d’accéder aux sites HTTPS). 

      Maintenant, nous pouvons ajouter les instructions pour la demande principale :

      ~/thunderbird/Dockerfile

      ...
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends thunderbird && 
          rm -rf /var/lib/apt/lists
      

      Comme auparavant, nous installons ici l’application. Si vous conteneurisez une autre application, vous pouvez remplacer ces commandes par celles nécessaires à l’installation de votre application spécifique. Certaines applications nécessiteront un peu plus de travail pour fonctionner dans Docker. Par exemple, si vous installez une application qui utilise Chrome, Chromium, ou QtWebEngine, vous devrez utiliser l’argument de la ligne de commande --no-sandbox parce qu’il ne sera pas soutenu au sein de Docker. 

      Ensuite, commençons à ajouter les instructions pour ajouter les derniers fichiers dans le conteneur :

      ~/thunderbird/Dockerfile

      ...
      COPY --from=easy-novnc-build /bin/easy-novnc /usr/local/bin/
      COPY menu.xml /etc/xdg/openbox/
      COPY supervisord.conf /etc/
      EXPOSE 8080
      

      Ici, vous ajoutez à l’image les fichiers de configuration que vous avez créés précédemment et vous copiez le binaire easy-novnc de la première étape.

      Le bloc de code suivant crée le répertoire de données et ajoute un utilisateur dédié à votre application. Ceci est important, car certaines applications refusent de s’exécuter en tant que root. Il est également bon de ne pas exécuter les applications en tant que root, même dans un conteneur.

      ~/thunderbird/Dockerfile

      ...
      RUN groupadd --gid 1000 app && 
          useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && 
          mkdir -p /data
      VOLUME /data
      

      Pour assurer la cohérence des UID/GID pour les fichiers, vous fixez explicitement les deux à 1000. Vous montez également un volume sur le répertoire de données pour vous assurer qu’il persiste entre les redémarrages.

      Enfin, ajoutons les instructions pour tout lancer :

      ~/thunderbird/Dockerfile

      ...
      CMD ["sh", "-c", "chown app:app /data /dev/stdout && exec gosu app supervisord"]
      

      En réglant la commande par défaut sur supervisord, le gestionnaire lancera les processus nécessaires à l’exécution de votre application. Dans ce cas, vous utilisez CMD plutôt qu’ENTRYPOINT. Dans la plupart des cas, cela ne ferait pas de différence, mais l’utilisation de CMD est plus adaptée à cette fin, pour plusieurs raisons. Premièrement, supervisord ne prend pas d’arguments qui seraient pertinents pour nous, et si vous fournissez des arguments au conteneur, ils remplacent CMD et sont annexés à ENTRYPOINT.  Deuxièmement, l’utilisation de CMD nous permet de fournir une commande entièrement différente (qui sera exécutée par /bin/sh -c) lors du passage des arguments au conteneur, ce qui rend le débogage plus facile.

      Et enfin, vous devez exécuterchown comme root avant de démarrer supervisord pour éviter les problèmes d’autorisation sur le volume de données et pour permettre aux processus enfant d’ouvrir stdout. Cela signifie également que vous devez utiliser gosu au lieu de l’instruction USER pour changer d’utilisateur. 

      Voici ce à quoi votre Dockerfile complété ressemblera :

      ~/thunderbird/Dockerfile

      FROM golang:1.14-buster AS easy-novnc-build
      WORKDIR /src
      RUN go mod init build && 
          go get github.com/geek1011/[email protected] && 
          go build -o /bin/easy-novnc github.com/geek1011/easy-novnc
      
      FROM debian:buster
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends openbox tigervnc-standalone-server supervisor gosu && 
          rm -rf /var/lib/apt/lists && 
          mkdir -p /usr/share/desktop-directories
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends lxterminal nano wget openssh-client rsync ca-certificates xdg-utils htop tar xzip gzip bzip2 zip unzip && 
          rm -rf /var/lib/apt/lists
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends thunderbird && 
          rm -rf /var/lib/apt/lists
      
      COPY --from=easy-novnc-build /bin/easy-novnc /usr/local/bin/
      COPY menu.xml /etc/xdg/openbox/
      COPY supervisord.conf /etc/
      EXPOSE 8080
      
      RUN groupadd --gid 1000 app && 
          useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && 
          mkdir -p /data
      VOLUME /data
      
      CMD ["sh", "-c", "chown app:app /data /dev/stdout && exec gosu app supervisord"]
      

      Sauvegardez et fermez votre Dockerfile. Nous sommes maintenant prêts à construire et à faire fonctionner notre conteneur, puis à accéder à Thunderbird &mdash, une application GUI.

      Étape 4 &mdash ; Création et utilisation du conteneur

      L’étape suivante consiste à construire votre conteneur et à le mettre en marche au démarrage. Vous mettrez également en place un volume pour préserver les données de l’application entre les redémarrages et les mises à jour.

      Construisez d’abord votre conteneur. Veillez à exécuter ces commandes dans le répertoire ~/thunderbird :

      • docker build -t thunderbird .

      Créez maintenant un nouveau réseau qui sera partagé entre les conteneurs de l’application :

      • docker network create thunderbird-net

      Créez ensuite un volume pour stocker les données de l’application :

      • docker volume create thunderbird-data

      Enfin, lancez-le et réglez-le pour qu’il redémarre automatiquement :

      • docker run --detach --restart=always --volume=thunderbird-data:/data --net=thunderbird-net --name=thunderbird-app thunderbird

      Notez que si vous le souhaitez, vous pouvez remplacer le thunderbird-app après l’option --name par un nom différent. Quel que soit votre choix, votre application est maintenant conteneurisée et en cours d’exécution. Utilisons maintenant le serveur web Caddy pour le sécuriser et nous y connecter à distance.

      Étape 5 &mdash ; Mise en place de Caddy

      Au cours de cette étape, vous configurerez le serveur web Caddy pour fournir une authentification et, éventuellement, un accès à distance aux fichiers via WebDAV. Par souci de simplicité, et pour vous permettre de l’utiliser avec votre proxy inverse existant, vous le ferez fonctionner dans un autre conteneur.

      Créez un nouveau répertoire et déplacez-vous à l’intérieur de celui-ci :

      Créez maintenant un nouveau Dockerfile en utilisant nano ou votre éditeur préféré :

      Ajoutez ensuite les directives suivantes :

      ~/caddy/Dockerfile

      FROM golang:1.14-buster AS caddy-build
      WORKDIR /src
      RUN echo 'module caddy' > go.mod && 
          echo 'require github.com/caddyserver/caddy/v2 v2.0.0' >> go.mod && 
          echo 'require github.com/mholt/caddy-webdav v0.0.0-20200523051447-bc5d19941ac3' >> go.mod
      RUN echo 'package main' > caddy.go && 
          echo 'import caddycmd "github.com/caddyserver/caddy/v2/cmd"' >> caddy.go && 
          echo 'import _ "github.com/caddyserver/caddy/v2/modules/standard"' >> caddy.go && 
          echo 'import _ "github.com/mholt/caddy-webdav"' >> caddy.go && 
          echo 'func main() { caddycmd.Main() }' >> caddy.go
      RUN go build -o /bin/caddy .
      
      FROM debian:buster
      
      RUN apt-get update -y && 
          apt-get install -y --no-install-recommends gosu && 
          rm -rf /var/lib/apt/lists
      
      COPY --from=caddy-build /bin/caddy /usr/local/bin/
      COPY Caddyfile /etc/
      EXPOSE 8080
      
      RUN groupadd --gid 1000 app && 
          useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && 
          mkdir -p /data
      VOLUME /data
      
      WORKDIR /data
      CMD ["sh", "-c", "chown app:app /data && exec gosu app /usr/local/bin/caddy run -adapter caddyfile -config /etc/Caddyfile"]
      

      Ce Dockerfile construit Caddy avec le plugin WebDAV activé, puis le lance sur le port 8080 avec le Caddyfile dans /etc/Caddyfile. Enregistrez et fermez le fichier.

      Ensuite, vous allez configurer le serveur web de Caddy. Créez un fichier nommé Caddyfile dans le répertoire que vous venez de créer :

      Ajoutez maintenant le bloc de code suivant à votre Caddyfile :

      ~/caddy/Caddyfile

      {
          order webdav last
      }
      :8080 {
          log
          root * /data
          reverse_proxy thunderbird-app:8080
      
          handle /files/* {
              uri strip_prefix /files
              file_server browse
          }
          redir /files /files/
      
          handle /webdav/* {
              uri strip_prefix /webdav
              webdav
          }
          redir /webdav /webdav/
      
          basicauth /* {
              {env.APP_USERNAME} {env.APP_PASSWORD_HASH}
          }
      }
      

      Ce Caddyfile est un proxy du répertoire root vers le conteneur thunderbird-app que vous avez créé à l’étape 4 (le Docker le résout en l’IP correcte). Il servira également de navigateur de fichiers en lecture seule sur /files et fera fonctionner un serveur WebDAV sur /webdav que vous pourrez monter localement pour accéder à vos fichiers. Le nom d’utilisateur et le mot de passe sont lus à partir des variables d’environnement APP_USERNAME et APP_PASSWORD_HASH. 

      Maintenant, construisez le conteneur :

      • docker build -t thunderbird-caddy .

      Caddy v.2 vous demande de hacher le mot de passe que vous souhaitez. Exécutez la commande suivante et n’oubliez pas de remplacer mypass avec un mot de passe fort de votre choix : 

      • docker run --rm -it thunderbird-caddy caddy hash-password -plaintext 'mypass'

      Cette commande produira une chaîne de caractères. Copiez ceci dans votre presse-papiers en préparation de l’exécution de la prochaine commande.

      Vous êtes maintenant prêt à faire fonctionner le conteneur. Veillez à remplacer myuser avec un nom d’utilisateur de votre choix, et remplacez mypass-hash par la sortie de la commande que vous avez exécutée à l’étape précédente. Vous pouvez également changer le port (8080 ici) pour accéder à votre serveur sur un port différent : 

      • docker run --detach --restart=always --volume=thunderbird-data:/data --net=thunderbird-net --name=thunderbird-web --env=APP_USERNAME="myuser" --env=APP_PASSWORD_HASH="mypass-hash" --publish=8080:8080 thunderbird-caddy

      Nous sommes maintenant prêts à accéder et à tester notre application.

      Étape 6 &mdash ; Tester et gérer l’application

      Accédez à votre application et assurez-vous qu’elle fonctionne.

      Ouvrez d’abord http://votre_serveur_ip:8080 dans un navigateur web, connectez-vous avec les identifiants que vous avez choisis auparavant, et cliquez sur Connect. 

      Page de connexion NoVNC 

      Vous devriez maintenant être en mesure d’interagir avec l’application, et celle-ci devrait automatiquement se redimensionner pour s’adapter à la fenêtre de votre navigateur.

      Menu principal de Thunderbird

      Si vous faites un clic droit sur le bureau noir, vous devriez voir un menu qui vous permet d’accéder à un terminal. Si vous cliquez avec le bouton du milieu de la souris, vous devriez voir une liste de fenêtres.

      Clic droit sur NoVNC

      Ouvrez maintenant http://votre_serveur_ip:8080/files/ dans un navigateur web. Vous devriez pouvoir accéder à vos fichiers.

      Accès au fichier NoVNC webdav

      En option, vous pouvez essayer de monter http://your_server_ip:8080/webdav/ dans un client WebDAV. Vous devez pouvoir accéder à vos fichiers et les modifier directement. Si vous utilisez l’option de carte lecteur réseau dans l’explorateur Windows, vous devrez soit utiliser un mandataire inverse pour ajouter le HTTPS, ou définir HKLMSYSTEMCurrentControlSetServicesClientWebParametersBasicAuthLevel à DWORD:2. 

      Dans les deux cas, votre application GUI native est maintenant prête à être utilisée à distance.

      Conclusion

      Vous avez maintenant configuré avec succès un conteneur Docker pour Thunderbird et ensuite, à l’aide de Caddy, vous avez configuré l’accès à ce conteneur via un navigateur web. Si jamais vous devez mettre à jour votre application, arrêtez les conteneurs, exécutez docker rm thunderbird-app thunderbird-web, reconstruisez les images, puis relancez les commandes d’exécution du docker à partir des étapes précédentes ci-dessus. Vos données seront toujours préservées puisqu’elles sont stockées dans un volume.

      Si vous voulez en savoir plus sur les commandes de base du Docker, vous pouvez lire ceci tutoriel ou cette fiche d’aide. Pour une utilisation à plus long terme, vous pouvez également envisager d’activer le HTTPS (qui nécessite un domaine) pour une sécurité supplémentaire.

      En outre, si vous déployez plus d’une application, vous pouvez utiliser Docker Compose ou Kubernetes au lieu de démarrer chaque conteneur manuellement. Et n’oubliez pas que ce tutoriel peut servir de base pour exécuter toute autre application Linux sur votre serveur, y compris :

      • Wine, une couche de compatibilité pour l’exécution d’applications Windows sous Linux.
      • GIMP, un éditeur d’images open-source.
      • Cutter, une plateforme de rétro-ingénierie open-source.

      Cette dernière option démontre le grand potentiel de la conteneurisation et de l’accès à distance aux applications GUI. Grâce à cette configuration, vous pouvez désormais utiliser un serveur doté d’une puissance de calcul considérablement plus importante que celle dont vous disposez localement pour faire fonctionner des outils gourmands en ressources comme Cutter.



      Source link