Dockeriser une application Shiny : un conteneur reproductible avec rocker/shiny
Empaquetez votre application, R et chaque dépendance dans une seule image portable qui tourne à l’identique sur n’importe quel serveur.
Conteneurisez une application Shiny avec Docker. Écrivez un Dockerfile sur l’image de base rocker/shiny, ajoutez vos packages en installations binaires rapides avec install2.r, construisez et exécutez le conteneur, figez la version de R pour une image reproductible, durcissez-la pour qu’elle tourne en non-root, et poussez un tag versionné vers un registre.
- Un conteneur fige toute votre application dans une seule image — votre code, R, chaque package et les bibliothèques de l’OS — pour qu’elle tourne à l’identique sur votre ordinateur portable, la machine d’un collègue ou un serveur de production.
rocker/shinyfait le gros du travail. L’image de base maintenue livre R et Shiny Server préinstallés ; votre Dockerfile se contente d’y copier votre application et ses packages.- Ajoutez les packages par la voie rapide avec
install2.r— des binaires précompilés depuis le dépôt intégré à l’image, donc les builds sont rapides et n’ont pas besoin de compilateurs système. - Épinglez le tag de base (
rocker/shiny:4.5.1) pour épingler la version de R — le principal levier de reproductibilité. Ne construisez jamais de la production sur:latest. - The runtime is the judge. Quand le conteneur répond à
http://localhost:3838, vous avez prouvé que l’image fonctionne — c’est exactement cette image que ShinyProxy et Kubernetes déploient.
Introduction
Votre application Shiny tourne sur votre ordinateur portable. Maintenant elle doit tourner sur un serveur — et « installer R, puis ces 30 packages, puis les bonnes bibliothèques système, puis espérer que les versions correspondent » est exactement là où les déploiements cassent. Un conteneur résout cela : il empaquette votre application avec R, chaque package R et les bibliothèques du système d’exploitation dans une seule image (un instantané figé et livrable) qui tourne à l’identique partout. Docker est l’outil qui construit et exécute les images.
C’est la voie de l’auto-hébergement. Si vous voulez seulement une URL gérée sans serveur à faire tourner, déployez plutôt sur shinyapps.io — cela ne demande aucun Dockerfile. Optez pour Docker quand vous voulez un contrôle total : des données privées qui ne peuvent pas quitter votre infrastructure, un serveur précis sur lequel vous déployez, ou une application que vous mettrez plus tard à l’échelle pour de nombreux utilisateurs. L’image que vous construisez ici est aussi l’unité exacte que ShinyProxy (pour servir un conteneur par utilisateur) et Kubernetes (pour mettre à l’échelle sur un cluster) déploient — donc conteneuriser est le socle sur lequel se construit toute voie d’auto-hébergement sérieuse.
Cette leçon prend une application fonctionnelle et la conteneurise de bout en bout : le Dockerfile, l’ajout de vos packages, la construction et l’exécution, la reproductibilité de l’image, et sa publication vers un registre.
Il vous faut trois choses : Docker installé (Docker Desktop sur Mac/Windows, Docker Engine sur Linux) ; une application Shiny fonctionnelle — si vous débutez, construisez d’abord votre première application Shiny ; et cette application enregistrée dans un dossier sous forme de app.R (ou ui.R/server.R). Si vous n’avez pas encore configuré R et Shiny, commencez par l’installation et la configuration.
Les commandes de cette page ne sont pas exécutées ici — construire une image écrit dans votre installation Docker, et une application Shiny a besoin d’un serveur R actif, aucune des deux ne tourne donc dans une page web statique. Copiez n’importe quel bloc dans un terminal (ou un Dockerfile) et exécutez-le sur votre machine. Le vrai test, c’est le conteneur en cours d’exécution : quand votre application se charge à http://localhost:3838, vous avez prouvé que l’image fonctionne — the runtime is the judge.
L’organisation du projet
Placez votre application dans un dossier avec le Dockerfile à côté. C’est tout ce qu’il faut pour commencer :
my-shiny-app/
├── Dockerfile # the build recipe (below)
├── .dockerignore # files to keep OUT of the image
└── app/
└── app.R # your Shiny app
Shiny Server sert les applications depuis /srv/shiny-server/, donc le Dockerfile y copie votre dossier app/. Garder l’application dans son propre sous-dossier rend l’étape de copie propre.
Le Dockerfile, ligne par ligne
Un Dockerfile est une recette en texte brut : chaque ligne est une étape de build. Voici la recette complète et fonctionnelle — elle construit et sert une application Shiny sans aucun package R supplémentaire :
# syntax=docker/dockerfile:1
FROM rocker/shiny:4.5.1
# replace the demo apps with your own
RUN rm -rf /srv/shiny-server/*
COPY app/ /srv/shiny-server/
EXPOSE 3838
USER shiny # rocker/shiny ships a non-root 'shiny' user — run as it
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -fsS http://localhost:3838/ || exit 1
CMD ["/usr/bin/shiny-server"]Lisez-la de haut en bas :
FROM rocker/shiny:4.5.1part de l’imagerocker/shinydu Rocker Project, qui livre R 4.5.1 et Shiny Server préinstallés. Épingler le tag épingle la version de R — le choix de reproductibilité le plus important que vous fassiez. N’utilisez jamais:latesten production ; il change R silencieusement sous vos pieds.RUN rm -rf /srv/shiny-server/*efface les applications de démonstration livrées avec l’image de base, pour qu’il ne reste que votre application.COPY app/ /srv/shiny-server/copie votre dossier localapp/dans la racine des applications de Shiny Server à l’intérieur de l’image.EXPOSE 3838documente que l’application écoute sur le port 3838 (le port par défaut de Shiny Server).USER shinybascule vers l’utilisateur non-rootshinyque l’image de base fournit déjà — un conteneur qui tourne en root est un risque inutile (plus de détails sur le durcissement ci-dessous).HEALTHCHECKindique à Docker comment savoir si l’application est vivante : il interroge l’application toutes les 30 secondes et marque le conteneur comme non sain si elle cesse de répondre. Les orchestrateurs s’en servent pour redémarrer un conteneur mort.CMD ["/usr/bin/shiny-server"]est la commande qui s’exécute au démarrage du conteneur — elle lance Shiny Server, qui sert votre application.
Le piège arm64 / amd64
rocker/shiny est publié pour amd64 (Intel/AMD) uniquement — il n’y a pas de build arm64. Sur une machine Apple Silicon ou une autre machine arm64, un simple docker build échoue avec no match for platform in manifest: not found. Construisez pour amd64 explicitement :
docker build --platform=linux/amd64 -t my-shiny-app .C’est d’ailleurs généralement ce que vous voulez — les serveurs de production sont massivement en amd64, donc linux/amd64 est la bonne cible. (Vous pouvez à la place ajouter --platform=linux/amd64 sur la ligne FROM pour inscrire ce choix dans le Dockerfile.)
Ajoutez les packages de votre application
Votre application a presque certainement besoin de packages au-delà de R de base. Installez-les avant de copier l’application, pour que Docker mette en cache cette couche coûteuse et ne la reconstruise que lorsque votre liste de packages change :
FROM rocker/shiny:4.5.1
# add the packages your app needs, as fast binary installs
RUN install2.r --error --skipinstalled ggplot2 dplyr
RUN rm -rf /srv/shiny-server/*
COPY app/ /srv/shiny-server/
EXPOSE 3838
USER shiny
CMD ["/usr/bin/shiny-server"]install2.r (du package littler, préinstallé dans chaque image Rocker) installe des packages binaires précompilés depuis le dépôt Posit Public Package Manager auquel l’image est épinglée. Les binaires signifient aucune compilation et aucune chasse aux bibliothèques système manquantes — les deux plus grandes sources de builds Docker lents et défaillants. Les options comptent :
--errorfait échouer tout le build si un package ne peut pas s’installer, pour qu’une image cassée ne soit jamais livrée.--skipinstalledsaute les packages déjà présents dans l’image de base (Shiny y est déjà).
Listez les packages que votre application charge avec library(). C’est tout — aucun appel install.packages() à écrire, aucune URL de dépôt à retenir.
Construisez, exécutez et vérifiez
Trois commandes vous mènent du Dockerfile à une application en ligne. D’abord, construisez (build) l’image (l’option -t la tague avec un nom) :
# build (on arm64/Apple Silicon add --platform=linux/amd64)
docker build -t my-shiny-app .Puis exécutez-la (run), en mappant le port 3838 du conteneur vers le même port sur votre machine :
docker run --rm -p 3838:3838 my-shiny-app--rm nettoie le conteneur quand vous l’arrêtez ; -p 3838:3838 connecte votre localhost:3838 à l’application à l’intérieur. Maintenant, ouvrez http://localhost:3838 dans un navigateur — votre application est en ligne. Appuyez sur Ctrl-C dans le terminal pour l’arrêter.
Cette application en cours d’exécution est la preuve. Une analyse statique ne peut pas vous dire que l’image est correcte ; un conteneur qui répond à localhost:3838, si. C’est le moment « the runtime is the judge » — si elle se charge et fonctionne ici, elle se chargera et fonctionnera sur le serveur.
Rendez l’image reproductible
La reproductibilité signifie que l’image que vous construirez le mois prochain est la même que celle que vous construisez aujourd’hui. Deux leviers font l’essentiel du travail, et vous les avez déjà tirés tous les deux :
- Épinglez la version de R en épinglant le tag de base (
rocker/shiny:4.5.1). Le tag est la version de R. - Installez des binaires avec
install2.r, qui tire du dépôt du gestionnaire de packages intégré à cette image taguée.
Pour des versions de packages stables au bit près, ajoutez un instantané daté du dépôt Posit Package Manager — chaque build résout alors exactement les mêmes versions figées à cette date :
# freeze package versions to a specific date (rocker noble = Ubuntu 24.04)
RUN install2.r --error --repos https://p3m.dev/cran/__linux__/noble/2026-07-01 ggplot2 dplyrrenv peut fonctionner dans Docker, mais un simple renv::restore() compile les packages depuis les sources — et cela échoue sur des dépendances de build système manquantes (par exemple, installer fs depuis les sources nécessite libuv). Pointez renv vers un dépôt binaire pour le nom de code Ubuntu de l’image avant de restaurer :
ENV RENV_CONFIG_REPOS_OVERRIDE=https://p3m.dev/cran/__linux__/noble/latest
COPY renv.lock renv.lock
RUN R -e "renv::restore()"Honnêtement : renv dans Docker n’en vaut la peine que si vous verrouillez déjà avec renv. Si ce n’est pas le cas, install2.r + un tag épinglé (+ un instantané daté) est plus simple et tout aussi reproductible. Utilisez ce à quoi votre projet s’engage déjà.
Livrez-la vers un registre
Pour exécuter l’image sur une autre machine, poussez-la vers un registre — un serveur qui stocke et distribue les images (Docker Hub, GitHub Container Registry, ou un registre privé). Taguez l’image avec une version, puis poussez :
# tag with a version and your registry namespace
docker tag my-shiny-app:latest ghcr.io/your-org/my-shiny-app:1.2.0
# push it
docker push ghcr.io/your-org/my-shiny-app:1.2.0Déployez toujours un tag de version spécifique (1.2.0), jamais :latest — un serveur qui tire :latest peut recevoir silencieusement une image différente de celle que vous avez testée. Un fichier .dockerignore (comme .gitignore, mais pour le build) garde les déchets hors de l’image pour qu’elle reste légère :
.git
.Rproj.user
*.log
.DS_Store
renv/library/
Durcissez-la
Deux habitudes couvrent l’essentiel de ce dont une petite image de production a besoin :
- Tournez en non-root — déjà fait avec
USER shinydans la recette. Si quelqu’un s’échappe de l’application, c’est un utilisateur non privilégié, pas root. - Abandonnez les privilèges à l’exécution. Démarrez le conteneur sans aucune capacité Linux supplémentaire ni moyen d’en acquérir de nouvelles :
docker run --cap-drop=ALL --security-opt=no-new-privileges -p 3838:3838 my-shiny-app(Un système de fichiers racine entièrement en lecture seule est plus strict encore, mais Shiny Server écrit dans /var/log/shiny-server et /tmp, il a donc besoin de montages --tmpfs correspondants — la leçon de sécurité dédiée couvre cela.) - Gardez l’image minimale et scannez-la. Une image plus petite a moins de packages susceptibles de mal tourner. Scannez-la à la recherche de vulnérabilités connues — une CVE (Common Vulnerabilities and Exposures) est une faille de sécurité cataloguée publiquement — avec Docker Scout ou Trivy :
docker scout cves my-shiny-app # or: trivy image my-shiny-appReconstruisez périodiquement sur le dernier tag de base pour récupérer les correctifs de sécurité. Câblez ce build-et-scan dans votre pipeline CI/CD (intégration continue / livraison continue) et chaque poussée est scannée automatiquement. (Si votre application compile des packages depuis les sources, un build multi-étapes — compiler dans une étape, ne copier que le résultat dans une étape d’exécution légère — allège l’image finale ; avec des packages binaires install2.r, vous en avez rarement besoin.)
Où va l’image ensuite
L’image est l’entrée des deux étapes suivantes d’une pile de production. Pour servir un conteneur séparé par utilisateur — avec authentification et isolation par session — ShinyProxy lance votre image à la demande. Pour mettre à l’échelle sur de nombreuses machines, un orchestrateur comme Kubernetes ou Docker Swarm planifie des réplicas de la même image et répartit la charge entre elles. Les deux consomment exactement l’image que vous venez de construire ; rien dans votre Dockerfile ne change. Et si le surcoût de l’auto-hébergement n’en vaut pas la peine pour votre application, shinyapps.io vous donne une URL gérée sans aucun Dockerfile.
Problèmes fréquents
no match for platform in manifest: not found sur un Mac M1/M2/M3. rocker/shiny est amd64 uniquement, donc un build arm64 ne trouve pas d’image correspondante. Construisez pour amd64 explicitement : docker build --platform=linux/amd64 -t my-shiny-app . — ce qui est de toute façon la bonne cible de production.
Un package échoue à se construire parce qu’une bibliothèque système est manquante. Certains packages ont besoin de bibliothèques OS au moment du build ou de l’exécution (par exemple sf a besoin de GDAL). Les binaires install2.r embarquent généralement ce dont ils ont besoin, mais si l’un échoue tout de même, installez d’abord la bibliothèque système — RUN apt-get update && apt-get install -y libgdal-dev && rm -rf /var/lib/apt/lists/* — ou partez d’une variante Rocker qui l’inclut déjà (comme rocker/geospatial).
L’application affiche un index de Shiny Server ou une 404, pas votre application. Vos fichiers d’application ne sont pas là où Shiny Server regarde. Confirmez que app.R a bien atterri directement dans /srv/shiny-server/ (ou dans un sous-dossier servi à /subfolder/). Vérifiez avec docker run --rm my-shiny-app ls /srv/shiny-server — vous devriez voir votre app.R, pas les applications de démonstration. La ligne rm -rf /srv/shiny-server/* efface les démos pour que seule votre application soit servie.
Questions fréquentes
Écrivez un Dockerfile qui commence par FROM rocker/shiny:4.5.1, efface les applications de démonstration (RUN rm -rf /srv/shiny-server/*), y copie votre application (COPY app/ /srv/shiny-server/) et lance Shiny Server (CMD ["/usr/bin/shiny-server"]). Ajoutez les packages dont votre application a besoin avec install2.r. Puis docker build -t my-shiny-app . et docker run --rm -p 3838:3838 my-shiny-app, et ouvrez http://localhost:3838.
Utilisez rocker/shiny, l’image maintenue du Rocker Project — elle livre R et Shiny Server préinstallés. Épinglez le tag à une version (rocker/shiny:4.5.1) pour que la version de R soit fixée ; ce tag est votre principal levier de reproductibilité. Évitez :latest en production.
rocker/shiny est publié pour amd64 uniquement, donc un simple build sur une machine Apple Silicon (arm64) échoue avec no match for platform in manifest: not found. Construisez pour amd64 explicitement avec docker build --platform=linux/amd64 -t my-shiny-app . — les serveurs de production sont en amd64, c’est donc la bonne cible.
Ajoutez une ligne avant de copier l’application : RUN install2.r --error --skipinstalled ggplot2 dplyr, en listant chaque package que votre application charge. install2.r installe des binaires précompilés depuis le dépôt Posit Package Manager intégré à l’image Rocker — rapide, aucune compilation, aucune bibliothèque système manquante. --error fait échouer le build sur un package défectueux ; --skipinstalled saute ceux déjà présents.
Pour la reproductibilité, épinglez le tag de base (rocker/shiny:4.5.1) pour fixer la version de R et installez des binaires avec install2.r ; ajoutez un dépôt instantané P3M daté (.../noble/2026-07-01) pour figer les versions de packages. Pour une image plus légère, n’ajoutez que les packages que vous utilisez réellement, ajoutez un .dockerignore pour tenir à l’écart les résidus de sources, et scannez le résultat avec Docker Scout ou Trivy.
Testez vos connaissances
Vous avez une application fonctionnelle dans app/app.R qui appelle library(shiny) et library(ggplot2). Écrivez un Dockerfile complet qui construit une image reproductible tournant en utilisateur non-root, puis donnez les deux commandes pour la construire et l’exécuter. (Supposez que vous êtes sur une machine amd64.)
Partez FROM un tag rocker/shiny épinglé. shiny est déjà dans la base, vous n’avez donc qu’à installer ggplot2 — utilisez install2.r. Effacez les applications de démonstration, copiez votre dossier app/ dans /srv/shiny-server/, basculez vers l’utilisateur shiny, et définissez le CMD. Construisez avec docker build -t ... . et exécutez avec docker run --rm -p 3838:3838 ....
# Dockerfile
FROM rocker/shiny:4.5.1
RUN install2.r --error --skipinstalled ggplot2
RUN rm -rf /srv/shiny-server/*
COPY app/ /srv/shiny-server/
EXPOSE 3838
USER shiny
CMD ["/usr/bin/shiny-server"]# build, then run
docker build -t my-ggplot-app .
docker run --rm -p 3838:3838 my-ggplot-appLe tag épinglé rocker/shiny:4.5.1 fixe la version de R ; install2.r ajoute ggplot2 comme binaire rapide (Shiny est déjà présent, donc --skipinstalled le sauterait) ; USER shiny tourne en utilisateur non-root que l’image de base fournit. Ouvrez http://localhost:3838 pour confirmer que ça fonctionne — l’application en cours d’exécution est la preuve.
Votre Dockerfile utilise FROM rocker/shiny:latest. Pourquoi est-ce un problème pour un déploiement en production ?
A. Les images :latest sont toujours plus grandes que les images épinglées.
B. :latest peut changer silencieusement la version de R entre deux builds, donc une image qui fonctionnait hier peut casser aujourd’hui — sans rien de changé dans votre Dockerfile.
C. rocker/shiny ne publie pas de tag :latest.
D. :latest désactive le HEALTHCHECK.
B. Le tag est votre seul levier sur la version de R. :latest suit ce que les mainteneurs de Rocker ont poussé le plus récemment, donc deux builds espacés de quelques semaines peuvent livrer des versions de R différentes et des résolutions de packages différentes — un piège de reproductibilité où le même Dockerfile produit des images différentes. Épinglez une version spécifique (rocker/shiny:4.5.1) pour tout ce qui part en production. A n’a aucun rapport avec le tag ; C est faux (:latest existe — il est juste risqué de s’y fier) ; D est inventé.
Conclusion
Conteneuriser une application Shiny est une courte recette : partez FROM rocker/shiny avec un tag épinglé, ajoutez vos packages avec install2.r, copiez l’application dans /srv/shiny-server/, et lancez Shiny Server en utilisateur non-root shiny. Construisez-la, exécutez-la, et ouvrez http://localhost:3838 — le conteneur en ligne est la preuve. Épinglez le tag et installez des binaires pour la reproductibilité, taguez avec une version et poussez vers un registre pour la livrer, et scannez l’image avant qu’elle ne sorte. Cette même image est exactement ce que ShinyProxy et Kubernetes déploient ensuite.
Leçons connexes
- Construisez et hébergez l’application : votre première application Shiny vous donne le
app.Rà conteneuriser, et l’installation et la configuration prépare R et Shiny en local. Vous préférez une URL gérée sans Dockerfile ? Déployez sur shinyapps.io est l’alternative hébergée. - Allez plus loin : Applications web Shiny — le cursus Shiny complet. · Science computationnelle et IA — le pilier.
Prouvez que vous savez le faire. Maîtrisez toute la série Shiny en production — suivez votre parcours, construisez des projets et obtenez un certificat.
Passez à Pro — Prova illimité sur vos propres données et un certificat vérifiable qui atteste la compétence.
dès 15 $/mois facturé annuellement
✓ Vous êtes Pro — continuez. The runtime is the judge.
Réutilisation
Citation
@online{2026,
author = {},
title = {Dockeriser une application Shiny : un conteneur reproductible
avec rocker/shiny},
date = {2026-07-16},
url = {https://www.datanovia.com/learn/programming/shiny/production/docker-containerization},
langid = {fr}
}