Déploiement d’un projet Web API .NET Core 3.1 avec Azure Kubernetes Services (AKS)

Nous avons eu l’occasion de travailler à deux reprises avec Kubernetes.

Deux univers bien distinct : Windows et Linux

Ce qu’il faut savoir, c’est que Kubernetes ne fonctionne pas sous Windows dans son plus simple appareil, il faut donc utiliser Linux pour pouvoir le découvrir et pour l’apprendre concrètement.

Si vous voulez l’utiliser sous Windows, il vous faudra utiliser des services externes type AKS. Néanmoins, pour ma part, je trouve que la compréhension d’un outil via ce genre de plateforme est assez biaisé, car trop « magique”. Cela demande une certaines rigueur,une curiosité et un intérêt différent que si vous le faisiez directement sous Linux.

Prérequis pour ce tutoriel

  • Visual Studio 2019 (ou Visual Studio Code)
  • Internet (pour accéder au portail Azure)
  • Powershell
  • Helm
  • Chocolatey
  • Docker
  • Azure-CLI

Création d’une Web API .NET Core 3.1 avec un container Docker sous Linux

Aujourd’hui, nous allons voir ensemble comment créer une Web API sous .NET Core 3.1 et la déployer sous Azure.

Ouvrez votre Visual Studio et créer un nouveau projet ASP .NET Core Application.

Choisissez ensuite API (faites attention à bien avoir sélectionné .NET Core ainsi que la version 3.1) puis dans le panneau de configuration à droite dans la partie “Advanced” de cocher “Enable Docker Support” et de choisir Linux.

1_HIycDu3ImbMFl2B6aDqQbA.png

Choix de la création de projet via Visual Studio et support Docker avec des containers Linux.

L’API par défaut que crée Microsoft, s’appelle WeatherForecast, et dans notre cas nous avons choisis de nommer notre projet WeatherForecastLinux (pour les personnes manquant d’inspiration pour le nommage, c’est cadeau…).

On va donc constater qu’un fichier Dockerfile est présent. Si vous pratiquez Docker ou que vous avez quelques bases dessus vous connaissez donc son utilité. Pour expliquer pourquoi il est présent, vous vous doutez fortement que c’est dû au fait qu’on ait coché la case de support de Docker lors de la création du projet.

Pour les personnes ne sachant pas ce qu’est un Dockerfile, voici une définition succincte : c’est un fichier texte contenant des instructions sur la façon de construire une image Docker.

Voilà à quoi ressemble notre Dockerfile auto-généré :

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY [“WeatherForecastLinux.csproj”, “”]
RUN dotnet restore “./WeatherForecastLinux.csproj”
COPY . .
WORKDIR “/src/.”
RUN dotnet build “WeatherForecastLinux.csproj” -c Release -o /app/build

FROM build AS publish
RUN dotnet publish “WeatherForecastLinux.csproj” -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY — from=publish /app/publish .
ENTRYPOINT [“dotnet”, “WeatherForecastLinux.dll”]

Si vous souhaitez vérifier que votre application se lance correctement, je vous suggère de cliquer sur :

1_FzBBfH9h-p7ucjzNtQugBw.png

Le fait de cliquer sur Docker, va permettre de build et de run le Dockerfile et donc de créer l’image Docker.

Nous allons maintenant ouvrir une fenêtre PowerShell :

  • Soit vous l’ouvrez directement dans le dossier de votre projet
  • Soit vous vous placez au bon endroit pour être au niveau de votre Dockerfile

Le build et le run précédent vous on créée une image, pour vérifier le nom de celui-ci vous pouvez directement taper la commande :

docker ps -a

Ou

docker images
Picture1.png

Dans notre cas, l’image qui nous intéresse est : weatherforecastlinux

 

Maintenant que toutes les fondations sont posées, nous pouvons maintenant passer au déploiement.

Azure Kubernetes Service (AKS)

Tout d’abord, assurez-vous d’avoir accès au Portail Azure, si ce n’est pas le cas créer vous un compte via une adresse Microsoft, et utiliser les 150€ gratuit fournit de base par Microsoft (si vous êtes vigilant dans vos différentes opérations avec Azure, vous ne devriez pas utiliser tout ce crédit en un coup).

Petit disclaimer : il y aura forcément un aspect « magique » ou un aspect de confusion pour les nouveaux arrivants sur Azure (et parfois même pour les plus anciens…) car Azure est très vaste, mais ne vous inquiétez pas, c’est tout à fait normal !

Il nous faudra tout d’abord installer Azure-CLI sur notre poste, afin d’utiliser la commande az (qui nous permet de faire de l’Azure directement via notre fenêtre Powershell). Pour se faire, ouvrir Powershell en mode administrateur et utiliser la commande suivante :

