Application Shiny en production avec ShinyProxy, Docker et Debian

Application Shiny en production avec ShinyProxy, Docker et Debian

shinyproxy-docker-shiny

Vous avez fait de belles applications Shiny, en suivant nos conseils de mise en package de Shiny par exemple, et vous souhaitez les mettre en production, en auto-hébergement, pour que d’autres puissent en profiter, sans limitations, sur Internet ou sur un serveur interne de votre entreprise ? ShinyProxy est fait pour vous !

ShinyProxy v2.0 est sorti récemment. Quelle belle occasion pour vous parler de sa mise en oeuvre !
Un intérêt majeur de ShinyProxy est la possibilité de créer un conteneur Docker indépendant pour chaque utilisateur qui se connecte à votre application Shiny. Cela permet de passer outre les limitations de nombre d’utilisateurs de ShinyServer. Ça vous intéresse ? Suivez la procédure d’installation…

Installation de ShinyProxy

Pour notre installation, nous avons choisi d’utiliser un serveur Debian Jessie. Nous vous laissons faire les ajustements de code nécessaires pour d’autres distributions Linux. (Par exemple, pour Ubuntu, remplacez ‘debian’ par ‘ubuntu’ dans les codes adéquats). De plus, il existe deux façons de déployer ShinyProxy, soit en utilisant JAVA, soit en utilisant un conteneur docker. Vous pourrez choisir soit l’une soit l’autre à la suite de l’article mais il faudra dans les deux cas installer docker sur votre serveur!

ShinyProxy et JAVA

Première étape : installer JAVA

ShinyProxy est un logiciel qui fonctionne avec JAVA, il faut donc vérifier s’il est installé et si oui, quelle version. Dans votre terminal, entrez la commande :

java -version

Si vous recevez un message de ce genre :

openjdk version "1.8.0_xxx"

Alors JAVA 8 est déjà installé sur votre serveur. Dans le cas contraire, vous pouvez installer soit (1) la version libre :

sudo apt install default-jre default-jdk

soit (2) la version java8 d’Oracle avec le PPA de webupd8team :

echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main" | \
  sudo tee /etc/apt/sources.list.d/webupd8team-java.list
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main" | \
  sudo tee -a /etc/apt/sources.list.d/webupd8team-java.list
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
sudo apt-get install oracle-java8-installer

On verifie si l’installation a bien fonctionné :

java -version
openjdk version "1.8.0_xxx"

Parfait, on peut alors continuer notre installation.

Deuxième étape : Installer Docker

Comme expliqué plus haut, ShinyProxy permet de lancer un conteneur Docker de notre application Shiny. Nous allons donc installer Docker CE sur notre serveur.

Il y a besoin de quelques dépendances. Mieux vaut aussi installer la dernière version de Docker CE en utilisant les serveurs Docker comme dépôt tiers.

Dans votre terminal :

sudo apt-get install \
     apt-transport-https \
     ca-certificates \
     curl \
     gnupg2 \
     software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"

Il suffit ensuite de remettre à jour le serveur puis d’installer Docker :

sudo apt-get install docker-ce

Pour savoir si tout s’est bien passé, un petit test pour demander à Docker de nous dire bonjour :

docker run hello-world

Si vous obtenez un message comme celui-ci :

Alors Docker est installé.

Une dernière petite modification…
Pour que ShinyProxy puisse fonctionner, il faut modifier le fichier de Docker /lib/systemd/system/docker.service et relancer Docker (utilisez votre éditeur de texte préféré):

sudo nano /lib/systemd/system/docker.service

Modifiez la ligne avec ‘ExecStart’

ExecStart=/usr/bin/dockerd -H fd:// -D -H tcp://127.0.0.1:2375

Puis relancez Docker

sudo systemctl daemon-reload
sudo systemctl restart docker

Troisième étape : Installer ShinyProxy

Il est temps de revenir à ce qui nous intéresse vraiment, l’installation de ShinyProxy pour déployer nos applications Shiny !

Dans un premier temps, vous devez cloner le dépôt GitHub du logiciel ShinyProxy (vous pouvez aussi télécharger le .zip depuis github) :

git clone https://github.com/openanalytics/ShinyProxy.git

On retrouve alors un dossier “ShinyProxy”. On entre dans le dossier et on installe ShinyProxy. Vous aurez peut-être besoin d’installer “maven” :

cd ShinyProxy/
sudo apt install maven
mvn -U clean install

On peut ensuite tester si les exemples fonctionnent. Pour cela, il faut le template de ShinyProxy et les images Docker des applications Shiny de la démo.

mkdir app-shiny
cd app-shiny/
git clone https://github.com/openanalytics/ShinyProxy-template.git
cd ShinyProxy-template/
docker build -t openanalytics/ShinyProxy-template .

Puis, il faut lancer ShinyProxy : Il faut remonter dans l’arborescence pour retrouver le dossier ‘ShinyProxy/target’.
Modifiez cette commande avec la version de ShinyProxy que vous avez.

cd ShinyProxy/target/
java -jar ShinyProxy-2.0.2.jar

Rendez-vous sur https://localhost:8080. Vous devriez voir la page suivante:

Pour pouvoir personnaliser son ShinyProxy (déployer ses applications, changer la page d’accueil de ShinyProxy), il faut modifier le fichier application.yml et les différents .html contenus dans les différents sous-dossiers de shinproxy/. Par exemple, nous pouvons modifier le fichier de configuration application.yml (ce fichier permet de définir les applications à déployer et autres configurations de ShinyProxy) :

cd ../src/main/ressources/
nano application.yml

