Juin 2019

Volume 34, numéro 6

Cet article a fait l'objet d'une traduction automatique.

[Points sur les données]

EF Core dans une application Docker conteneurisée (3e partie)

Par Julie Lerman

Julie LermanDans les deux derniers articles, je vous ai présenté dans la création d’une petite API ASP.NET Core à l’aide d’Entity Framework encapsulés dans un conteneur Docker. Dans le premier article, j’ai inclus une base de données SQLite au sein du conteneur. Dans la seconde, j’ai ciblé une base de données SQL Azure est accessible à partir de n’importe quel endroit. Dans ce cas, le plus grand défi était comment conserver les secrets (tels que les mots de passe de base de données) secrète et fluide de configurations (par exemple, les chaînes de connexion pour les bases de données de développement ou de production). Ce qui impliquait apprenant à tirer parti de la capacité de Docker Compose à lire les variables d’environnement à partir de l’hôte.

Il existe un autre chemin d’accès très intéressante pour la conservation des données consiste à disposer d’un serveur de base de données et les données dans des conteneurs. J’ai écrit sur l’utilisation de SQL Server pour Linux dans des conteneurs Docker dans les articles précédents, tel que celui à msdn.com/magazine/mt784660. J’aime vraiment le moyen que Steve Lasker de Microsoft exprime la perspective de l’utilisation de SQL Server dans des conteneurs pour le développement et de test :

Rotation SQL dans un conteneur offre aux développeurs la capacité à isoler/simuler un environnement. Y compris une autre version de SQL Server. La possibilité de démarrer un test à partir de l’état exact, chaque fois, il est bon de. En particulier lorsque vous testez une mise à niveau de base de données, au lieu d’essayer de comprendre comment annuler la mise à jour de la base de données, redémarrez simplement le conteneur.

Dans l’article sur SQL Server pour Linux, j’ai d’interagir avec la base de données à l’aide de sqlcmd uniquement à la ligne de commande. Dans un article de la plus récent (msdn.com/magazine/mt832858), j’ai utilisé un Studio de données Azure pour interagir avec un SQL Server et la base de données en conteneur. Maintenant, je souhaite intégrer un serveur SQL dédié en conteneur dans mon développement d’API. Je vais montrer vous effectuer cette opération dans Visual Studio, poursuivre l’exemple que j’ai utilisé dans la colonne précédente.

Récapitulatif de l’API

L’API est simple avec une classe Magazine deux-propriété unique (Id et nom), un contrôleur de Magazines et un DbContext Core EF qui utilise des migrations pour amorcer des nouvelles bases de données avec quatre magazines.

L’itération suivante de l’application, dans la partie 2 de la série (msdn.com/magazine/mt833438), introduit l’orchestration de conteneur via un fichier docker-compose. Alors que c’était une solution de conteneur unique qui n’en ont réellement besoin d’orchestration, docker-compose fourni la possibilité de passer des variables d’environnement dans le conteneur sans stocker les valeurs directement dans l’image. Mais même avec les solutions de conteneur unique, un fichier compose peut être utilisé pour exécuter l’application sur un cluster Docker Swarm ou Kubernetes, ce qui vous donne de mise à l’échelle et la réparation automatique.

La classe MagazinesContext utilisé les variables d’environnement pour injecter un mot de passe à la chaîne de connexion de base de données.

Déplacement vers une base de données en conteneur

L’objectif de cet article est de cibler un serveur SQL Server pour le serveur Linux et une base de données dans des conteneurs sur mon ordinateur de développement. Cela signifie la mise à jour le fichier docker-compose existant et la mise à jour des chaînes de connexion dans l’application. En tout, pas beaucoup d’efforts. Mais si vous n’avez jamais utilisé auparavant, il est certainement intéressant que quelqu'un vous montrer comment !

Plus grands changements seront dans le fichier docker-compose.YML. Et ce qui est très utile est que Docker s’occupera des parties plus difficiles pour vous, simplement en lisant les instructions relayées dans docker-compose. Étant donné que tout ceci commence dans Visual Studio 2017, les outils pour Docker participeront également lorsque vous exécutez ou déboguez à partir de Visual Studio. Si vous utilisez Visual 2019 Studio (qui, où j’écris ceci, lancement officiel que hier, donc je continuerai cette série en 2017), les outils sont intégrée et l’expérience doit être le même.

Voici la version précédente du fichier docker-compose.yml :

version: '3.4'
services:
  dataapidocker:
    image: ${DOCKER_REGISTRY-}dataapidocker
    build:
      context: .
      dockerfile: DataAPIDocker/Dockerfile
    environment:
      - DB_PW

Ce fichier docker-compose gérait uniquement une seule image, définie dans le service dataapidocker. Les outils permet de garantir que la variable DOCKER_REGISTRY est remplacée au moment de l’exécution par le moteur Docker en cours d’exécution sur mon ordinateur de développement. Ensuite, à l’aide de cette image, celle-ci recherchera le fichier Dockerfile (défini dans la partie 1 et 2 de partie de cette série) pour obtenir des instructions sur la procédure à suivre avec l’image lorsque l’instance de conteneur est créé. Étant donné que je n’a pas fourni une valeur pour la variable d’environnement DB_PW directement dans le fichier docker-compose, il me permet de passer une valeur à partir de l’interpréteur de commandes où j’exécute le conteneur ou d’une autre source, tel qu’un fichier .env de docker. J’ai utilisé un fichier .env dans la partie 2 pour stocker la paire clé-valeur de DB_PW et mon mot de passe, eiluj.

Donc maintenant je vais indiquer à docker-compose que je souhaite qu’elle également faire tourner un conteneur de SQL Server. L’image SQL Server pour Linux est une image officielle de Microsoft conteneur du Registre (MCR), même si elle est également répertorié dans Docker Hub pour la découverte. En référençant ici, Docker commencera par regarder dans le Registre local (sur l’ordinateur de développement dans lequel je travaille) et si l’image n’est pas trouvé il, il sera puis extrayez l’image à partir de la MCR. Consultez Figure 1 pour obtenir un exemple de ces modifications.

Fichier de Docker-Compose la figure 1 avec les modifications pour inclure un conteneur/serveur mssql

version: '3.4'
services:
  dataapidocker:
    image: ${DOCKER_REGISTRY-}dataapidocker
    build:
      context: .
      dockerfile: DataAPIDocker/Dockerfile
    environment:
      - DB_PW
    depends_on:
      - db
  db:
    image: mcr.microsoft.com/mssql/server
    environment:
      SA_PASSWORD: "${DB_PW}"
      ACCEPT_EULA: "Y"
    ports:
      - "1433:1433"

Mais le nouveau service que j’ai ajouté, ce qui j’ai nommé db, pointe plus qu’à l’image mssql/serveur. Nous allons, comme on le dit, décompressez les modifications. N’oubliez pas qu’il existe une autre modification sera disponible une fois que je travaille via cette étape.

Le premier changement consiste au sein du service dataapidocker, celui d’origine qui décrit le conteneur pour l’API. J’ai ajouté un mappage appelé depends_on, qui contient ce que YAML appelle un élément de séquence, appelé base de données. Cela signifie que, avant d’exécuter le conteneur dataapidocker, Docker recherche la docker-compose le fichier à un autre service nommé db et devrez utiliser ses détails pour instancier le conteneur défini par ce service.

Le service de base de données commence en pointant sur l’image SQL Server pour Linux à l’aide de son nom officiel de Docker. Cette image nécessite que vous passez deux variables d’environnement lors de l’exécution d’un conteneur — SA_Password et ACCEPT_EULA, par conséquent, la description du service contient également ces informations. Et, enfin, vous devez spécifier le port que le serveur sera disponible sur : 1433:1433. La première valeur fait référence au port de l’hôte et le second pour le port à l’intérieur du conteneur. Exposer le serveur via le port de l’hôte par défaut 1433 rend plus facile d’accéder à la base de données depuis l’ordinateur hôte. Je vous montrerai comment cela fonctionne une fois que j’ai indiqué ce projet soit opérationnel.

