Tutoriel officiel pour apprendre systématiquement la traduction japonaise Docker

À propos de cet article

** Traduit par ** getting-started : https://github.com/docker/getting-started/tree/6190776cb618b1eb3cfb21e207eefde511d13449

Licence: Apache License 2.0

Bureau Docker

Docker Desktop est un outil permettant de créer et de partager des applications et des microservices conteneurisés. Fonctionne sur Mac OS et Windows.

** Mémo du traducteur japonais **

Pour installer le bureau Docker, allez sur ici et téléchargez-le, ou exécutez la commande suivante pour l'installer à partir de Homebrew Cask. ..

$ brew cask install docker

Ouvrez le bureau Docker pour démarrer le didacticiel. Chaque commande, etc. sera expliquée en détail dans la seconde moitié, veuillez donc découvrir comment le conteneur est créé ici.

Clone

Tout d'abord, clonez le référentiel.

Le projet Getting Started est un référentiel Github simple qui contient tout ce dont vous avez besoin pour créer une image et l'exécuter en tant que conteneur.

$ git clone https://github.com/docker/getting-started.git

Build

Ensuite, créez une image.

Une image Docker est un système de fichiers privé pour les conteneurs. Il fournit tous les fichiers et le code dont le conteneur a besoin.

$ cd getting-started
$ docker build -t docker101tutorial .

Run

Lançons le conteneur.

Lancez un conteneur basé sur l'image créée à l'étape précédente. Lorsque vous lancez le conteneur, vous pouvez lancer l'application à l'aide de ressources isolées en toute sécurité du reste de votre PC.

$ docker run -d -p 80:80 --name docker-tutorial docker101tutorial

Share

Enregistrez et partagez votre image.

L'enregistrement et le partage d'une image sur Docker Hub permettent aux autres utilisateurs de télécharger et de lancer facilement l'image sur n'importe quelle machine souhaitée.

Pour utiliser Docker Hub, vous devez créer un compte Docker.

$ docker tag docker101tutorial michinosuke/docker101tutorial
$ docker push michinosuke/docker101tutorial

docker_01.png

Docker Tutorial

L'accès au conteneur créé dans le didacticiel du bureau Docker lancera un didacticiel Docker plus détaillé.

Accédons à [http: // localhost](http: // localhost).

Commençons avec

À propos de la commande que vous venez d'exécuter

J'ai pu configurer un conteneur pour ce tutoriel.

Tout d'abord, jetons un coup d'œil à la commande que vous venez d'exécuter. Je l’ai peut-être oublié, alors je l’écrirai à nouveau.

docker run -d -p 80:80 docker/getting-started

Vous avez peut-être remarqué que certains indicateurs sont utilisés. Chaque drapeau a les significations suivantes.

** Application **

Vous pouvez raccourcir toute la commande en combinant des indicateurs à une seule lettre. Par exemple, la commande ci-dessus peut également être écrite comme suit:

docker run -dp 80:80 docker/getting-started

Tableau de bord Docker

Avant de poursuivre le tutoriel, je vais vous présenter un tableau de bord Docker qui peut afficher une liste de conteneurs fonctionnant sur le PC. Avec le tableau de bord Docker, vous pouvez accéder rapidement aux journaux du conteneur, obtenir la coque à l'intérieur du conteneur et gérer facilement le cycle de vie du conteneur (arrêts et suppressions).

Pour accéder au tableau de bord, allez sur Mac (https://docs.docker.com/docker-for-mac/dashboard/) ou Windows (https://docs.docker.com/docker-for-) Suivez les étapes dans windows / dashboard /). Si vous l'ouvrez maintenant, ce didacticiel devrait être en cours d'exécution. Le nom du conteneur (qui est jolly_bouman ci-dessous) est un nom généré aléatoirement. Donc je pense qu'il est affiché avec un nom différent.

tutorial-in-dashboard.png

Qu'est-ce qu'un conteneur?

J'ai démarré le conteneur, mais qu'est-ce que le conteneur exactement? En termes simples, un conteneur est un autre processus simple isolé de tous les autres processus sur la machine hôte. L'isolement utilise l'espace de noms du noyau et les groupes C, une fonctionnalité qui a longtemps été utilisée sous Linux. Docker a travaillé pour rendre ces fonctionnalités familières et faciles à utiliser.

Qu'est-ce qu'une image de conteneur?

Utilisez un système de fichiers isolé lors de l'exécution du conteneur. Ce système de fichiers provient de l'image du conteneur. L'image contient le système de fichiers du conteneur, donc toutes les dépendances, paramètres, scripts, binaires, etc. nécessaires pour exécuter l'application doivent être inclus dans l'image. L'image contient également des paramètres de conteneur tels que des variables d'environnement, des commandes de démarrage par défaut et d'autres métadonnées.

Nous parlerons plus en détail des calques d'image, des meilleures pratiques et plus tard.

** Informations **

Si vous connaissez chroot, considérez le conteneur comme une extension de chroot. Le système de fichiers est simplement importé de l'image. Cependant, le conteneur a une fonction d'isolation plus forte que "chroot".

Présentation des applications à utiliser

À partir de là, nous continuerons à utiliser une application de gestion de liste simple qui s'exécute sur Node.js. Peu importe si vous ne connaissez pas Node.js. Aucune connaissance de JavaScript n'est requise.

Supposons que l'équipe de développement soit très petite et crée une application simple pour montrer MVP (Minimum Practical Product). Vous n'avez pas à réfléchir à la façon dont cela fonctionne pour de grandes équipes ou plusieurs développeurs, créez simplement une application pour montrer comment cela fonctionne et ce que vous pouvez faire.

todo-list-sample.png

Obtenir l'application

Avant de pouvoir exécuter l'application, vous devez mettre le code source de l'application sur votre PC. Dans un vrai projet, je pense qu'il est courant de cloner à partir d'un référentiel. Cependant, dans ce tutoriel, nous avons créé un fichier ZIP contenant l'application, nous allons donc l'utiliser.

  1. Après [Télécharger le fichier ZIP](http: //localhost/assets/app.zip), ouvrez le fichier ZIP et décompressez-le.

  2. Après la décompression, ouvrez le projet dans n'importe quel éditeur. Si l'éditeur n'est pas installé, utilisez le code Visual Studio (https://code.visualstudio.com/). Vous devriez voir package.json et deux sous-répertoires ( src et spec).

ide-screenshot.png

Créez une image de conteneur pour votre application

Utilisez Dockerfile pour créer votre application. Dockerfile est un script d'instructions basé sur du texte utilisé pour créer des images de conteneur. Si vous avez déjà créé un Dockerfile, vous constaterez peut-être que le Dockerfile ci-dessous est défectueux. Nous en reparlerons plus tard.

  1. Créez un Dockerfile avec le contenu suivant dans le répertoire contenant package.json.
FROM node:12-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]

Vérifiez si le Dockerfile a une extension telle que .txt. Certains éditeurs ajouteront automatiquement une extension, ce qui peut entraîner une erreur à l'étape suivante.

  1. Sinon, ouvrez un terminal et accédez au répertoire app où se trouve le Dockerfile. Construisons l'image du conteneur en utilisant la commande docker build.
docker build -t getting-started .

Cette commande utilise un Dockerfile pour créer une nouvelle image de conteneur. Vous avez peut-être remarqué que de nombreuses "couches" ont été installées. La raison en est que j'ai demandé au constructeur de commencer par l'image node: 12-alpine. Cependant, l'image n'était pas sur mon PC, j'ai donc dû la télécharger.

Une fois l'image téléchargée, j'ai copié l'application et utilisé yarn pour installer les dépendances de l'application. L'instruction CMD spécifie la commande par défaut à exécuter lorsque le conteneur est démarré à partir de cette image.

Enfin, le drapeau -t marque l'image. Pensez-y comme donnant à l'image un nom convivial. Nous avons nommé l'image «Getting-started» afin que vous puissiez vous y référer lorsque vous démarrez le conteneur.

Le . à la fin de la commande docker build indique que Docker recherchera le Dockerfile dans le répertoire courant.

Lancer le conteneur d'application

Maintenant que nous avons l'image, exécutons l'application. Pour ce faire, utilisez la commande docker run. (Vous rappelez-vous l'avoir utilisé une fois?)

  1. Démarrez le conteneur à l'aide de la commande docker run et spécifiez le nom de l'image que vous venez de créer.
docker run -dp 3000:3000 getting-started

Rappelez-vous les indicateurs -d et -p? J'ai démarré le nouveau conteneur en mode détaché (exécution en arrière-plan) et mappé le port 3000 sur l'hôte au port 3000 sur le conteneur. Si vous n'effectuez pas de mappage de port, vous ne pourrez pas accéder à l'application.

  1. Après quelques secondes, essayez d'ouvrir http: // localhost: 3000 dans votre navigateur Web. Vous devriez voir l'application.

todo-list-empty.png

  1. Essayez d'ajouter un ou deux éléments et voyez s'ils fonctionnent comme prévu. Vous pouvez vérifier l'achèvement de l'élément ou supprimer l'élément. Le frontal a enregistré l'élément dans le back-end. C’est très facile, non?

À ce stade, vous disposez d'une application de gestion de liste Todo avec certains éléments. Apprenons maintenant à gérer les conteneurs avec quelques modifications.

Si vous regardez le tableau de bord Docker, vous pouvez voir que deux conteneurs sont en cours d'exécution. (Ce tutoriel lui-même et le conteneur d'application viennent d'être lancés.)

dashboard-two-containers.png

emballer

Dans ce chapitre, vous avez appris les bases de la création d'une image de conteneur et créé un Dockerfile pour celle-ci. Après avoir créé l'image, j'ai démarré le conteneur et touché l'application en cours d'exécution.

Ensuite, apprenons à modifier l'application et à mettre à jour l'application en cours d'exécution avec une nouvelle image. En cours de route, vous apprendrez également quelques commandes utiles.

Mettre à jour l'application

En guise de petite demande de fonctionnalité, l'équipe produit m'a demandé de modifier le "texte vide" qui apparaît lorsqu'un élément de la liste ToDo n'existe pas. Je veux le changer comme suit.

You have no todo items yet! Add one above!

C'est facile? Nous allons faire ce changement.

Mettre à jour le code source

  1. Réécrivez la ligne 56 de src / static / js / app.js pour utiliser le nouveau texte.
- <p className="text-center">No items yet! Add one above!</p>
+ <p className="text-center">You have no todo items yet! Add one above!</p>
  1. Créez l'image mise à jour à l'aide de la même commande que vous avez utilisée précédemment.
docker build -t getting-started .
  1. Démarrez un nouveau conteneur avec le code mis à jour.
docker run -dp 3000:3000 getting-started

Ah! Je pense que j'ai eu cette erreur. (L'ID est différent)

docker: Error response from daemon: driver failed programming external connectivity on endpoint laughing_burnell 
(bb242b2ca4d67eba76e79474fb36bb5125708ebdabd7f45c8eaf16caaabde9dd): Bind for 0.0.0.0:3000 failed: port is already allocated.

Qu'est-il arrivé? L'ancien conteneur fonctionnait, donc je n'ai pas pu lancer le nouveau. La raison de ce problème est qu'un port particulier ne peut être écouté que par un seul processus (y compris le conteneur) sur le PC où se trouve le conteneur, mais le conteneur utilisait déjà le port 3000. Vous devez supprimer l'ancien conteneur pour éliminer cette erreur.

Remplacer l'ancien conteneur

Pour supprimer le conteneur, vous devez d'abord l'arrêter. Une fois arrêté, vous pouvez le supprimer. Il existe deux façons de supprimer un ancien conteneur. Veuillez choisir la méthode que vous aimez.

Supprimer le conteneur avec la CLI

  1. Utilisez la commande docker ps pour obtenir l'ID du conteneur.
docker ps
  1. Utilisez la commande docker stop pour arrêter le conteneur.
# <the-container-id>Remplacez-le par l'ID obtenu avec la commande docker ps.
docker stop <the-container-id>
  1. Après avoir arrêté le conteneur, supprimez-le avec la commande docker rm.
docker rm <the-container-id>

** Application **

Vous pouvez arrêter et supprimer un conteneur avec une seule commande en ajoutant le drapeau "force" à la commande docker rm.

Exemple) docker rm -f <the-container-id>

Supprimer le conteneur à l'aide du tableau de bord Docker

Vous pouvez supprimer un conteneur en seulement deux clics en ouvrant le tableau de bord Docker. C'est beaucoup plus facile que de trouver et de supprimer l'ID du conteneur.

  1. Ouvrez le tableau de bord et passez la souris sur le conteneur de l'application pour voir la liste des actions sur la droite.

  2. Cliquez sur le bouton Corbeille pour supprimer le conteneur.

  3. Confirmez la suppression et vous avez terminé.

dashboard-removing-container.png

Lancez l'application mise à jour

  1. Lancez l'application mise à jour.
docker run -dp 3000:3000 getting-started
  1. Rechargez le navigateur sur [http: // localhost: 3000](http: // localhost: 3000) et vous verrez le texte mis à jour.

todo-list-updated-empty-text.png

emballer

Bien que j'aie pu mettre à jour l'application, il y avait deux choses à noter.

Avant de parler de permanence, apprenons à partager une image avec les autres.

Partagez l'appli

Maintenant que vous avez créé l'image, partageons-la. Pour partager une image Docker, vous devez utiliser le registre Docker. Le registre par défaut est Docker Hub, et les images que j'ai utilisées jusqu'à présent ont également été prises à partir de là.

Créer un référentiel

Pour pousser une image, vous devez d'abord créer un référentiel sur Docker Hub.

  1. Accédez à Docker Hub (https://hub.docker.com/) et connectez-vous si nécessaire.

  2. Cliquez sur le bouton ** Créer un référentiel **.

  3. Spécifiez «Getting-started» comme nom du référentiel. Assurez-vous que le niveau de publication est «Public».

  4. Cliquez sur le bouton ** Créer **.

Si vous regardez le côté droit de la page, vous verrez la commande Docker. Voici un exemple de la commande que vous devez exécuter pour pousser vers ce référentiel.

push-command.png

Poussez l'image

  1. Essayez d'exécuter la commande push depuis Docker Hub sur la ligne de commande. Notez que l'espace de noms de la commande doit être le vôtre, pas "docker".
$ docker push docker/getting-started
The push refers to repository [docker.io/docker/getting-started]
An image does not exist locally with the tag: docker/getting-started

Pourquoi a-t-il échoué? Cette commande push a recherché une image nommée docker / getting-started, mais n'a pas pu la trouver. Je ne trouve pas l'image en exécutant docker image ls. Pour résoudre ce problème, les images que vous avez créées jusqu'à présent doivent être balisées pour leur donner un nom différent.

** Mémo du traducteur japonais **

Il y a des «images docker» dans la commande qui fonctionnent de la même manière que «image docker ls». Cela est dû à la réorganisation de la commande Docker, et docker image ls est plus récent et recommandé. Dans ce didacticiel, nous verrons d'autres commandes qui auront le même comportement à l'avenir.

Référence: https://qiita.com/zembutsu/items/6e1ad18f0d548ce6c266

  1. Connectez-vous à Docker Hub à l'aide de la commande docker login -u YOUR-USER-NAME.

  2. Utilisez la commande docker tag pour donner un nouveau nom à l'image de" mise en route ". Remplacez YOUR-USER-NAME par votre identifiant Docker.

docker tag getting-started YOUR-USER-NAME/getting-started
  1. Essayez à nouveau d'exécuter la commande push. Je n'ai ajouté aucune balise au nom de l'image, donc si vous l'avez copiée et collée à partir de Docker Hub, supprimez la partie tagname. Si vous ne spécifiez pas de balise, Docker utilise la balise «latest».
docker push YOUR-USER-NAME/getting-started

Exécutez l'image sur une nouvelle instance

Maintenant que nous avons construit l'image et l'avons poussée dans le registre, exécutons cette image de conteneur sur une nouvelle instance. Pour cela, utilisez Play with Docker.

  1. Ouvrez Play with Docker (http://play-with-docker.com/) dans votre navigateur.

  2. Connectez-vous avec votre compte Docker Hub.

  3. Une fois connecté, cliquez sur le lien "\ + AJOUTER UNE NOUVELLE INSTANCE" dans la barre de gauche (si vous ne le voyez pas, étendez votre navigateur un peu sur le côté). Après quelques secondes, une fenêtre de terminal apparaîtra sur votre navigateur.

pwd-add-new-instance.png

  1. Lancez l'application poussée sur le terminal.
docker run -dp 3000:3000 YOUR-USER-NAME/getting-started

Une fois l'image acquise, elle démarre.

Vous verrez un badge indiquant 5.3000, et cliquez dessus pour voir l'application que vous avez modifiée. Vous l'avez fait, pas vous. Si vous ne voyez pas le badge qui dit 3000, cliquez sur le bouton Ouvrir le port et entrez 3000.

emballer

Dans ce chapitre, vous avez appris à transmettre et à partager des images dans le registre. Ensuite, je suis entré dans une nouvelle instance et j'ai lancé l'image poussée. Ceci est courant dans les pipelines CI, où une fois que le pipeline crée une image et la pousse vers le registre, la dernière version de l'image est disponible en production.

Maintenant que vous l'avez compris, revenons au dernier sujet du chapitre précédent. Un problème est survenu lorsque j'ai redémarré l'application, tous les éléments de la liste À faire étaient supprimés. Bien sûr, ce n'est pas une bonne UX (expérience utilisateur), alors apprenons à conserver les données après un redémarrage.

Persister la base de données

Comme vous l'avez peut-être remarqué, la liste ToDo est initialisée chaque fois que vous démarrez le conteneur. Pourquoi. Explorons un peu plus en profondeur le fonctionnement du conteneur.

Système de fichiers de conteneurs

Lorsque le conteneur est lancé, différentes couches de l'image sont utilisées pour le système de fichiers. De plus, chaque conteneur réserve un "espace de travail" pour créer / mettre à jour / supprimer. Les modifications n'affectent pas un autre conteneur, même si la même image est utilisée.

Regarde

Pour le voir en action, commençons deux conteneurs et créons un fichier pour chacun. Si vous créez un fichier dans un conteneur, vous constaterez que le fichier n'est pas valide dans l'autre conteneur.

Démarrez un conteneur ubuntu qui crée un / data.txt avec des nombres aléatoires de 1,1 à 10000.

docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"

Si vous êtes familier avec les commandes, vous verrez que vous lancez le shell Bash et appelez deux commandes (en utilisant && pour cela). Dans la première partie, j'écris un nombre aléatoire dans / data.txt. La deuxième commande continue simplement de surveiller le fichier pour maintenir le conteneur en cours d'exécution.

  1. Allons à l'intérieur du conteneur avec exec pour voir ce qui est sorti. Vous pouvez le faire en ouvrant le tableau de bord et en cliquant sur la première action de l'image en cours d'exécution ubuntu.

dashboard-open-cli-ubuntu.png

Vous pouvez voir que le shell s'exécute à l'intérieur du conteneur ubuntu. Exécutez la commande suivante pour afficher le contenu de / data.txt. Une fois que vous avez fait cela, fermez à nouveau le terminal.

cat /data.txt

Si vous voulez faire la même chose en utilisant la ligne de commande, utilisez docker exec. Après avoir obtenu l'ID du conteneur avec docker ps, vous pouvez obtenir le contenu du fichier avec la commande suivante.

docker exec <container-id> cat /data.txt

Vous devriez voir un nombre aléatoire.

  1. Lancez un autre conteneur ubuntu et vérifiez si le même fichier existe.

docker run -it ubuntu ls /

Il n'y a pas de data.txt. Il a été écrit dans l'espace de travail du premier conteneur.

  1. Supprimez le premier conteneur à l'aide de la commande docker rm -f.

Volume du conteneur

A présent, nous savons que le conteneur commence par définir l'image au démarrage. Un conteneur peut créer, mettre à jour et supprimer des fichiers, mais il est perdu lorsque le conteneur est supprimé et toutes les modifications sont limitées à ce conteneur. Mais avec les volumes, vous pouvez tous les changer.

Volumes (https://docs.docker.com/storage/volumes/) permet à un chemin de système de fichiers particulier dans un conteneur de se connecter à une machine hôte. Si un répertoire du conteneur est monté, la modification de ce répertoire affectera également la machine hôte. Si vous montez le même répertoire même après avoir redémarré le conteneur, vous pouvez voir le même fichier.

Il existe deux types de volumes. J'utilise les deux, mais utilisons ** volume nommé ** pour le moment.

Persister les données Todo

L'application ToDo stocke les données dans la base de données SQLite située dans / etc / todos / todo.db. Ne vous inquiétez pas si vous ne connaissez pas SQLite. SQLite est une base de données relationnelle simple qui stocke toutes vos données dans un seul fichier. Ce n'est pas la meilleure façon de travailler avec des données volumineuses, mais cela fonctionne pour les petites applications de démonstration. Comment passer à un autre moteur de base de données sera décrit plus loin.

Étant donné que la base de données est un fichier unique, vous devriez être en mesure de conserver ce fichier sur l'hôte afin qu'il puisse être référencé par le conteneur suivant afin que vous puissiez reprendre là où vous vous étiez arrêté. Vous pouvez rendre les données persistantes en créant un volume et en vous connectant au répertoire dans lequel les données sont stockées (également appelé montage). Lorsque le conteneur écrit dans le fichier todo.db, il est conservé sur l'hôte dans le volume.

Pour toucher brièvement, je vais utiliser ** Volume nommé **. Considérez un volume nommé comme un compartiment pour vos données. Docker réserve de l'espace physique sur le disque, il vous suffit donc de vous souvenir du nom du volume. Lorsque vous utilisez un volume, Docker vérifie que vous obtenez les données correctes.

  1. Créez un volume avec la commande docker volume create.
docker volume create todo-db
  1. L'application ToDo que vous avez déjà lancée est en cours d'exécution sans utiliser de volumes persistants, utilisez donc le tableau de bord ou utilisez la commande doker rm -f <id> pour l'arrêter.

  2. Je démarre un conteneur d'application ToDo, ajoutez l'indicateur -v pour spécifier la connexion de volume. Connectez-vous à / etc / todos en utilisant un volume nommé et capturez tous les fichiers.

docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
  1. Après avoir lancé le conteneur, ouvrez l'application et essayez d'ajouter des éléments à votre liste de tâches.

items-added.png

  1. Supprimez le conteneur d'applications ToDo. Utilisez le tableau de bord ou utilisez docker ps pour obtenir l'ID, puis utilisez docker rm -f <id> pour le supprimer.

  2. Démarrez un nouveau conteneur en utilisant la même commande que ci-dessus.

  3. Après avoir confirmé que la liste est affichée, supprimez le conteneur et continuez.

Maintenant que vous savez comment conserver les données.

** Application **

Les volumes nommés et les montages de liaison (plus à ce sujet plus tard) sont deux volumes pris en charge depuis l'installation de Docker, mais il existe également de nombreux plugins de pilote prenant en charge NFS, SFTP, NetApp, etc. Faire. Ceci est très important lors du lancement de conteneurs sur plusieurs hôtes dans un environnement de cluster tel que Swarm ou Kubernetes.

En savoir plus sur le volume

De nombreuses personnes demandent souvent: «Où se trouve l'emplacement réel où Docker stocke les données lors de l'utilisation de volumes nommés? Si vous voulez savoir, vous pouvez utiliser la commande docker volume inspect.

docker volume inspect todo-db
[
    {
        "CreatedAt": "2019-09-26T02:18:36Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": {},
        "Scope": "local"
    }
]

Le «point de montage» est l'emplacement réel où les données sont stockées sur le disque. Notez que la plupart des machines nécessitent des privilèges root pour accéder à ce répertoire depuis l'hôte.

** Accéder aux données de volume directement sur le bureau Docker **

Lors de l'exécution sur le bureau Docker, les commandes Docker s'exécutent en fait à l'intérieur d'une petite machine virtuelle sur la machine. Si vous voulez voir le contenu réel du répertoire Mountpoint, vous devez d'abord aller à l'intérieur de la machine virtuelle.

emballer

À ce stade, j'ai pu créer une application fonctionnelle qui pourrait être redémarrée vivante. Nous espérons montrer à nos investisseurs et les aider à comprendre notre vision.

Cependant, la reconstruction de l'image prend un peu trop de temps chaque fois que vous effectuez une modification. Il existe une meilleure façon d'apporter des changements. Le montage bind (celui auquel j'ai fait allusion plus tôt) est la méthode. Nous allons jeter un coup d'oeil.

Utiliser le montage de liaison

Dans le chapitre précédent, nous avons utilisé des volumes nommés pour conserver la base de données. Les volumes nommés sont utiles si vous souhaitez simplement stocker vos données, car vous n'avez pas à vous soucier de l'emplacement de stockage de vos données.

** Bind Mount ** vous permet de contrôler le point de montage exact sur votre hôte. Il peut également être utilisé pour la persistance des données, mais est souvent utilisé pour fournir des données supplémentaires à un conteneur. Lors du développement d'une application, vous pouvez connecter le code source à un conteneur avec un montage de liaison pour modifier, répondre ou voir les modifications immédiatement.

Pour les applications créées avec Node, nodemon est le meilleur moyen de surveiller les modifications de fichiers et de redémarrer l'application. Des outils similaires existent dans la plupart des langages et des frameworks.

Tableau de comparaison des types de volume

Les montages de liaison et les volumes nommés sont les deux principaux types de volumes du moteur Docker. D'autre part, des pilotes de volume supplémentaires sont disponibles dans d'autres cas d'utilisation (SFTP, Ceph / Getting-started-with-the-docker-rbd-volume-plugin /), NetApp, [S3](https://github.com (/ elementar / docker-s3-volume) etc.).

Named Volumes Lier la monture
Emplacement de l'hôte Docker choisit je choisis
Exemple de montage( -vutilisation) my-volume:/usr/local/data /path/to/data:/usr/local/data
Créer un nouveau volume avec le contenu du conteneur Yes No
Prise en charge du pilote de volume Yes No

Démarrer un conteneur en mode développeur

Commençons un conteneur qui peut être utilisé dans la phase de développement. Procédez comme suit:

Alors, commençons.

  1. Assurez-vous que le conteneur de démarrage que vous avez utilisé jusqu'à présent n'est pas démarré.

  2. Exécutez la commande suivante. Je vais également expliquer ce que vous faites.

docker run -dp 3000:3000 \
    -w /app -v "$(pwd):/app" \
    node:12-alpine \
    sh -c "yarn install && yarn run dev"

Si vous utilisez PowerShell, utilisez la commande suivante.

docker run -dp 3000:3000 `
    -w /app -v "$(pwd):/app" `
    node:12-alpine `
    sh -c "yarn install && yarn run dev"
  1. Vous pouvez voir les journaux avec la commande docker logs -f <container-id>. Si vous regardez cela, vous savez que vous êtes prêt.
docker logs -f <container-id>
$ nodemon src/index.js
[nodemon] 1.19.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Using sqlite database at /etc/todos/todo.db
Listening on port 3000

Lorsque vous avez fini de consulter le journal, vous pouvez quitter avec Ctrl + C.

  1. Apportons maintenant quelques modifications à l'application. Changeons le bouton "Ajouter un élément" dans le fichier src / static / js / app.js en" Ajouter ". C'est sur la ligne 109.
-                         {submitting ? 'Adding...' : 'Add Item'}
+                         {submitting ? 'Adding...' : 'Add'}
  1. Actualisez simplement (ou ouvrez) la page et vous verrez les changements reflétés presque immédiatement dans votre navigateur. Le redémarrage du serveur Node prend quelques secondes, donc si vous obtenez une erreur, essayez d'actualiser après quelques secondes.

updated-add-button.png

  1. Essayez d'apporter d'autres modifications. Une fois cela fait, arrêtez le conteneur puis utilisez docker build -t getting-started . pour créer une nouvelle image.

L'utilisation de montages de liaison est très courante dans le développement local. L'avantage est que la machine de développement n'a pas besoin d'avoir des outils de construction ou des environnements installés. Avec juste la commande docker run, l'environnement de développement est tiré et prêt à fonctionner. Nous parlerons de Docker Compose dans un chapitre ultérieur, qui peut simplifier les commandes avec de nombreux indicateurs.

emballer

Nous avons rendu la base de données permanente afin de pouvoir répondre rapidement aux demandes et aux désirs des investisseurs et des fondateurs. mais attendez un instant. Une excellente nouvelle est arrivée!

** Votre projet sera développé dans le futur. ** **

En vue de sa commercialisation, la base de données doit être migrée vers une base de données plus extensible que SQLite. En termes simples, vous devez utiliser MySQL avec la base de données relationnelle intacte. Mais comment faire fonctionner MySQL? Comment autoriser la communication entre les conteneurs? J'en parlerai dans le prochain chapitre.

Application avec plusieurs conteneurs

Jusqu'à présent, nous avons travaillé avec une application de conteneur. Mais je veux ajouter MySQL à mon application. Une question courante est: "Où dois-je exécuter MySQL? Dois-je l'exécuter dans le même conteneur et le démarrer séparément?" En général, chaque conteneur ne doit faire qu'une seule chose. Il y a plusieurs raisons à cela.

Il y a aussi d'autres raisons. Donc, je vais mettre à jour l'application pour qu'elle fonctionne comme ça.

multi-app-architecture.png

Réseau de conteneurs

N'oubliez pas que les conteneurs s'exécutent indépendamment par défaut et ne savent rien des autres processus ou conteneurs sur la même machine. Alors, comment autorisez-vous un conteneur à communiquer avec d'autres conteneurs? La réponse est ** Réseau **. Vous n'avez pas besoin d'être un ingénieur réseau. N'oubliez pas cette règle.

Lorsque deux conteneurs sont dans le même réseau, ils peuvent communiquer entre eux. La communication n'est possible que si vous êtes sur le même réseau.

Démarrez MySQL

Il existe deux façons de placer un conteneur sur le réseau. Le premier est la méthode d'attribution au début. La seconde consiste à connecter un conteneur existant. Cette fois, créons d'abord le réseau, puis connectons le conteneur MySQL démarré.

  1. Créez un réseau.
docker network create todo-app
  1. Démarrez le conteneur MySQL et connectez-vous au réseau. Il définit également certaines variables d'environnement utilisées pour initialiser la base de données. (Voir le chapitre «Variables d'environnement» dans Liste MySQL Docker Hub)
docker run -d \
    --network todo-app --network-alias mysql \
    -v todo-mysql-data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=secret \
    -e MYSQL_DATABASE=todos \
    mysql:5.7

Si vous utilisez PowerShell, utilisez la commande suivante.

docker run -d `
    --network todo-app --network-alias mysql `
    -v todo-mysql-data:/var/lib/mysql `
    -e MYSQL_ROOT_PASSWORD=secret `
    -e MYSQL_DATABASE=todos `
    mysql:5.7

Vous avez spécifié l'indicateur --network-alias. Cela sera discuté plus tard.

** Informations pour les professionnels **

J'ai utilisé un volume nommé todo-mysql-data et je l'ai monté sur / var / lib / mysql où les données MySQL sont stockées. Cependant, je n'utilise pas la commande docker volume create. Docker a reconnu que nous allions utiliser un volume nommé et a créé le volume automatiquement.

  1. Pour vérifier si la base de données est en cours d'exécution, connectez-vous à la base de données et assurez-vous qu'elle est connectée.
docker exec -it <mysql-container-id> mysql -p

Si un mot de passe vous est demandé, entrez ** secret **. Dans le shell MySQL, affichez la liste des bases de données et assurez-vous que vous disposez de la base de données todos.

mysql> SHOW DATABASES;

Ça devrait ressembler à ça.

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| todos              |
+--------------------+
5 rows in set (0.00 sec)

Vous avez une base de données todos.

Connectez-vous à MySQL

Maintenant que nous avons confirmé que MySQL a démarré, utilisons-le réellement. Mais si vous démarrez un autre conteneur sur le même réseau, comment trouvez-vous le conteneur? (N'oubliez pas que chaque conteneur a une adresse IP différente.)

Pour comprendre cela, utilisez le conteneur nicolaka / netshoot, qui contient des outils utiles pour le dépannage et le débogage des problèmes de réseau.

  1. Lancez un nouveau conteneur en utilisant l'image nicolaka / netshoot. Assurez-vous que vous êtes connecté au même réseau.
docker run -it --network todo-app nicolaka/netshoot
  1. Utilisez la commande dig, qui est un outil DNS pratique à l'intérieur du conteneur. Trouvez l'adresse IP avec le nom d'hôte mysql.
dig mysql

Vous devriez voir quelque chose comme ceci:

; <<>> DiG 9.14.1 <<>> mysql
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32162
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;mysql.             IN  A

;; ANSWER SECTION:
mysql.          600 IN  A   172.23.0.2

;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Tue Oct 01 23:47:24 UTC 2019
;; MSG SIZE  rcvd: 44

Si vous regardez la section "ANSWER SECTION", vous pouvez voir que l'enregistrement A de mysql est 172.23.0.2 (votre adresse IP est susceptible d'avoir une valeur différente). mysql n'est généralement pas un nom d'hôte valide, mais Docker a pu résoudre l'adresse IP d'un conteneur avec un alias réseau de mysql (n'oubliez pas d'utiliser l'indicateur --network-alias " As-tu?).

Cela signifie que même les applications ToDo peuvent communiquer avec la base de données simplement en se connectant à un hôte nommé mysql. Cela n'a jamais été aussi simple.

Exécutez des applications qui utilisent MySQL

L'application ToDo vous permet de définir certaines variables d'environnement qui spécifient les paramètres de connexion MySQL. Les détails sont les suivants.

** Attention **

Il est normal d'utiliser des variables d'environnement pour configurer des connexions dans un environnement de développement, mais leur utilisation dans une application exécutée dans un environnement de production est une pratique ** hautement déconseillée **. Diogo Monica, ancien responsable de la sécurité chez Docker, explique pourquoi excellent article -secret-data /) est écrit.

Une approche plus sûre consiste à tirer parti du support secret fourni par le framework d'orchestration de conteneurs. Dans la plupart des cas, ces fichiers secrets seront montés dans un conteneur en cours d'exécution. De nombreuses applications (y compris les images MySQL et les applications ToDo) prennent également en charge les variables d'environnement avec le suffixe _FILE qui pointent vers des fichiers contenant des fichiers.

Par exemple, si vous définissez la variable MYSQL_PASSWORD_FILE, l'application utilisera le contenu du fichier référencé comme mot de passe de connexion. Veuillez noter que Docker ne prend en charge aucune de ces variables d'environnement. L'application doit savoir comment rechercher des variables d'environnement et obtenir le contenu du fichier.

Maintenant que l'explication est terminée, commençons le conteneur.

  1. Spécifiez chacune des variables d'environnement mentionnées ci-dessus pour permettre au conteneur de se connecter au réseau de votre application.
docker run -dp 3000:3000 \
  -w /app -v "$(pwd):/app" \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:12-alpine \
  sh -c "yarn install && yarn run dev"

Si vous utilisez PowerShell, utilisez la commande suivante.

docker run -dp 3000:3000 `
  -w /app -v "$(pwd):/app" `
  --network todo-app `
  -e MYSQL_HOST=mysql `
  -e MYSQL_USER=root `
  -e MYSQL_PASSWORD=secret `
  -e MYSQL_DB=todos `
  node:12-alpine `
  sh -c "yarn install && yarn run dev"
  1. Si vous regardez les journaux du conteneur (docker logs <container-id>), vous verrez un message indiquant que vous utilisez une base de données MySQL.
# Previous log messages omitted
$ nodemon src/index.js
[nodemon] 1.19.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Connected to mysql db at host mysql
Listening on port 3000
  1. Ouvrez l'application dans votre navigateur et essayez d'ajouter des applications à votre liste de tâches.

  2. Connectez-vous à la base de données MySQL et voyez si l'élément est écrit. Le mot de passe est ** secret **.

docker exec -ti <mysql-container-id> mysql -p todos

Ensuite, dans le shell MySQL, procédez comme suit:

mysql> select * from todo_items;
+--------------------------------------+--------------------+-----------+
| id                                   | name               | completed |
+--------------------------------------+--------------------+-----------+
| c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! |         0 |
| 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome!        |         0 |
+--------------------------------------+--------------------+-----------+

Bien entendu, le contenu du tableau est différent car il contient vos éléments. Mais vous pouvez voir que l'article est stocké ici.

En regardant le tableau de bord Docker, deux conteneurs sont en cours d'exécution. Cependant, rien n'indique qu'ils sont regroupés dans une seule application. Voyons comment améliorer cela.

dashboard-multi-container-app.png

emballer

J'ai pu créer une application qui stocke des données dans une base de données externe qui s'exécute dans un conteneur séparé. J'ai appris un peu plus sur le réseau de conteneurs et appris à utiliser DNS pour découvrir des services.

Cependant, vous pouvez être dépassé par tout ce dont vous avez besoin pour lancer cette application. Vous devez créer un réseau, démarrer un conteneur, spécifier toutes les variables d'environnement, ouvrir des ports, etc. C'est certainement trop difficile à retenir et difficile à dire à quelqu'un.

Dans le chapitre suivant, nous parlerons de Docker Compose. Avec Docker Compose, vous pouvez partager plus facilement votre pile d'applications et la lancer avec une seule commande simple.

Utiliser Docker Compose

Docker Compose a été développé pour faciliter la définition et le partage d'applications multi-conteneurs. Avec Compose, vous pouvez définir un service en créant un fichier YAML et le démarrer ou l'arrêter avec une seule commande.

Le gros avantage de l'utilisation de Compose est que vous pouvez définir une pile d'application dans un fichier et l'enregistrer à la racine de votre référentiel de projet (versionné) afin que n'importe qui puisse facilement contribuer à votre projet. En fait, il existe de nombreux projets de ce type sur GitHub et GitLab.

Allons-y pour la première fois.

Installez Docker Compose

Si Docker Desktop / Toolbox est installé sur votre Windows ou Mac, Docker Compose est déjà installé. Docker Compose est également installé sur l'instance Play-with-Docker. Si vous utilisez une machine Linux, vous devez installer Docker Compose en suivant cette page (https://docs.docker.com/compose/install/).

Une fois l'installation terminée, vous devriez pouvoir vérifier les informations de version en exécutant la commande suivante.

docker-compose version

Créer un fichier de composition

  1. Créez un fichier appelé docker-compose.yml à la racine du projet de votre application.

  2. Dans le fichier Compose, commencez par définir la version du schéma. Dans la plupart des cas, il est préférable d'utiliser la dernière version. Pour obtenir la dernière version et la compatibilité du schéma, consultez Référence du fichier de composition (https://docs.docker.com/compose/compose-file/).

version: 3.7
  1. Ensuite, définissez une liste de services (ou conteneurs) que vous souhaitez exécuter dans le cadre de votre application.
version: "3.7"

services:

Ensuite, déplaçons le service vers un fichier Compose.

Définir le service de l'application

N'oubliez pas, voici les commandes que j'ai utilisées pour définir le conteneur de mon application.

docker run -dp 3000:3000 \
  -w /app -v "$(pwd):/app" \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:12-alpine \
  sh -c "yarn install && yarn run dev"

Si vous utilisez PowerShell, j'ai utilisé une commande comme celle-ci:

docker run -dp 3000:3000 `
  -w /app -v "$(pwd):/app" `
  --network todo-app `
  -e MYSQL_HOST=mysql `
  -e MYSQL_USER=root `
  -e MYSQL_PASSWORD=secret `
  -e MYSQL_DB=todos `
  node:12-alpine `
  sh -c "yarn install && yarn run dev"
  1. Tout d'abord, définissez l'entrée de service et l'image du conteneur. Vous pouvez choisir n'importe quel nom de service. Le nom est automatiquement utilisé comme alias réseau, ce qui facilite la définition des services MySQL.
version: "3.7"

services:
  app:
    image: node:12-alpine
  1. Généralement, les commandes sont écrites près de la définition de «image», mais dans n'importe quel ordre. Maintenant écrivons dans le fichier.
version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
  1. Déplaçons la partie -p 3000: 3000 de la commande vers ports. Ici, Écriture courte est utilisée, mais elle est redondante et [Écriture longue](https: // docs. Vous pouvez également utiliser docker.com/compose/compose-file/#long-syntax-1).
version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
  1. Ensuite, déplacez le répertoire de travail (-w / app) et le mappage de volume (-v "$ (pwd): / app") vers working_dir et volumes. Les volumes sont également écrits sous la forme court et long. Il y a compose-file / # long-syntax-3).

L'un des avantages des définitions de volume Docker Compose est que vous pouvez utiliser un chemin relatif au répertoire actuel.

version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
  1. Enfin, migrez les variables d'environnement à l'aide de la clé environment.
version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

Définir un service MySQL

Définissons maintenant le service MySQL. Les commandes utilisées pour le conteneur sont:

docker run -d \
  --network todo-app --network-alias mysql \
  -v todo-mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=todos \
  mysql:5.7

Si vous utilisez PowerShell, utilisez la commande suivante.

docker run -d `
  --network todo-app --network-alias mysql `
  -v todo-mysql-data:/var/lib/mysql `
  -e MYSQL_ROOT_PASSWORD=secret `
  -e MYSQL_DATABASE=todos `
  mysql:5.7
  1. Tout d'abord, définissez un nouveau service, nommez-le mysql, et il obtiendra automatiquement l'alias du réseau. Spécifions l'image à utiliser.
version: "3.7"

services:
  app:
    # The app service definition
  mysql:
    image: mysql:5.7
  1. Ensuite, spécifiez le mappage de volume. Un volume nommé a été créé automatiquement lorsque vous avez démarré le conteneur avec docker run. Cependant, il n'est pas créé lors du lancement à l'aide de Compose. Définissez le volume avec volume: au niveau supérieur, puis spécifiez le point de montage pour la configuration du service. Si vous spécifiez uniquement le nom du volume, les options par défaut sont utilisées. Cependant, il existe de nombreuses autres options disponibles (https://docs.docker.com/compose/compose-file/#volume-configuration-reference).
version: "3.7"

services:
  app:
    # The app service definition
  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql

volumes:
  todo-mysql-data:
  1. Enfin, spécifiez les variables d'environnement.
version: "3.7"

services:
  app:
    # The app service definition
  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

Le fichier docker-compose.yml terminé ressemble à ceci:

version: "3.7"

services:
  app:
    image: node:12-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

Lancer la pile d'applications

Maintenant que vous avez docker-compose.yml, tout ce que vous avez à faire est de le démarrer.

  1. Tout d'abord, assurez-vous qu'aucune autre copie de app / db n'est en cours d'exécution. (Utilisez docker ps et docker rm -f <ids>.)

  2. Démarrez la pile d'applications à l'aide de la commande docker-compose up. Ajoutez l'indicateur -d à exécuter en arrière-plan.

docker-compose up -d

Lorsque vous l'exécutez, vous devriez voir quelque chose comme ceci:

Creating network "app_default" with the default driver
Creating volume "app_todo-mysql-data" with default driver
Creating app_app_1   ... done
Creating app_mysql_1 ... done

Vous pouvez créer des volumes ainsi que des réseaux. Par défaut, Docker Compose crée automatiquement un réseau de piles d'applications (c'est pourquoi nous ne l'avons pas défini dans le fichier Compose).

** Mémo du traducteur japonais ** --Lorsque l'erreur suivante s'affiche dans docker-compose up

[ERROR] [FATAL] InnoDB: Table flags are 0 in the data dictionary but the flags in file ./ibdata1 are 0x4800!

Il a été corrigé en supprimant le volume avec la commande suivante. Cela peut avoir été causé par l'écriture par erreur de docker-compose.yml dans mysql: latest au début.

docker volume rm app_todo-mysql-data
  1. Jetez un œil aux journaux en utilisant la commande docker-compose logs -f. Vous pouvez voir que les journaux de chaque service sont regroupés en un seul. Ceci est très utile lorsque vous souhaitez voir des problèmes de synchronisation. L'indicateur -f suit le journal, donc le journal généré est sorti en direct.

La sortie réelle ressemble à ceci:

mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
mysql_1  | Version: '5.7.27'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
app_1    | Connected to mysql db at host mysql
app_1    | Listening on port 3000

Le nom du service (en couleur) sur la première ligne permet d'identifier le message. Si vous voulez voir les journaux pour un service particulier, ajoutez le nom du service à la fin de la commande log (par exemple, docker-compose logs -f app).

** Application ** - Attendez la base de données avant de lancer l'application

En fait, lorsque vous démarrez l'application, elle essaiera de se connecter une fois que MySQL sera prêt. Docker ne fournit pas de prise en charge intégrée pour le lancement d'un autre conteneur une fois que le conteneur est entièrement lancé, exécuté et préparé. Pour les projets basés sur des nœuds, vous pouvez utiliser wait-port. Des projets similaires existent dans d'autres langages et frameworks.

  1. Ouvrez l'application et vous devriez la voir en cours d'exécution. Et vous pouvez l'arrêter avec une seule commande.

Vérifiez la pile d'applications sur le tableau de bord Docker

En regardant le tableau de bord Docker, il existe un groupe nommé ** app **. Il s'agit du nom du projet Docker Compose et est utilisé pour regrouper les conteneurs. Par défaut, le nom du projet est le nom du répertoire où se trouve docker-compose.yml.

dashboard-app-project-collapsed.png

Si vous ouvrez la liste déroulante de l'application, vous pouvez voir les deux conteneurs définis dans le fichier de composition. Le nom est « _ _ <numéro en double>». Grâce à cela, il est facile de comprendre quel conteneur est quelle application et quel conteneur est la base de données mysql.

dashboard-app-project-expanded.png

Arrête tout

Tout ce que vous avez à faire est d'exécuter docker-compose down ou de mettre l'ensemble de l'application dans la corbeille du tableau de bord Docker. Le conteneur sera arrêté et le réseau sera supprimé.

** Supprimer le volume **

Par défaut, l'exécution de docker-compose down ne supprime pas le volume nommé dans le fichier de composition. Si vous souhaitez supprimer les volumes, vous devez ajouter l'indicateur --volumes.

Dans le tableau de bord Docker, la suppression de la pile d'applications ne supprime pas le volume.

Une fois arrêté, passez simplement à un autre projet et exécutez docker-compose up pour développer ce projet. C'est très simple, non?

emballer

Dans ce chapitre, vous avez découvert Docker Compose et comment il facilite la définition et le partage d'applications pour plusieurs services. J'ai migré la commande que j'utilisais vers le format Compose approprié et j'ai créé un fichier Compose.

Le tutoriel est également entré dans la phase finale. Cependant, le Dockerfile que j'ai utilisé jusqu'à présent a un gros problème, je voudrais donc couvrir certaines des meilleures pratiques pour la création d'images. Nous allons jeter un coup d'oeil.

Bonnes pratiques de création d'images

Couche d'image

Saviez-vous que vous pouvez voir les composants d'une image? Vous pouvez utiliser la commande docker image history pour voir la commande utilisée pour créer chaque calque contenu dans l'image.

  1. Utilisez la commande docker image history pour examiner les couches de l'image de démarrage que vous avez créée précédemment dans ce didacticiel.
docker image history getting-started

Vous devriez voir quelque chose comme ceci (probablement un ID différent):

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
a78a40cbf866        18 seconds ago      /bin/sh -c #(nop)  CMD ["node" "src/index.j…    0B                  
f1d1808565d6        19 seconds ago      /bin/sh -c yarn install --production            85.4MB              
a2c054d14948        36 seconds ago      /bin/sh -c #(nop) COPY dir:5dc710ad87c789593…   198kB               
9577ae713121        37 seconds ago      /bin/sh -c #(nop) WORKDIR /app                  0B                  
b95baba1cfdb        13 days ago         /bin/sh -c #(nop)  CMD ["node"]                 0B                  
<missing>           13 days ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B                  
<missing>           13 days ago         /bin/sh -c #(nop) COPY file:238737301d473041…   116B                
<missing>           13 days ago         /bin/sh -c apk add --no-cache --virtual .bui…   5.35MB              
<missing>           13 days ago         /bin/sh -c #(nop)  ENV YARN_VERSION=1.21.1      0B                  
<missing>           13 days ago         /bin/sh -c addgroup -g 1000 node     && addu…   74.3MB              
<missing>           13 days ago         /bin/sh -c #(nop)  ENV NODE_VERSION=12.14.1     0B                  
<missing>           13 days ago         /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B                  
<missing>           13 days ago         /bin/sh -c #(nop) ADD file:e69d441d729412d24…   5.59MB   

Chaque calque représente un calque de l'image. Sur cet écran, la base de l'image est affichée en bas et la dernière couche est affichée en haut. Cela peut vous aider à voir rapidement chaque calque et à localiser de grandes images.

  1. Avez-vous remarqué que certaines lignes ont été omises? Vous pouvez obtenir une sortie complète en ajoutant l'indicateur --no-trunc. (Il est intéressant d'obtenir une sortie non abrégée avec des indicateurs omis, n'est-ce pas?)
docker image history --no-trunc getting-started

Cache de couche

Nous avons en fait vu les couches, ce qui est une histoire très importante lorsqu'il s'agit de réduire le temps de construction des images de conteneurs.

Après avoir changé de couche, toutes les couches en aval doivent être régénérées.

Jetons un coup d'œil au Dockerfile que nous utilisions à nouveau.

FROM node:12-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]

En revenant à la sortie de l'historique de l'image, nous pouvons voir que chaque commande du Dockerfile est une nouvelle couche de l'image. Vous vous souvenez peut-être que les dépendances de fil ont été réinstallées lorsque vous avez apporté des modifications à l'image. Y'a t'il un moyen d'arranger cela? Il est ridicule d'installer les mêmes dépendances à chaque fois que vous créez.

Pour résoudre ce problème, vous devez reconstruire le Dockerfile pour mettre en cache les dépendances. Pour les applications basées sur des nœuds, les dépendances sont définies dans le fichier package.json. Cela signifie que si vous copiez d'abord uniquement ce fichier, les autres fichiers seront copiés une fois les dépendances installées. Ainsi, les dépendances de fil ne seront recréées que si vous modifiez package.json. N'est-ce pas génial?

  1. Mettez à jour le Dockerfile pour que le package.json soit copié en premier, les dépendances sont installées, puis les autres fichiers sont copiés.
FROM node:12-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
CMD ["node", "src/index.js"]
  1. Créez un fichier appelé .dockerignore dans le même dossier que Dockerfile et écrivez le contenu suivant.
node_modules

Avec le fichier .dockerignore, vous pouvez sélectionner et copier uniquement les fichiers dont vous avez besoin pour votre image. Voir ici (https://docs.docker.com/engine/reference/builder/#dockerignore-file) pour plus d'informations. Dans ce cas, le dossier node_modules sera exclu dans le second COPY. Sinon, il sera écrasé par le fichier généré par la commande RUN. Pour plus d'informations sur les raisons pour lesquelles cette méthode est recommandée pour les applications Node.js et d'autres bonnes pratiques, consultez Node Web Apps dans Docker (https://nodejs.org/en/docs/guides/). Voir nodejs-docker-webapp /).

  1. Construisez une nouvelle image avec docker build.
docker build -t getting-started .

Vous devriez voir quelque chose comme ceci:

Sending build context to Docker daemon  219.1kB
Step 1/6 : FROM node:12-alpine
---> b0dc3a5e5e9e
Step 2/6 : WORKDIR /app
---> Using cache
---> 9577ae713121
Step 3/6 : COPY package.json yarn.lock ./
---> bd5306f49fc8
Step 4/6 : RUN yarn install --production
---> Running in d53a06c9e4c2
yarn install v1.17.3
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 10.89s.
Removing intermediate container d53a06c9e4c2
---> 4e68fbc2d704
Step 5/6 : COPY . .
---> a239a11f68d8
Step 6/6 : CMD ["node", "src/index.js"]
---> Running in 49999f68df8f
Removing intermediate container 49999f68df8f
---> e709c03bc597
Successfully built e709c03bc597
Successfully tagged getting-started:latest

Vous pouvez voir que toutes les couches ont été reconstruites. J'ai fait un gros changement dans le Dockerfile, donc il n'y a plus de problème.

  1. Modifiez le fichier src / static / index.html (changez le contenu de <title> en "The Awesome Todo App").

  2. Reconstruisez l'image Docker avec docker build -t getting-started .. Cette fois, ce que vous voyez devrait changer un peu et ressembler à ceci:

Sending build context to Docker daemon  219.1kB
Step 1/6 : FROM node:12-alpine
---> b0dc3a5e5e9e
Step 2/6 : WORKDIR /app
---> Using cache
---> 9577ae713121
Step 3/6 : COPY package.json yarn.lock ./
---> Using cache
---> bd5306f49fc8
Step 4/6 : RUN yarn install --production
---> Using cache
---> 4e68fbc2d704
Step 5/6 : COPY . .
---> cccde25a3d9a
Step 6/6 : CMD ["node", "src/index.js"]
---> Running in 2be75662c150
Removing intermediate container 2be75662c150
---> 458e5c6f080c
Successfully built 458e5c6f080c
Successfully tagged getting-started:latest

Vous avez remarqué que la construction est très rapide. Vous pouvez également voir que les étapes 1 à 4 incluent toutes «Utilisation de la caisse». Vous êtes maintenant prêt à utiliser le cache de compilation. Il est très rapide de pousser, d'extraire et de mettre à jour des images.

Construction en plusieurs étapes

Je n'entrerai pas trop dans les détails dans ce didacticiel, mais les constructions en plusieurs étapes sont un outil ridiculement puissant pour vous aider à créer des images en utilisant plusieurs étapes. Il présente les avantages suivants:

Exemples Maven et Tomcat

Lors de la création d'une application Java, vous avez besoin d'un JDK pour compiler le code source en code octet Java. Cependant, le JDK n'est pas nécessaire dans un environnement de production. Vous pouvez également utiliser des outils tels que Maven ou Gradle pour créer votre application. Ceux-ci ne sont pas non plus nécessaires pour l'image finale. C'est là que les versions en plusieurs étapes sont utiles.

FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package

FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps 

Dans cet exemple, nous allons construire Java en utilisant Maven dans la première étape nommée build. La deuxième étape, commençant par FROM tomcat, copie les fichiers de l'étape build. L'image finale n'est que la dernière étape créée (remplacée par le drapeau --target).

Exemple de réaction

Lors de la création d'une application React, vous avez besoin d'un environnement Node qui compile le code JS (généralement JSX), les feuilles de style SASS, etc. en HTML statique, JS et CSS. Si vous n'avez pas besoin de rendu côté serveur, vous n'avez pas besoin d'un environnement Node pour créer votre environnement de production. Ensuite, tout ce que vous avez à faire est de placer les ressources statiques dans un conteneur Nginx statique.

FROM node:12 AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build

FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html

Ici, nous construisons (maximisons le cache de couches) en utilisant l'image node: 12, puis nous copions la sortie dans le conteneur Nginx. C'est mieux, non?

emballer

Avec un peu de compréhension de la façon dont l'image est structurée, l'image se construit plus rapidement et vous permet de placer moins de changements. Les builds en plusieurs étapes contribuent également à améliorer la sécurité du conteneur final en réduisant la taille globale de l'image et en découplant les dépendances de build et d'exécution.

Que faire ensuite

Le tutoriel est terminé, mais il y a plus à apprendre sur les conteneurs. Je n'entrerai pas dans les détails ici, mais jetons un coup d'œil.

Orchestration de conteneurs

L'exécution d'un conteneur dans un environnement de production peut être difficile. Je ne veux pas me connecter à la machine et exécuter docker run ou docker-compose up. Pourquoi? Alors, que se passe-t-il si le conteneur meurt? Comment évoluer sur plusieurs machines? L'orchestration de conteneurs résout ce problème. Des outils comme Kubernetes, Swarm, Nomad et ECS résolvent tous ce problème de manière légèrement différente.

L'idée générale est d'avoir un "manager" qui reçoit ** l'état attendu **. Cet état est comme "Je veux que vous démarriez deux instances d'application Web et ouvrez le port 80". Le gestionnaire surveille toutes les machines du cluster et délègue le travail aux «travailleurs». Le gestionnaire surveille les modifications (par exemple lorsque le conteneur est arrêté) et agit ensuite pour que ** l'état réel ** reflète l'état attendu.

Projet d'infrastructure de Cloud Native Computing

CNCF (Cloud Native Infrastructure Project) est une variété de projets open source indépendants des fournisseurs, notamment Kubernetes, Prometheus, Envoy, Linkerd, NATS et plus encore. Vous pouvez voir le Projet créé ici et le [diagramme CNCF] global (https://landscape.cncf.io/) ici. Je vais. Beaucoup de ces projets vous aideront à résoudre des problèmes tels que la surveillance, la journalisation, la sécurité, le registre d'images et la messagerie.

Donc, si vous n'êtes pas sûr de l'ensemble du conteneur et du développement de l'application native cloud, veuillez l'utiliser. Rejoignez la communauté, posez des questions et étudiez. Nous attendons votre participation avec impatience.

Recommended Posts

Tutoriel officiel pour apprendre systématiquement la traduction japonaise Docker
[Introduction à Docker] Tutoriel officiel (traduction en japonais)
Docker Gradle Quick Reference Traduction japonaise
Traduction japonaise du backend Docker Desktop WSL 2
tutoriel docker (mémo)
settings.gradle traduction en japonais
Traduction en japonais de Gradle
build.gradle traduction en japonais
Indiquez comment apprendre de Docker à AKS sur AWS