Invoke-WebRequest -Uri  -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList ‘/I AzureCLI.msi /quiet’

Redémarrer votre Powershell pour que la commande puisse être active. Si cela ne fonctionne pas chez vous, installez le .msi directement sur le site et installez-le classiquement.

Il vous faut maintenant vous connecter, pour que votre instance et les informations soient bien raccorder à votre Portail Azure :

az login -u votremail@mail.com -p votremotdepasse

Kubernetes

Kubernetes est un orchestrateur. On peut dire que c’est un ensemble de services réseaux qui permet de lancer des pods Docker en cluster avec une gestion de Load Balancing.

Pods

Les pods correspondent au processus en cours d’exécution et encapsulent un ou des conteneurs applicatifs. Ce sont des instances uniques, cela signifie qu’ils possèdent :

  • Une IP unique
  • Un fichier qui indique comment le conteneur doit être exécuté
  • Des ressources de stockage

Ce qu’il faut retenir, si nous devions résumer un peu tout ça, c’est que les pods peuvent correspondre à une application ayant sa propre mémoire, sa propre IP. Néanmoins, un pod a une durée de vie définit et ne sera pas en mesure de se relancer automatiquement de lui-même.

Load Balancing

Ou répartition de charge en français, désigne un processus de répartition d’un ensemble de tâche sur un ensemble de ressources. Le but étant de rendre le traitement global plus efficace, en permettant d’optimiser le temps de réponse pour chaque tâche tout en évitant un surcharge inégale des nœuds de calculs.

Création d’un Resource Group Azure : WeatherForecastAPI_RG

Resource Group (ou RG)

Un resource group ou groupe de ressources est en quelque sorte un conteneur dit « logique » ayant pour objectif de regrouper différentes entités (Web API, VM, Base de données, etc…). Toutes les entités présentes au sein du groupe sont alors accessibles.

Dans notre cas, cela va nous permettre de créer un cluster et de déployer notre application directement dans ce RG.

Pour pouvoir créer un groupe de ressources en ligne de commande :

az group create --name WeatherForecastAPI_RG --location francecentral

La réponse à cette commande devra vous apparaître sous cette forme :

{
  "id": "/subscriptions/caf29a4f-0f21-45d9-b52e-f1e0c0b8e4be/resourceGroups/WeatherForecastAPI_RG",
  "location": "francecentral",
  "managedBy": null,
  "name": "WeatherForecastAPI_RG",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}

Comme nous pouvons le voir, nous retrouvons le nom de notre Resource Group ainsi que son state (Succeeded). Nous pouvons également voir que nous avons bien la localisation précédemment choisie qui nous est retournée.

Build de l’image Docker

Docker

Docker est une plateforme de conteneurisation. Et les conteneurs ressemblent en tout point à des machines virtuelles ou seul le système d’exploitation ou OS aura été virtualisé. Docker permet de regrouper tout le nécessaire de notre application et est donc qualifiée de compacte, puissante et innovante avec une scalabilité importante.

Nous allons donc builder l’image dont on parle un peu plus haut : weatherforecastlinux mais cette fois nous allons récupérer le tag avec le mot clef -t (que vous pouvez également voir sur la capture d’écran plus  haut).

docker build -t weatherforecastlinux:dev .

Si tout se déroule correctement vous êtes censés avoir une mention de toutes les étapes présente dans votre Dockerfile ainsi que la notion Successfully

Création de la registry WEFCACR dans Azure Container Registry (ACR)

Registry

Une registry est une sorte de « repository » d’images. Grossièrement on peut dire que c’est un espace de stockage d’images.

Pour pouvoir la créer sous Azure en ligne de commande :

az acr create --resource-group WeatherForecastAPI_RG --name WEFCACR --sku Basic

La commande ci-dessus permet de créer une registry, en spécifiant le Resource Group ainsi que le nom que l’on souhaite donner à la registry (ici WEFACR). Le –sku Basic est un élément sans importance, d’ailleurs si vous ne l’indiquez pas, par défaut il vous sera rajouté.

La commande suivante, vous permet de lister les différentes registry.

az acr list --resource-group WeatherForecastAPI_RG --query "[].{acrLoginServer:loginServer}" --output table

Enfin la commande az acr login, vous permet comme son nom l’indique de vous connecter à Azure Container Registry (ACR).

az acr login --name WEFCACR

Tag de l’image Docker avec la registry wefcacr.azurecr.io

La commande ci-dessous, vous permet de taguer votre image docker en lui donnant un nouveau nom :

docker tag weatherforecastlinux:dev wefcacr.azurecr.io/weatherforecast:dev