Lorsqu’il est temps pour exécuter cet docker-compose en dehors de Visual Studio, je dois également exposer des ports à partir du service dataapidocker. Les outils de Visual Studio créé un deuxième fichier docker-compose, docker-compose.override.yml, utilisé par Visual Studio pendant le développement. Dans ce fichier sont quelques mappages supplémentaires, y compris les mappage de ports (ports : - 80) pour le service dataapidocker. Par conséquent, pour l’instant je laisse les outils ce qui me permet de parcourir le site Web lors du débogage dans Visual Studio à votre place.

Définition d’un Volume distinct pour les données persistantes

Il est encore davantage de travail à faire docker-compose, toutefois. Avec la description, les données et les bases de données sont créées dans le même conteneur que le serveur SQL Server est en cours d’exécution. Cela est probablement pas un problème pour tester si une base de données clair est souhaitée pour chaque test. Il est préférable, toutefois, pour conserver les données séparément. Il existe plusieurs façons pour ce faire, mais je vais utiliser ce que l'on appelle un volume de données. Examinons mon billet de blog sur bit.ly/2pZ7dDb, où j’aborde en détail sur les volumes de données et montrent comment elles sont conservées même si vous arrêtez ou supprimez le conteneur en cours d’exécution SQL Server.

Vous pouvez laisser les instructions dans le fichier docker-compose pour spécifier un volume pour rendre persistantes les données séparément dans le conteneur de SQL Server, comme je l’ai fait Figure 2. Un volume n’est pas identique à un conteneur, donc il n’est pas un autre service. Au lieu de cela, vous créez une nouvelle clé appelée volumes qui est un frère aux services. Au sein de la clé, vous fournissez votre propre nom pour le volume (j’ai appelé le mien mssql-server-julie-data). Il n’existe aucune valeur associée à cette clé. Un volume d’affectation de noms de cette façon vous permet de réutiliser avec d’autres conteneurs si vous avez besoin. Vous trouverez plus d’informations sur les volumes dans la référence de Docker pour docker-compose à docs.docker.com/compose/compose-file ou, pour plus d’informations, consultez cours de Pluralsight de Elton Stoneman sur les données avec état avec Docker ( pluralsight.pxf.io/yoLYv).

Figure 2 définition d’un Volume de données dans Docker-Compose

services:
  dataapidocker: [etc]
  db:
    image: mcr.microsoft.com/mssql/server
    volumes:
      - mssql-server-julie-data:/var/opt/mssql/data
    environment:
      SA_PASSWORD: "${DB_PW}"
      ACCEPT_EULA: "Y"
    ports:
      - "1433:1433"
volumes:
  mssql-server-julie-data: {}

Notez que le mappage de la base de données a également un nouveau mappage pour les volumes. Ce mappage contient un élément de la séquence dans laquelle mappée le volume nommé à un chemin d’accès cible dans le conteneur source où les fichiers journaux et les données seront stockées.

Configuration de la chaîne de connexion pour le serveur SQL en conteneur

En guise de rappel, dans la version précédente de l’application, j’ai laissé une chaîne de connexion à SQL Server LocalDB dans appsettings. Development.JSON pour les heures que je veux tester l’API en cours d’exécution dans l’élément Kestrel ou le serveur IIS local.  La chaîne de connexion à la base de données SQL Azure, nommé ConnectionStrings:MagsConnectionMssql, est stockée dans une variable d’environnement dans le fichier Dockerfile de l’API, juste au-dessus de la section qui définit l’image de build. Voici les premières lignes de ce fichier Dockerfile. La chaîne de connexion a des espaces réservés pour l’id utilisateur et le mot de passe. L’id d’utilisateur est toujours dans le fichier Dockerfile, car j’ai a été de se concentrer sur le masquage du mot de passe et n’avez pas encore supprimé :

FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
ENV ConnectionStrings:MagsConnectionMssql="Server=[Azure SQL endpoint];
    Initial Catalog=DP0419Mags;Persist Security Info=False;
    User ID=ENVID;Password=ENVPW;MultipleActiveResultSets=False;
    Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
ENV DB_UserId="lerman"
FROM microsoft/dotnet:2.2-sdk AS build

Cette chaîne de connexion peut facilement être déplacée vers le docker-compose.yml et contrôlée par des moyens externes. Méthode de Configuration de démarrage de l’API remplace les espaces réservés utilisateur et mot de passe avec les valeurs des variables d’environnement fourni, y compris le mot de passe DB_PW que j’ai stockée dans le fichier the.env dont le contenu ressembler à ceci :