Pour enlever une application démo par exemple, il suffit de supprimer les lignes suivantes :

  - id: 06_tabsets
    container-cmd: ["R", "-e", "ShinyProxy::run_06_tabsets()"]
    container-image: openanalytics/ShinyProxy-demo
    container-network: sp-example-net

Vous devez ensuite mettre à jour en retournant sur ShinyProxy/ pour recompiler notre fichier .jar:

cd ../../../
mvn -U clean install

Relancer notre .jar:

cd target/
java -jar ShinyProxy-2.0.2.jar

Mais tout ceci prend beaucoup de temps. À chaque changement il faut recompiler, relancer etc… Les aller-retours sont donc fréquents et nous font perdre du temps. De plus, ici, il ne tourne pas en tâche de fond, le terminal doit rester ouvert (bien que vous puissiez utiliser nohup). Bref, plein d’arguments pour utiliser la version “ShinyProxy en conteneur”.

ShinyProxy en conteneur Docker

N’oubliez pas d’installer docker aussi pour suivre cette partie (cf. Deuxième étape : Installer Docker) !

Pour nous faciliter la vie, il exite des templates de ShinyProxy facilement déployable avec Docker. Vous trouverez un exemple ici!

Dans un premier temps, il faut cloner le dépôt GitHub :

mkdir ShinyProxy-docker
cd ShinyProxy-docker/
git clone https://github.com/openanalytics/ShinyProxy-config-examples.git

On se retrouve alors avec quatre dossiers. Pour cet exemple, nous allons utiliser le dossier commençant par 02. Il contient deux fichiers importants : (1) le fichier application.yml qui permet la configuration de notre ShinyProxy et (2) le dockerfile, qui permet de monter l’image de ShinyProxy.

Application.yml

Nous allons détailler les lignes de codes importantes de ce fichier. Nous allons aussi pouvoir évoquer les différences entre les versions 1.1 et 2.0 de ShinyProxy car l’écriture du .yml a changé.

Les changements entre les deux versions se trouvent sur la partie dédiée aux applications Shiny. docker est remplacé par container, name par id et groups par access-groups.
Ainsi dans la version ShinyProxy 1.1, on avait :

  apps:
  - name: 01_hello
    display-name: Hello Application
    description: Application which demonstrates the basics of a Shiny app
    docker-cmd: ["R", "-e", "ShinyProxy::run_01_hello()"]
    docker-image: openanalytics/ShinyProxy-demo
    groups: [scientists, mathematicians]
    

Et dans la version 2.0, nous avons :

  specs:
  - id: 01_hello
    display-name: Hello Application
    description: Application which demonstrates the basics of a Shiny app
    container-cmd: ["R", "-e", "ShinyProxy::run_01_hello()"]
    container-image: openanalytics/ShinyProxy-demo
    container-network: sp-example-net

Voici l’exemple du .yml proposé dans le dossier 02 que nous avons téléchargé tout à l’heure :

proxy:  
  port: 8080
  authentication: simple
  admin-groups: admins
  users:
  - name: jack
    password: password
    groups: admins
  - name: jeff
    password: password
  docker:
      internal-networking: true
  specs:
  - id: 01_hello
    display-name: Hello Application
    description: Application which demonstrates the basics of a Shiny app
    container-cmd: ["R", "-e", "ShinyProxy::run_01_hello()"]
    container-image: openanalytics/ShinyProxy-demo
    container-network: sp-example-net
  - id: 06_tabsets
    container-cmd: ["R", "-e", "ShinyProxy::run_06_tabsets()"]
    container-image: openanalytics/ShinyProxy-demo
    container-network: sp-example-net
logging:
  file:
    ShinyProxy.log

Dans ce fichier, port nous indique que le conteneur va se lancer sur le port 8080, authentication nous donne le type d’identification choisi, dans notre cas c’est “simple”. Autrement dit, on crée des users, ce qui peut être long (il en existe bien d’autres). On retrouve ensuite la partie specs pour les différentes applications Shiny.

Petit focus sur des options interéssantes :

  • heartbeat-timeout: 60000 permet de configurer combien de temps (en millisecondes) le conteneur reste en activité s’il n’est pas utilisé. Après quoi, il est stoppé.
  • hide-navbar : true permet de cacher la barre de navigation.

Il en existe bien d’autres que vous pouvez retrouver ici.

Le Dockerfile

Le Dockerfile permet de construire notre image Docker en fonction de ce qui nous intéresse. Dans le dossier 02, il permet de changer directement le .yml mais on pourrait vouloir changer la page d’accueil par exemple (dossier 04 pour les plus curieux).

La mise en place de ShinyProxy

Il est temps maintenant de pratiquer.

Dans un premier temps, il faut créer un réseau pour que ShinyProxy puisse communiquer avec les conteneurs des Shiny app. Nommons ce réseau sp-example-net:

sudo docker network create sp-example-net

Ensuite, il faut créer notre image ShinyProxy: Il faut être sûr d’être à l’intérieur du bon dossier (dans 02-containerized-docker-engine)!

cd 02-containerized-docker-engine
docker build -t mon_ShinyProxy .

Pour finir, mettons notre conteneur en service :

sudo docker run -d -v /var/run/docker.sock:/var/run/docker.sock --net sp-example-net -p 8080:8080 mon_ShinyProxy

On gagne beaucoup de temps par rapport à la version hors-Docker. En deux lignes de commande, on peut relancer son ShinyProxy si on a fait des modifications du .yml.

Et il existe bien d’autres possibilités avec ShinyProxy et Docker.

Voilà, vous avez toutes les informations pour mettre en production votre application Shiny ! N’oubliez pas de transformez votre application en package! Si ce n’est pas le cas, on vous explique comment mettre son application Shiny au format package. Et si vous ne vous en sortez pas, vous pouvez toujours nous demander !