Se connecter dans la registry WEFCACR

az acr login --name WEFCACR

 

Push de l’image Docker dans WEFCACR

On va push l’image dans la registry en faisant un docker push et en spécifiant le nom de la registry (que l’on peut retrouver à l’aide de la commande az acr list) et en spécifiant le nom de l’image ainsi que son tag.

docker push wefcacr.azurecr.io/weatherforecast:dev

 

Création du cluster AKS WEFCACRCluster

Cluster

Un cluster Azure peut être considéré comme une « grappe », il peut utiliser des nœuds et exécuter des conteneurs.

Allez sur le portail Azure et dans la barre de rechercher, taper Kubernetes services :

Kubernetes_services.png

Cliquez sur le bouton Add, vous atteindrez cette page :

Picture2.png

Puis cliquer sur Ajouter, votre Cluster mettra un certains temps à se créer ce qui est tout à fait normal. Il vous faudra donc patienter deux minutes grand maximum, avant de lancer la commande suivante :

Connexion au cluster WEFCACRCluster

az aks get-credentials --resource-group WeatherForecastAPI_RG --name WEFCACRCluster

permet d’associer le ressource group a notre cluster

Liaison entre le cluster AKS et la registry

az aks update -n WEFCACRCluster -g WeatherForecastAPI_RG --attach-acr WEFCACR

ici nous attachons notre cluster a notre registry en spécifiant a qu’elle ressources groupe notre cluster appartient

Installation de Helm sous Windows

Helm est un gestionnaire de paquets pour Kubernetes qui va permettre d’installer et de gérer le cycle de vie de nos applications.

Pour l’installer sous Windows, il vous faut installer Chocolatey et pour se faire voici la première commande permettant d’installer Chocolatey (gestionnaire de paquets pour Windows qui vous permet d’installer ou de désinstaller des applications grâce à la commande choco).

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
  • Installation de Helm via Chocolatey
choco install kubernetes-helm

 

Création des fichiers avec Helm

Nous allons créer un dossier chart, qui sera architecturé de la façon suivante :

  • chart/
    • Chart.yaml
    • values.yaml
    • templates/
      • deployment.yaml
      • service.yaml

Architecture du fichier Chart.yaml

name: aspnet3-demo
version: 1.0.0

Architecture du fichier values.yaml

environment: development

apphost: k8s

label:
name: dockerwithlinux

container:
name: dockerwithlinux
pullpolicy: IfNotPresent
image: jlaacr02.azurecr.io/app1
tag: v1
port: 80
replicas: 3

service:
port: 8888
#type: ClusterIP
type: NodePort

Ce fichier va nous permettre de définir quelle image nous allons pull et quel tag utiliser, ainsi que les port que nous voulons.

Architecture du fichier templates/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment
  labels:
    app: {{ .Values.label.name }}
spec:
  replicas: {{ .Values.replicas }}
  selector:
    matchLabels:
      app: {{ .Values.label.name }}
  template:
    metadata:
      labels:
        app: {{ .Values.label.name }}
        environment: {{ .Values.environment }}
    spec:
      containers:
        - name: {{ .Values.container.name }}
          image: {{ .Values.container.image }}:{{ .Values.container.tag }}
          imagePullPolicy: {{ .Values.container.pullPolicy }}
          ports:
            - containerPort: {{ .Values.container.port }}
          env:
            - name: apphost
              value: {{ .Values.apphost }}
            - name: appenvironment
              value: {{ .Values.environment}}

Ce fichier forme notre application en type deployement .

Architecture du fichier templates/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}-service
  labels:
    app: {{ .Values.label.name }}
spec:
  ports:
  - port: {{ .Values.service.port}}
    protocol: TCP
    targetPort: {{ .Values.container.port }}
  selector:
    app: {{ .Values.label.name }}
  type: {{ .Values.service.type }}

Ce fichier forme notre application pour le mode service.

Déploiement dans AKS via Helm

La commande ci-dessous permet de déployer notre image.

helm install dockerwithlinux ./chart

Déploiement dans AKS sans Helm

Nous allons créer un fichier my1.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dockerwithlinux-app
spec:
  selector:
    matchLabels:
      run: dockerwithlinux
  replicas: 3
  template:
    metadata:
      labels:
        run: dockerwithlinux
    spec:
      containers:
        - name: dockerwithlinux
          image: jlaacr02.azurecr.io/dockerwithlinux:v1
          ports:
            - containerPort: 80
              protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: dockerwithlinux-service
  labels:
    app: dockerwithlinux
spec:
  ports:
  - port: 8888
    protocol: TCP
    targetPort: 80
  selector:
    app: dockerwithlinux
  type: NodePort