DB_PW=eiluj

Le fichier .env et sa valeur DB_PW seront lues par docker-compose et passé dans le conteneur pour le fichier Dockerfile lire et mettre à disposition de l’application. Au final, je suis supprime la chaîne de connexion et les variables de DB_UserId Dockerfile.

Mais cette chaîne de connexion a été pour SQL Azure. Maintenant, je dois modifier sa valeur pour pointer vers le conteneur de SQL Server :

ENV ConnectionStrings:MagsConnectionMssql
  "Server=db;Database=DP0419Mags;User=sa;Password=ENVPW;"

J’utilise le même nom de variable, car c’est ce que Startup.ConfigureServices attend. Ce qui est intéressant est que l’exécution du conteneur comprenne le nom de la base de données service défini dans docker-composer en tant que le nom du serveur. Par conséquent, dans la chaîne de connexion, je peux spécifier le serveur en tant que base de données. L’utilisateur par défaut que l’image mssql/serveur utilise pour configurer le serveur étant sa, j’ai codé que directement dans la chaîne de connexion, c’est pourquoi j’ai besoin n’est plus une variable d’environnement pour l’id d’utilisateur. Toutefois, j’utilise toujours un espace réservé, ENVPW, pour la valeur de mot de passe.

Comme avec l’exemple de la colonne précédente, l’espace réservé sera finalement remplacé par la valeur de la variable d’environnement DB_PW. Voici ce que le code se présente désormais comme qui lit la chaîne de connexion et la variable DB_PW, puis met à jour la chaîne de connexion avant de le transmettre au fournisseur SQL Server :

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  var config = new StringBuilder(
    Configuration["ConnectionStrings:MagsConnectionMssql"]);
  string conn = config.Replace("ENVPW", Configuration["DB_PW"])
                      .ToString();
  services.AddDbContext<MagContext>(options => options.UseSqlServer(conn));
}

Voici toutes les modifications nécessaires. Maintenant nous allons déboguer et voir ce qui se passe.

Débogage avec le conteneur de base de données

Assurez-vous que le docker-compose projet est le projet de démarrage dans la solution et que le bouton de débogage est défini sur Docker Compose, puis appuyez sur F5 pour déboguer l’API.

Si c’est la première fois que vous exécutez l’application de cette façon et que vous avez extrait jamais l’image mssql/serveur, qui sera la première chose à se produire.  L’image de SQL Server n’est pas petit — il s’agit 1,45 Go. Par conséquent, la première fois que vous tirez dessus, soyez patient. Notez qu’il nécessite 2 Go de RAM, par conséquent, veillez à attribuer suffisamment de RAM à votre moteur Docker (dans les paramètres Docker) pour l’exécuter. Même dans ce cas, il s’agit toujours plus rapide que l’installation de SQL Server sur votre ordinateur, et il utilise uniquement les ressources déjà affectées à Docker, pas des ressources sur votre ordinateur hôte. Et une fois l’image n’y figure, il est breezy pour mettre en place un grand nombre d’instances. Un autre avantage est que les mises à jour l’image de base sont extraites en tant que couches petits, pas la chose entière à nouveau. Notez que les images du Kit de développement logiciel et aspnetcore-runtime Microsoft/dotnet se trouvent déjà sur mon système, grâce au travail que j’ai fait dans les colonnes précédentes.

Si vous regardez la sortie de génération, vous verrez que l’application crée le volume de données avant de gérer le conteneur mssql/server : dans le cas présent « gestion » signifie tout d’abord l’extraction à partir de Docker Hub, car c’est nouveau dans mon système. Cet ordre des opérations se produit parce que le serveur étant dépend du volume, le volume obtient prises en charge en priorité. Une fois cela fait, il démarre la création de l’image de l’API si nécessaire et ensuite tourner les conteneurs. Les étapes sont clairement relayés dans la sortie de génération grâce aux outils.

Comme avec les versions précédentes de cette application, les résultats de la méthode GET du contrôleur Magazines sont affichés dans une fenêtre de navigateur.

Explorer les conteneurs créés par docker-compose

Maintenant nous allons voir ce qui se passait avec Docker. Je vais faire que sur la ligne de commande, bien que l’extension Docker pour Visual Studio Code est une autre option froid d’y parvenir.

Tout d’abord, je vais répertorier les images avec les images docker de commande. Si vous êtes familiarisé avec l’utilisation de l’interface CLI Docker, vous pouvez utiliser le plus explicite image ls de commande docker. Comme vous pouvez le voir dans Figure 3, cela indique que l’image mssql est maintenant sur mon ordinateur et qu’une nouvelle version de mon image dataapidocker a été créée, également.

Inspecter les Images
Figure 3 inspecter les Images

Ensuite, je vais vérifier les conteneurs avec docker ps, l’équivalent abrégé de ls de conteneur docker. Cette sortie est large, donc je vous montre la gauche de l’écran ci-dessus la moitié droite dans la moitié Figure 4.

Les conteneurs en cours d’exécution

Les conteneurs en cours d’exécution
Figure 4 les conteneurs en cours d’exécution

Et, enfin, pour voir le volume qui a été créé, qui est maintenant lié au conteneur de base de données, je peux utiliser le lscommand de volume docker, comme indiqué dans Figure 5.

La commande de Volume Docker
Figure 5 la commande de Volume Docker

Notez que les noms de conteneurs et le volume de données sont précédées de la même texte généré par le processus de débogage de Visual Studio en combinaison avec les outils.

N’oubliez pas que j’ai exposées à la base de données à partir du conteneur sur le port de l’hôte 1433 je peux utiliser les outils sur mon ordinateur de développement pour examiner le serveur qui se trouve dans le conteneur de base de données, ainsi que les bases de données dans le volume attaché. Je vais utiliser Azure Data Studio à suivre. Figure 6 montre comment j’ai défini la connexion.

Configuration d’une connexion à ma base de données en conteneur
Figure 6 Configuration d’une connexion à ma base de données en conteneur

Avec la connexion établie, je peux ensuite interagir avec le serveur et ma nouvelle base de données. Figure 7 affiche l’Explorateur de base de données sur la gauche, ainsi que d’une requête et résultats sur la droite.

Interaction avec la base de données en conteneur dans Azure Data Studio
Figure 7 interagir avec la base de données en conteneur dans Azure Data Studio

Les conteneurs de votre application sont prêts pour l’Action

Avoir vos applications encapsulées dans des images Docker rend faciles à déployer les applications et toutes leurs dépendances en tant que conteneurs. Mais pour les débutants de conteneur et les vétérans, je pense que les outils pour développer des applications pour qu’elles soient déjà associés à des images et une orchestration rend en tirant parti des conteneurs donc beaucoup plus simple. Et, dans cette série, je me suis concentrée sur le développement et le débogage local uniquement. Après la partie 2, j’ai publié un billet de blog sur le déploiement de la solution d’image unique vers Azure de test à bit.ly/2CR40x3. Cette solution stocke ses données dans la base de données SQL Azure et exécuter le conteneur de test à l’aide d’Azure Container Instances. J’ai également écrit un billet de blog sur la publication de l’image de dataapidocker à partir de cet article à Docker Hub et de puis qui héberge la solution complète dans une machine virtuelle de Linux sur Azure, qui est une autre façon excellente pour tester vos conteneurs orchestrées. Vous pouvez trouver ce billet de blog à bit.ly/2VBaN8M.


Julie Lermanest directeur régional Microsoft, Microsoft MVP, coach équipe de logiciel et consultant qui habite dans les collines du Vermont. Vous pouvez elle partage son savoir-faire sur l’accès aux données et d’autres sujets à des groupes d’utilisateurs et des conférences dans le monde entier. À l’adresse thedatafarm.com et est l’auteur de « Programming Entity Framework », ainsi qu’à un Code First et une édition DbContext, à partir d’o ' Reilly Media. Vous pouvez la suivre sur Twitter : @julielerman et consulter ses cours Pluralsight sur bit.ly/PS-Julie.

Merci aux experts techniques suivants d'avoir relu cet article : Elton Stoneman (Docker), Travis Wright (Microsoft)


Discuter de cet article sur le forum MSDN Magazine