Tutoriel : Premiers pas de développeur avec Docker, Azure et Visual Studio 2/3

Dans ce tutoriel, nous allons créer une petite application console avec Visual Studio, la déployer d’abord dans un conteneur Linux, puis dans un conteneur Windows, sur Azure.

Les concepts généraux de Docker ont été rappelés sur la page 1/3 de cet article.

Nous utiliserons 2 manières différentes de déployer l’application:

- d’abord vers un conteneur Linux (cette page): en créant les différents composants de manière “manuelle” pour bien comprendre comment fonctionne Docker

- ensuite vers un conteneur Windows (dans la page 3/3 de l’article): en se reposant entièrement sur l’assistant dans Visual Studio qui prendra en charge intégralement les opérations, y compris la création de la VM dans Azure.

Notez que les  2 procédures (manuelle ou auto) fonctionnent aussi bien sur Linux que sur Windows.

Pré-requis

De manière générale pour déployer une application dans un conteneur Docker, il faut:

Il faut On utilisera
Une machine serveur avec un OS proposant une technologie de conteneurs, compatible avec Docker Une VM Linux avec extension Docker ou une VM Windows Server 2016 dans Azure
Une machine cliente sur laquelle un client Docker est installé - Notre PC de dev avec Visual Studio + l’extension Docker pour Visual Studio  - le client Docker en ligne de commande, pratique pour les tests (package Chocolatey)
Des certificats OpenSSL qui permettront au client Docker de se connecter au host Docker - openSSL (pour la partie manuelle du tuto) et/ou - l’extension Docker pour Visual Studio qui les créera pour nous si on part de 0
Le code de votre application ainsi qu’un fichier DockerFile Visual Sudio avec l’extension Docker pour VS qui créera un dockerfile adapté au type de conteneur (c’est à dire l’OS sur lequel il tourne)

 

Nous verrons tout cela étape par étape : à ce stade du tutoriel il vous faut simplement:

 

Je suis partie d’un Visual Studio vierge en terme d’extensions, ce qui me permettra de vous montrer au fur et à mesure les différents composants à installer pour faire fonctionner ce petit monde-là.

 

Les étapes

Pour publier une application dans un conteneur Docker sur Azure, vous pouvez très bien n’utiliser qu’un seul outil : Visual Studio. En effet, l’extension Docker pour Visual Studio vous fournit un assistant qui va s’occuper de provisionner la VM, créer et uploader les certificats et y déployer le code sous la forme d’une image Docker.

Soit. Vous aurez votre application qui tourne dans Docker.

Mais vous n’aurez pas compris comment ça marche en dehors de Visual Studio...et ne saurez pas prendre la main dessus avec les outils Docker.

Donc dans ce tutoriel, on va se retrousser les manches et réaliser les différentes étapes nous-même, jusqu’à arriver à la publication du code où nous passerons effectivement la main à l’extension Docker pour le télécharger et démarrer le conteneur.

Nous allons donc:

  1. Créer une VM Linux avec l’extension Docker dans Azure
    • Créer des certificats SSL à ajouter dans la configuration de l’extension Docker
    • Ajouter des point de terminaison/endpoints sur la VM pour pouvoir se connecter au docker host depuis le client Docker
  2. Installer l’extension Docker pour Visual Studio
  3. Créer une application console ASP.Net 5
  4. Déployer l’application dans un conteneur linux sur notre VM Linux
  5. Déployer la même application dans un conteneur Windows d’une nouvelle VM Windows Server 2016 créée cette fois par Visual Studio
  6. Constater que cela ne fonctionne pas
  7. Modifier le dockerfile
  8. Re-déployer l’application dans un conteneur Windows
  9. Constater que cela fonctionne

 

1. Création de la VM Linux dans Azure

Depuis le portail, sur la marketplace, choisissez la VM Docker on Ubuntu Server:

image

C’est en fait une VM Ubuntu classique, avec l’extension docker pré-installée : elle nous permet d’avoir un docker engine sur notre VM.

image

Cliquez sur “Créer”, puis renseignez le nom de la machine hôte (de préférence,  utilisez le rappel “linux” dans le nom pour ne pas confondre les VMs Windows et Linux lors du déploiement à partir de Visual Studio), l’utilisateur et le mot de passe.

image

Ajout des points de terminaison

Ajoutez un point de terminaison 2376 sur votre VM pour pouvoir vous connecter au Docker host de la manière suivante

image

Faites de même avec le port 80 pour obtenir

image

Ouvrir les ports c’est nécessaire mais cela ne suffit pas pour se connecter au docker host.

En effet, Docker est configuré pour fonctionner avec une clé de sécurité SSL. Bon ça va se compliquer un peu car il va falloir générer les certificats SSL. Cette étape est prise en charge par Visual Studio si vous créez la VM depuis l’assistant : c’est ce que l’on verra dans la 2ème partie du tuto où nous laisserons VS prendre tout en charge pour déployer l’application dans un conteneur Windows.

Création des certificats SSL

Le démon Docker sur le serveur est configuré pour utiliser la sécurité TLS. Le client Docker recherche la clé du client (key.pem) et le certificat (cert.pem) par défaut dans le dossier <%userprofile%>\.docker. Si ces éléments ne sont pas présents, il convient de les générer à l'aide d'OpenSSL.

C’est ce que nous allons faire à présent.

Installez OpenSSL depuis un des sites recommandés ici https://wiki.openssl.org/index.php/Binaries

Générez vos certificats ainsi:

 echo 01 > ca.srl

openssl genrsa -des3 -out ca-key.pem
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca.pem
openssl genrsa -des3 -out server-key.pem
openssl req -new -key server-key.pem -out server.csr
openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem -out server-cert.pem

echo "Creating client keys..."
openssl genrsa -des3 -out client-key.pem
openssl req -new -key client-key.pem -out client.csr
echo extendedKeyUsage = clientAuth > extfile.cnf
openssl x509 -req -days 365 -in client.csr -CA ca.pem -CAkey ca-key.pem -out client-cert.pem -extfile extfile.cnf

echo "Stripping passwords from keys..."
openssl rsa -in server-key.pem -out server-key.pem
openssl rsa -in client-key.pem -out key.pem

ou selon la doc https://docs.docker.com/engine/articles/https/ et copiez-les dans le répertoire <user>/.docker.

(Oui c’est pénible : si vous préférez sauter cette étape, commencez par la partie 3/3 du tuto où VS génère automatiquement les certificats dans le répertoire adéquat lorsqu’il crée la VM Clignement d'œil )

Si l’on était parti d’une VM Ubuntu simple, à laquelle on aurait ajouté l’extension docker, nous aurions pu spécifier les certificats dans la configuration de l’extension en précisant les 3 fichiers de certificats nécessaires. <user>/.docker. Les fichiers à utiliser sont ca.pem, server-cert.pem, server-key.pem.

image

Mais avec la VM incluant une extension déjà configurée, les fichiers sont pris dans le répertoire <user>/.docker.

Si vous voulez modifier les certificats a posteriori, voici une méthode pas très jolie, mais simple et pratique : sélectionnez votre VM et ajoutez une nouvelle fois l’extension Docker en précisant les nouveaux certificats. Validez.

L’installation réussit mais on trouve une erreur dans les détails de l’extension.

Redémarrez la VM : cette fois ça fonctionne.

On a terminé de configurer notre VM avec Docker.

Cliquez sur “Créer”

Votre machine est en cours de provisionnement

    

image

Vous pouvez y accéder facilement grâce à la zone de recherche du bandeau et l’épingler sur l’écran d’accueil pour y accéder facilement.

image

Passons maintenant sur la machine client : celle sur laquelle vous avez  installé Visual Studio.

2. Installation de l’extension Docker pour Visual Studio

Installez tout d’abord Microsoft ASP.NET and Web Tools 2015 (Beta8) – Visual Studio 2015 ; choisissez les composants à installer selon les instructions ci-dessous:

Install Instructions

1.
Close all instances of Visual Studio.

2.
Install .NET Version Manager (Beta8) using DotNetVersionManager-x64.msi. For 32 bit machines use DotNetVersionManager-x86.msi.

3.
Update Visual Studio 2015 (Enterprise, Professional or Community) with ASP.NET and Web Tools 2015 (Beta8) by installing WebToolsExtensionsVS14.msi. If you are using Visual Studio 2015 Express for Web, then install WebToolsExtensionsVWD14.msi instead.

 

Dans Visual Studio, via le menu “Tools>Extensions and Updates”, ajoutez l’extension Visual Studio Tools for Docker (ici en October Preview):

image

image

3. Création d’une application Console

Puis créez un nouveau projet de type Web/Console Application.

image

Ajoutez simplement les 2 lignes de code suivantes dans le Main du fichier Program.cs:

 namespace DockerConsoleApp
{
    public class Program
    {
        public void Main(string[] args)
        {
            Console.WriteLine("I'm running in a container :D");
            Console.ReadLine();
        }
    }
}

Si vous l’exécutez localement sur la machine, vous obtiendrez

image

 

4. Déployer l’application dans un conteneur sur notre VM Linux

Faites un click droit sur le projet dans l’explorateur de fichiers et choisissez “Publish”:

image

Voici l’assistant de publication qui vous propose de publier votre application dans un conteneur docker.

image

Sélectionnez la cible Docker Containers

image

Choisissez la souscription Azure et le nom de la VM Linux avec Docker que vous venez de créer puis validez.

image

Remarquez l’url de votre agent Docker qui utilise le port 2376.

Cliquez sur le bouton “Validate Connection”: normalement, ça devrait bien se passer.

Je vous encourage à installer le client Docker de base via Chocolatey : cela vous permettra de communiquer avec votre Docker host sans Visual Studio et de vous familiariser avec les commandes Docker.

Si vous n’avez pas encore Chocolatey sur votre machine, vous pouvez suivre cette petite vidéo qui vous expliquera comment faire pour installer Chocolatey ainsi que le client Docker.

Vous pouvez tester la connexion à partir du client docker en copiant/collant la commande Preview dans les options avancées de la boite de dialogue.

image

Je vais utiliser la commande “info”, et vous pouvez utiliser les commandes docker depuis le Command Prompt.

image

Pour l’instant, je n’ai pas d’image docker et a forciori, pas de conteneur en cours d’exécution.

A présent, cliquez sur le bouton Publish

Plusieurs choses se passent à ce moment (vous pouvez voir le détail dans la fenêtre Output de VS, notamment:

  • la création du fichier Dockerfile dans le projet Visual Studio
  • la création de l’image correspondant à votre application, en partant du packaging décrit dans le dockerfile
  • le transfert de votre app dans le docker host, via le docker engine
  • la récupération des “couches du millefeuille” applicatif décrites dans le dockerfile et le point d’entrée du code utilisé pour l’exécution du conteneur
  • le démarrage du conteneur

 

Normalement vous devriez vous retrouver avec ce genre de résultat, à la fin de l’output

 VERBOSE:  ---> Running in 7bf52b2450c1
VERBOSE:  ---> 191d76de7c39
VERBOSE: Removing intermediate container 7bf52b2450c1
VERBOSE: Successfully built 191d76de7c39
VERBOSE(0,0): Warning : You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
The Docker image "dockerconsoleapp" was created successfully.
VERBOSE: Starting Docker container: dockerconsoleapp
Executing command [docker --tlsverify -H tcp://stephetutodockerlinux.cloudapp.net:2376 run -t -d dockerconsoleapp]
VERBOSE: cc80b00c123b7978695931afcaefe05165876f07a95edb54662513ec9d8a3902
Docker container started with ID: cc80b00c123b7978695931afcaefe05165876f07a95edb54662513ec9d8a3902
To see standard output from your application, open a command line window and execute the following command: 
    docker --tlsverify -H tcp://stephetutodockerlinux.cloudapp.net:2376 logs --follow cc80b00c123b7978695931afcaefe05165876f07a95edb54662513ec9d8a3902
Publish completed successfully.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
========== Publish: 1 succeeded, 0 failed, 0 skipped ==========

Le fichier Dockerfile

Le dockerfile est créé par Visual Studio en fonction de l’OS – Linux ou Windows - sur lequel est basé le conteneur qui va faire tourner l’app. Il permet à docker de savoir comment reconstituer le contexte : c’est à dire les couches d’images dont votre application a besoin pour s’exécuter. Vous allez comprendre en jetant un œil au dockerfile:

 FROM microsoft/aspnet:1.0.0-beta8

ADD . /app

WORKDIR /app/approot

ENTRYPOINT ["./DockerConsoleApp"]

Sur une machine linux, on va partir de l’image Microsoft/aspnet avec la version 1.0.0-beta8, récupérée dans la registry officielle de Docker.

La registry regroupe les images qui y sont poussées par les éditeurs et qui sont ensuite utilisées et notées par les utilisateurs.

image

Cette image aspnet publiée par Microsoft est elle-même basée sur Mono, l’implémentation x-plat de .Net.

image

Si vous jetez un œil au dockerfile cette image vous trouverez les couches qui permettent cette fois de retrouver le bon contexte de packaging pour ASP.NET pour linux.

image

On continue comme ça jusqu’à l’OS (et sa version) : c’est l’illustration des couches du fameux millefeuille, qui permet de retrouver toujours un environnement de déploiement et d’exécution identique.

Dans notre dockerfile, il est précisé l’ajout du package de notre application, le répertoire courant ainsi que le point d’entrée pour l’exécution de l’application.

Le conteneur

Pour vérifier si votre conteneur a bien démarré, on va réexécuter la commande docker info: on y trouve bien 1 conteneur – c’est bon signe Sourire

image

Pour lister les images, on utilise la commande “images”

image

On retrouve bien l’image Microsoft/aspnet qui a été récupéree par docker dans la registry officielle Docker (celle-ci est fournie par Microsof) utilisée en sous-couche de notre image applicative dockerconsoleapp.

On trouve aussi l’image de notre application dockerconsoleapp qui est la dernière couche du millefeuille.

Pour lister les conteneurs, on utilise la commande “ps”"

image

Pour voir la sortie standard de notre application, il suffit de copier/coller la commande suggérée par VS dans l’Output:

 docker --tlsverify -H tcp://stephetutodockerlinux.cloudapp.net:2376 logs --follow cc80b00c123b7978695931afcaefe05165876f07a95edb54662513ec9d8a3902

image

Youpi !!

Dans la dernière partie de l’article, nous déploierons la même application dans un conteneur Windows, créé directement depuis Visual Studio et non plus depuis le portail Azure comme nous l’avons fait ici. Si l’on souhaite utiliser la même solution Visual Studio pour déployer l’application sur 2 types de conteneurs différents, nous verrons qu’il y a quelques petites subtilités, en particulier le dockerfile puisque l’application devra tourner sur 2 OS différents.

Références

https://docs.asp.net/en/latest/publishing/docker.html

https://blogs.msdn.com/b/webdev/archive/2015/01/14/running-asp-net-5-applications-in-linux-containers-with-docker.aspx

https://blog.siliconvalve.com/2015/01/07/get-started-with-docker-on-azure/

https://github.com/chanezon/azure-linux

https://azure.microsoft.com/fr-fr/documentation/articles/virtual-machines-docker-with-portal/

https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-docker-ubuntu-quickstart/