Déploiement dans Kubernetes du fichier my1.yaml

kubectl apply -f my1.yaml

Exposition du déploiement en service

kubectl expose deployment dockerwithlinux-deployment --type=LoadBalancer --name=dockerwithlinux-service

Récupération de l’adresse IP externe du service

kubectl get service dockerwithlinux-service

Cette commande nous permet de récupérer notre service ainsi que l’IP externe qui sera tout d’abord dans un état dit « pending » (en attente en français).

getservices.PNG

Nous en avons créé un deuxième de service ici, mais fiez-vous à la commande get-service que vous voyez.

Comme nous pouvons le voir ici, par rapport à ce que nous disions, nos avons un EXTERNAL-IP ou IP externe qui prend tout d’abord un état « en attente » en fonction de l’état de votre cluster (vous n’aurez pas du tout la même IP que nous donc dans l’étape du dessous pensez bien à mettre votre EXTERNAL-IP que la commande vous indiquera).

Test du service

Comme vu juste au dessus, nous allons donc récupérer notre EXTERNAL-IP est l’inclure dans la commande suivante :

curl 20.40.148.135/controllerName/methodName

Mettre capture d’écran.

Nous allons maintenant nous rendre sur le portail Azure, afin de visualiser le cluster WEFACRCluster.

Monitoring

Cluster

portailcluster.PNG

Nous voici à présent sur le portail Azure, dans notre Cluster (pour rappel, pour y accéder il faut aller au niveau de Kubernetes Services, puis sur votre Cluster, et aller dans l’onglet Insights). On peut constater les diverses activités de celui-ci.

On peut voir la quantité de CPU utilisé, la mémoire, le nombre de nœuds ainsi que l’activité des pods.

Contrôleurs

Vous restez sur votre Cluster, et vous devez sélectionner Controller :

controller.PNG

Cette partie contrôleurs, peut s’apparenter au portail Kubernetes qui nous permet de visualiser les différents états de nos images.

 

Conclusion

Comme nous avons pu le voir tout au long de ce tutoriel, Azure est une sorte de baguette magique surpuissante, mais qui dissimule un pouvoir mal compris ou mal utilisé par beaucoup d’entre nous finalement. Hors malgré cela, il ne faut pas simplement le pointer du doigt en disant que c’est le mal, mais plutôt essayer de comprendre en profondeur où cela veut nous mener. Kubernetes et Docker sont de plus en plus mis sur le devant de la scène et pour une meilleure compréhension, nous avons tendance à penser qu’il vaut mieux que vous vous formiez indépendamment d’Azure, car la dissimulation est le pire ennemi du savoir et dans notre milieu, en tant que développeurs, le savoir et la capacité d’apprendre par nous-même est, selon nous, primordial.

 

Article écrit par :

  • Julie LACOGNATA <julie.lacognata@infeeny.com>
  • Kévin ANSARD <kevin.ansard@infeeny.com>

Docker et les containers sous Linux

Pré-requis

Vous aurez besoin des éléments suivants pour suivre ce tutoriel :

  • Docker
  • Visual Studio 2019
  • Powershell (ou votre terminal favoris)
  • DotNet

Point d’attention : Il est important que vous pensiez à “switch” votre Docker (si ce n’est pas déjà fait) en Switch to Linux container.

On a essayé de comprendre au mieux le fonctionnement de Docker avec les containers sous Linux depuis un poste sous Windows. Dans cette démarche, nous avons effectués deux essais :

  • Le premier avec Visual Studio et le support Docker intégré.
  • Le second en ligne de commande avec un Dockerfile produit par nos soins.

Exemple d’un projet sous Visual Studio avec support Docker sous Linux

Voici les étapes suivies pour la création du projet (accès pour les néophytes qui ne connaîtraient pas l’environnement de Visual Studio) :

  • Créer un projet WebApplication avec ASP .NET Core 3.1
  • Prendre l’option API et cocher la case “Enable Docker support” avec pour option Linux

Le Dockerfile

Dans le cadre d’un projet avec Docker et des containers sous Linux, le Dockerfile est quelques peu différent :

Pour rappel : lors de la création d’un projet sous Visual Studio avec le support Docker, le Dockerfile est généré automatiquement, avec la commande FROM référençant l’ISO de l’OS choisit (dans notre cas : Linux) avec l’import de la librairie ASP .NET Core.

On a cherché à comprendre pourquoi il y avait deux EXPOSE. En nous renseignant au niveau de la documentation Docker officielle, nous avons compris l’utilité de ceux-ci, son fonctionnement in fine. Néanmoins, nous n’avons pas compris pourquoi notre API ne nous renvoie rien si nous changeons les ports avec la commande suivante (sous Powershell) :

docker run -d -p 42422:80 image_name

Cette commande, permet d’ajouter un host au port 80, dans notre cas 42422. Nous vous expliquerons les différentes options de cette ligne de commande un peu plus bas lors de notre second exemple.

Si on exécute avec le programme à l’aide du bouton “Docker” dans Visual Studio, celui-ci est correctement lancé (par défaut ça vous renverra au WeatherForecast si vous avez pris une API classique).

Exemple d’un projet en ligne de commande avec création d’un Dockerfile

Pour information, le début de notre exemple se base sur le tutoriel suivant qui lui se base sur des containers sous Windows. Par conséquent, il n’y a que le début de notre projet qui ressemble à cette documentation.

Dans le cadre de cet exemple, nous allons mettre en place les éléments suivants :

  • Création d’un dossier de travail
  • Création d’une application .NET
  • Création d’un fichier Dockerfile vide
  • Mise en place du Dockerfile Linux / ASP .NET Core
  • Création d’une image Docker de notre application à partir de notre Dockerfile
  • Création d’un container / exécution de notre container
  • Test de notre application
  • Modification des ports utilisés

Nous allons tout d’abord, créer un dossier dans lequel nous allons effectuer les différentes opérations que nous avons résumés juste au-dessus. Ce dossier s’appellera tuto, pour se faire, nous allons écrire dans notre commande Powershell la commande suivante :

mkdir tuto
cd tuto

La commande mkdir permet de créer le dossier tuto, et la commande cd permet de se placer au niveau du dossier tuto.

Pour la suite, nous allons créer un nouveau projet à l’intérieur du dossier tuto (puisque nous nous y trouvons) :

Nous faisons appel à dotnet car nous souhaitons créer une application .NET, le “new console” permet de définir le type de projet souhaité (ici une application Console). Le -o permet d’indiquer le path du projet app et le -n permet de lui donner un nom en l’occurrence ici : myapp.

Sur l’image ci-dessus, nous pouvons constater que nous nous sommes placés au niveau du dossier app, puis nous avons affichés le contenu du dossier.

Nous avons ensuite exécuter l’application avec la commande :

dotnet run

Cela nous affiche la chaîne de caractère “Hello World!”. En effet, lorsque nous lançons Visual Studio et que nous allons sur le fichier Program.cs, nous voyons que par défaut, la méthode Main affiche la string en question.

Ensuite, nous allons créer notre image Docker. Pour mener a bien cette tâche, nous avons besoin de deux choses :

  • De l’exécutable (.dll)
  • Du Dockerfile

Pour créer l’exécuter, nous avons utilisés la commande suivante:

Celle-ci nous sert à compiler l’application dans le dossier publish. Nous pouvons voir qu’après l’exécution de la commande, le path est indiqué.

Ici, nous vérifions bien que myapp a bien été compilé en myapp.dll.

Nous allons créer le fichier Dockerfile dans le dossier tuto (le fichier doit se trouver à la racine du projet). Il va être composé de la façon suivante :

  • Le FROM ressemble quasiment à celui qui se trouve plus haut dans le premier exemple, à la différence qu’il y a pas de AS base en plus.
  • Le COPY va permettre de copier tout se qui se trouve dans notre dossier publishdans le dossier app, qui lui sera crée dans notre container.
  • Le ENTRYPOINT va permettre d’indiquer à Docker qu’il est une application exécutable en partant de dll.

Nous allons maintenant créer notre image, pour se faire, nous allons retourner à la racine du projet tuto. Puis, nous exécuterons :

Nous allons examiner cette commande ensemble :

  • build : Créer une nouvelle image Docker
  • -t: Permet de donner un nom à cette image
  • -f: Permet de désigner le fichier que nous voulons sélectionner
  • Dockerfile: Correspond à notre fichier et le . derrière sert à indiquer qu’il doit chercher dans le dossier actuel (en l’occurrence le dossier tuto)

Nous pouvons constater, que Docker lors de la première étape va pull l’image de l’ISO, ainsi que les dépendances nécessaires. Durant la deuxième étape, la copie du contenu du dossier publish dans le dossier app va être réalisé. Et enfin, la troisième étape permet d’indiquer à Docker que c’est un exécutable.

Si maintenant, nous faisons un :

docker images

Nous pouvons voir que la dépendance aspnet de .NET Core a bien été pull correctement et que notre image est bien existante (myimage).

Pour la prochaine étape, nous allons créer et exécuter notre container via notre image avec la commande :

docker run image_name

Nous pouvons observer que notre commande nous renvoie la même chaîne de caractère que nous renvoyé notre app. Si nous exécutons :

docker ps -a

Cette commande nous permet d’afficher la liste des différents containers présent sur votre poste. On peut y voir :

  • L’ID du container
  • Le nom de l’image sur lequel il est basé
  • Le point d’entrée
  • La date de création
  • Le statut
  • Le ou les ports sur lequel il est hébergé
  • Le nom du container (généré par défaut)

En l’occurrence, nous n’avons pas de port indiqué sur l’image ci-dessus, car notre application n’est pas une application Web.

Dans le cas où vous auriez une application Web et non pas une application Console comme nous. Vous pourriez tout à fait exécuter la commande suivante :

docker run -d -p 42422:80 –name container_name image_name

Elle nous renvoie, l’ID du container crée et celui-ci sera hébergé sur le port 80 pour host le port 42422.

Nous vous proposons un récapitulatif des commandes docker, dotnet et bash
ci-dessous :

Bash :

  • mkdir : Permet de créer un dossier
  • cd : Permet de se déplacer d’un dossier à l’autre
  • ls : Permet d’indiquer le contenu d’un dossier

Dotnet :

  • dotnet run : Permet d’exécuter une application .NET
  • dotnet new : Permet de créer une application
  • dotnet publish : Permet de compiler une application

Docker :

  • docker build : Permet de créer une image
  • docker images : Permet d’afficher l’ensemble des images
  • docker run : Permet de créer et d’exécuter un container
  • docker ps -a : Permet de voir l’ensemble des containers
  • docker rm : Permet de supprimer un container

Article écrit par :

  • Julie LACOGNATA <julie.lacognata@infeeny.com>
  • Pierre KORE <pierre.kore@infeeny.com>
  • Kévin ANSARD <kevin.ansard@infeeny.com>

Comprendre Docker et les architectures orientées micro-services

Prise en main

Nous avons essayé de prendre en main une solution d’architecture orientée micro-services avec Docker.

Pour cette analyse, nous nous sommes basés sur le repository suivant : https://github.com/dotnet-architecture/eShopOnContainers

Il est très complet et les explications pour l’installer sur votre poste sont suffisamment clair pour que vous puissiez lancer le projet sur vos machines. Assurez-vous d’avoir Docker d’installé et un Visual Studio ou Visual Studio Code.

Cet article relate une expérience en entreprise afin de prendre en main tout cela. Si vous rencontrez des coquilles ou des interrogations, n’hésitez pas à nous en faire part.

Projet eShopOnContainers

Sur ce, revenons-en au sujet principal : le projet eShopOnContainers.

Si vous souhaitez une meilleure compréhension des micro-services, vous avez des livres numériques à disposition dans le lien du Github. Pour les personnes qui ne seraient pas à l’aise avec l’anglais voici un lien en français résumant les points importants : https://docs.microsoft.com/fr-fr/dotnet/architecture/microservices/architect-microservice-container-applications/microservices-architecture.

Le livre a pour but d’expliquer les principes de base des architectures orientées micro-services en utilisant Docker et ses conteneurs. Le projet eShopOnContainers illustre les propos tenu dans le livre.

Les différentes étapes de notre mise en place du projet

Installation de Docker

Version Docker Desktop sur Windows Enterprise (version également valable pour Windows Pro mais pas pour la version Classic)

Pour toutes les personnes qui installent Docker pour la première fois, les étapes se font facilement et sans encombre, il vous faudra créer un compte sur le site officiel de Docker (https://www.docker.com/) afin d’avoir un DockerID.

  • Les problèmes rencontrés

Un problème peut parfois arriver lorsque vous avez une version de Docker ultérieure à cette version 18.06.0-ce-win70 et que vous essayez de la mettre à jour vers la version actuelle Docker Desktop Community 2.2.0.0.

En effet, il y a des résidus de l’ancienne version qui empêche de mettre à jour la version de Docker.

  • La solution

Pour résoudre ce problème de mise à jour de version de Docker, il existe un script PowerShell que vous trouverez ci-dessous :

Il faut enregistrer ce fichier sous format .ps1 et le l’exécuter avec une fenêtre PowerShell en mode administrateur !

$ErrorActionPreference = « SilentlyContinue » kill -force -processname ‘Docker for Windows’, com.docker.db, vpnkit, com.docker.proxy, com.docker.9pdb, moby-diag-dl, dockerd try { ./MobyLinux.ps1 -Destroy } Catch {} $service = Get-WmiObject -Class Win32_Service -Filter « Name=’com.docker.service' » if ($service) { $service.StopService() } if ($service) { $service.Delete() } Start-Sleep -s 5 Remove-Item -Recurse -Force « ~/AppData/Local/Docker » Remove-Item -Recurse -Force « ~/AppData/Roaming/Docker » if (Test-Path « C:\ProgramData\Docker ») { takeown.exe /F « C:\ProgramData\Docker » /R /A /D Y } if (Test-Path « C:\ProgramData\Docker ») { icacls « C:\ProgramData\Docker\ » /T /C /grant Administrators:F } Remove-Item -Recurse -Force « C:\ProgramData\Docker » Remove-Item -Recurse -Force « C:\Program Files\Docker » Remove-Item -Recurse -Force « C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Docker » Remove-Item -Force « C:\Users\Public\Desktop\Docker for Windows.lnk » Get-ChildItem HKLM:\software\microsoft\windows\currentversion\uninstall | % {Get-ItemProperty $_.PSPath} | ? { $_.DisplayName -eq « Docker » } | Remove-Item -Recurse -Force Get-ChildItem HKLM:\software\classes\installer\products | % {Get-ItemProperty $_.pspath} | ? { $_.ProductName -eq « Docker » } | Remove-Item -Recurse -Force Get-Item ‘HKLM:\software\Docker Inc.’ | Remove-Item -Recurse -Force Get-ItemProperty HKCU:\software\microsoft\windows\currentversion\Run -name « Docker for Windows » | Remove-Item -Recurse -Force #Get-ItemProperty HKCU:\software\microsoft\windows\currentversion\UFH\SHC | ForEach-Object {Get-ItemProperty $_.PSPath} | Where-Object { $_.ToString().Contains(« Docker for Windows.exe ») } | Remove-Item -Recurse -Force $_.PSPath #Get-ItemProperty HKCU:\software\microsoft\windows\currentversion\UFH\SHC | Where-Object { $(Get-ItemPropertyValue $_) -Contains « Docker » }

Une fois le script enregistré, pour le lancer il vous suffit de lancer la commande dans le dossier où vous avez enregistrer le script suivante dans votre PowerShell :

.\[nom de fichier].ps1

Que permet-il ? De retirer tous les résidus présent sur votre poste de travail.

Une fois le script terminé, vous pouvez relancer l’installation de Docker Desktop sur votre machine.

Cloner le repository eShopOnContainers

Pour se faire, rendez-vous sur le lien se trouvant plus haut et ouvrir un cmd ou une fenêtre Powershell dans le répertoire souhaité puis exécuter la commande suivante :

git clone https://github.com/dotnet-architecture/eShopOnContainers.git

Configurer votre réseau

Lors de l’étape de configuration de votre réseau, nous vous conseillons (au cas où le script add-firewall-rules-for-sts-auth-thru-docker.ps1 ne fonctionne pas immédiatement au lancement et vous indique une erreur) de vérifier la sécurité de votre PC. Pour pouvoir y accéder, ouvrez votre fenêtre PowerShell en mode administrateur dans le répertoire de votre projet et plus exactement dans :

C:\votre_repertoire\eShopOnContainers\deploy\windows

Et exécutez la commande suivante :

> Get-ExecutionPolicy

Cela va vous indiquer le mode dans lequel vous êtes entre

  • Restricted
  • AllSigned
  • RemoteSigned
  • Unrestricted

Ensuite pour modifier cette restriction, taper et exécuter la commande suivante :

>Set-ExecutionPolicy RemoteSigned

Le mode RemoteSigned permet d’autoriser l’exécution de script locaux. Nous vous conseillons de remettre après avoir lancer le script .ps1 de remettre la protection initiale de votre PC pour éviter toutes erreurs possible par la suite.

Builder le projet

Toujours avec votre fenêtre PowerShell revenir sur src\ et lancer un

docker-compose build

Cette étape prend un peu de temps (entre 10 à 30 minutes selon les pc et la connexion)

Une fois cette étape terminée, lancer la commande

docker-compose up

Elle va vous permettre d’instancier les différents micro-services du projet.

Chaque services dans la solution possédant son propre Dockerfile, le fait de lancer un docker-compose permet d’indiquer qu’on lance l’entièreté du projet afin de lancer l’exécution de tous les micro-services.

Vous pouvez lancer l’adresse suivante : localhost:5107 qui vous permettra de connaitre l’état de vos micro-services (si tout s’est bien passé, tout devrait apparaitre vert et vous pourrez en parallèle ouvrir le site web sous l’adresse localhost:5100 et voir le eShopOnContainers Catalog.

Fichier docker.compose.yml ?

Docker compose est un outil  de gestion de package Docker. Cet outil va lancer vos conteneurs et leurs éventuels liens à partir d’un fichier de configuration écrit en yaml.

Il permet la gestion de plusieurs conteneurs et leurs communication grâce a un fichier docker-compose.yml

Exemple d’un fichier docker.compose.yml

Pour aller plus loin

Hello World – Docker

Ouvrir une fenêtre PowerShell et lancer la commande :

docker run hello-world

Celle-ci va télécharger l’image, la build et la run et vous obtiendrez :

Qu’est-ce qu’un Dockerfile ?

Un Dockerfile est “un fichier texte qui contient des instructions sur la façon de construire une image Docker. C’est comme un script batch” (cf. le livre Containerized Docker Application Lifecycle with Microsoft Platform and tools book).

Le principal avantage de ce fichier est qu’il facilite la reproductibilité de la création des images.

Comme vous pouvez le voir ci-dessus, voici la composition d’un Dockerfile.

Comment ça marche ?

  • FROM : Permet de définir une image de base sur laquelle construire notre image. Par exemple la première ligne de la capture d’écran va récupérer l’image aspnet:3.1-nanoservier-1903 (version 3.1 d’ASP .NET Core) sur lequel va tourner notre container.
  • WORKDIR : Définit le dossier dans lequel l’installation des packages va être fait, il se fait sur le daemon.
  • EXPOSE : Sert à définir le ou les port(s) exposé(s) par notre container.
  • COPY : Copie les fichiers de notre répertoire vers le WORKDIR définit.
  • RUN : Permet de build notre image.
  • ENTRYPOINT : Correspond au point d’entrée pour lancer notre application

Docker Engine (daemon)

Afin d’orchestrer les différents conteneurs. Docker est doté d’un service de type client-serveur qui permet la communication entre l’utilisateur et un service nommé Docker Engine.

Docker Engine est une Api RESTful qui se charge de construire et exécuter les conteneurs. Le Client est un exécutable permettant (via une invite de commande la plupart du temps) d’envoyer des instructions à un daemon faisant tourner Docker Engine.

On notera qu’il est tout à fait possible d’interroger le daemon docker autrement qu’avec le client. (Utilisation de requête Curl par exemple).

Les images Docker

Une image est un ensemble de fichier en lecture seul archivé au format .tar :

  • Version : contenant la version de l’image.
  • Json : contenant un grand nombre de métadonnée (ex : id de l’image, référencement des images utilisées).
  • tar : archive contenant le système de fichier de l’image

Elles sont une représentation statique d’une application ou d’un service, de leurs configurations ou et de leurs dépendances. Un conteneur n’est donc rien d’autres que l’instanciation d’une image Docker.

L’une des forces des images Docker, est qu’elles peuvent être composé d’une ou plusieurs autres images en les référençant. Cela revient à créer une archive englobant tous les fichiers contenus par les images sous-jacent. Elle bénéficie ainsi de l’ensemble du système de fichier de celles-ci lors de son instanciation en conteneurs, évitant ainsi astucieusement les redondances.

Qu’est-ce que ça nous a appris ?

De faire la différence entre une application monolithique et une application orientée micro-services.

Application monolithique

L’application monolithique est simple en terme de conception (beaucoup plus simple à comprendre également)

Il peut convenir au petit projet, mais dès lors que le projet change pour intégrer plus de complexité, il peut s’avérer limité.
pourquoi ?

  • A cause de sa scalabilité -> on s’explique, lorsque vous souhaitez agrandir votre projet à cause d’un goulot d’étranglement, il est tout à fait possible d’agrandir toute l’application. Cependant dans la plupart des cas il n’y a qu’une partie de l’application qui nécessite une mise à l’échelle. Ce qui entraîne un gaspillage des ressources non négligeable.
  • Le déploiement : Dans ce type d’application, lorsqu’une modification est apporté à une partie de l’application c’est l’ensemble qui va être déployé.

Application orientée micro-services

L’application orientée micro-services est complexe en terme de compréhension, mais apporte de nombreux avantages. Chaque services étant indépendant les uns des autres, ils peuvent être réutilisés pour divers projet.

Si demain, on veut récupérer un service de paiement, il est tout à fait possible de le récupérer et de remplacer celui existant par le nouveau (on parle alors d’interopérabilité du service).

  • Il est possible de scaler un service en particulier
  • Grâce à l’isolation permis par Docker, il est possible d’installer un environnement spécifique pour chaque service
  • Facilite grandement le déploiement et la mise à jour des services

Les bases de Docker

Nous avons également pris en main les bases de Docker et vu les principes de conteneur et de conteneurisation.

Article écrit par :

  • Julie LACOGNATA <julie.lacognata@infeeny.com>
  • Pierre KORE <pierre.kore@infeeny.com>
  • Kévin ANSARD <kevin.ansard@infeeny.com>