Loupe

Docker : Optimisation d'une SPA React aspnetcore avec Visual Studio

Dockeriser une application SPA

Avec les récentes versions de Visual Studio (notamment la dernière version 2019), il est de plus en plus facile de dockeriser une application aspnetcore. L’EDI est maintenant capable de créer automatiquement le fichier Dockerfile, permettant de démarrer un conteneur en quelques minutes, sans même avoir de connaissances poussées de Docker !

Cependant, le fichier généré ne contient que le nécessaire pour générer une application dotnet, mais rien concernant la génération de SPA React (ou n’importe quel autre framework de SPA), comme on peut le constater en regarder les issues Github #5417 et #5450.

En attendant d’avoir une solution plus générique, nous pouvons toujours nous approprier le contenu du Dockerfile, ajouter les outils nécessaires pour générer notre SPA React, et optimiser sa génération.

Voyons ça avec un exemple pratique !

Créer une application aspnetcore React

Cette première partie est super simple, il faut bien entendu s’assurer d’avoir le sdk dotnet installé (en utilisant la ligne de commande Chocolatey choco install dotnetcore-sdk par exemple)

Note : La dernière version du sdk dotnet ne fonctionne pas avec Visual Studio 2017. Dans ce cas, préférez l’utilisation de la version 2.2.107 du sdk.

Lancez ensuite la commande dotnet new react, et testez votre nouvelle application aspnetcore React avec la commande dotnet run.

Dockerization de l’application aspnetcore React avec Visual Studio 2019

Ouvrez le nouveau projet fraîchement créé avec Visual Studio 2019, puis effectuez un click droit sur le fichier .csproj et sélectionnez Add > Docker Support.

01-add-docker-support-to-aspnetcore-react-project.png.png

Sélectionnez ensuite Linux comme type de conteneur.

01b-linux-container.PNG.png

Visual Studio devrait ajouter au projet quelques propriétés MSBuild, quelques launch-settings ainsi qu’un fichier .dockerignore et un Dockerfile.

Parfait ! Essayons maintenant de générer une image depuis notre fichier Dockerfile en exécutant la commande docker build -t docker-aspnetcore-react .

02-docker-react-aspnetcore-npm-not-found.png

Oh non ! La ligne de commande npm n’a pas été reconnue…

Voyons voir comment fixer ce problème !

Ajouter NodeJS au Dockerfile pour générer la SPA React

Le problème est simplement lié au fait que NodeJS ne soit pas installé à l’intérieur de notre conteneur de Build. Du coup npm install ainsi que npm build ne peuvent pas être exécutées pour générer les fichiers de notre SPA React.

Pour cela, nous avons besoin de rajouter les lignes de commande à notre Dockerfile afin d'installer NodeJS dans notre conteneur :

RUN apt-get install --yes curl
RUN curl --silent --location https://deb.nodesource.com/setup_10.x | bash -
RUN apt-get install --yes nodejs

Ces 3 lignes sont le minimum requis pour installer NodeJS (version 10 dans cet exemple). Cela devrait nous permettre d’exécuter les lignes de commande npm.

Mais puisque nous sommes en train de modifier le fichier Dockerfile, profitons-en pour y ajouter quelques petites optimisations.

Optimisation pour un Docker d’une SPA React

La première optimisation est plutôt simple :

Plutôt que de copier l’intégralité des node_modules à l’intérieur du conteneur, ignorons cette copie, et laissons-les être récupérés automatiquement depuis le cache !

Pour ignorer les fichiers node_modules, il suffit juste d’ajouter au ficher .dockerignore cette ligne :

**/node_modules

Cela devrait faire le travail, et éviter la copie de plusieurs milliers de fichiers pesants plusieurs mégaoctets ! C’est une bonne première étape :)

Pour la seconde optimisation, il est nécessaire de comprendre une petite particularité concernant la génération d’image Docker :
Les images sont générées en lisant le fichier Dockerfile ligne par ligne et, plus important, si aucune modification n’a été détectée pour une étape donnée depuis la dernière génération de l’image, cette ligne est ignorée, et le contenu est récupéré depuis le cache (en à peine quelques millisecondes).

La règle est donc de placer les étapes qui changent rarement le plus tôt possible dans le fichier Dockerfile, et de conserver les étapes mouvantes plutôt à la fin (telle que la copie du code source).

Par exemple, on peut trouver ce genre d’optimisation déjà présente dans le fichier Dockerfile, pour la génération de l’application aspnetcore :

  • Le fichier .csproj est d’abord copié dans le conteneur, puis un dotnet restore est exécuté, permettant la récupération des dépendances (qui ne sont pas sensées changer régulièrement). Quelques étapes plus tard, le code source en entier est ensuite copié (code source généralement légèrement différent à chaque commit), puis la build s’effectue.

Reproduisions la même chose pour notre projet NodeJS :
Commençons par copier les fichiers package.json et package-lock.json, puis exécutons npm installpour récupérer les packages, et pour finir il ne reste plus qu’à builder l’application ! Pour cela il faut ajouter au fichier Dockerfile :

COPY ["ClientApp/package.json", "ClientApp/"]
COPY ["ClientApp/package-lock.json", "ClientApp/"]
WORKDIR /src/ClientApp
RUN npm install
 
# Do not forget to change the current working directory to /src before copying all source code
WORKDIR /src

Parfait ! Essayons de builder notre image via docker build -t docker-aspnetcore-react .

03-docker-react-aspnetcore-successfully-built.png

Victoire ! Ça fonctionne !

Pour aller plus loin, nous pourrions voir comment exécuter nos tests dotnet et javascript depuis Docker et collecter leurs résultats, ou encore comment ajouter le support du https depuis notre application aspnetcore dans Docker, mais ce sont des sujets pour de futurs articles !

Que le code soit avec vous !

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus