Cet article est une traduction japonaise du didacticiel Docker Desktop.
Ceci est un tutoriel officiel, vous pouvez donc étudier avec confiance et efficacité.
Il couvre tout, de Docker Desktop à Docker Hub en passant par Docker Compose, il est donc parfait pour les débutants qui souhaitent se familiariser avec Docker et les intermédiaires pour revenir sur les bases.
Le tutoriel original est à jour au ** 2020/11/19 **. Veuillez noter que les informations peuvent être obsolètes si une longue période s'est écoulée.
Les parties qui n'induisent pas le lecteur en erreur sont traduites comme il convient en mettant l'accent sur la lisibilité.
Nous affinons en utilisant DeepL etc., mais s'il y a des erreurs ou de meilleures expressions, veuillez faire une demande de modification.
** Traduit par ** getting-started : https://github.com/docker/getting-started/tree/6190776cb618b1eb3cfb21e207eefde511d13449
Licence: Apache License 2.0
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 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).
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.
-d
: Exécute le conteneur en mode détaché (arrière-plan).
-p
: mappe le port 80 de l'hôte sur le port 80 du conteneur.
docker / getting-started
: Image à utiliser
** 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
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.
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.
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 dechroot
. Le système de fichiers est simplement importé de l'image. Cependant, le conteneur a une fonction d'isolation plus forte que "chroot".
À 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.
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.
Après [Télécharger le fichier ZIP](http: //localhost/assets/app.zip), ouvrez le fichier ZIP et décompressez-le.
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
).
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.
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.
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.
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?)
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.
À 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.)
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.
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.
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>
docker build -t getting-started .
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.
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.
docker ps
pour obtenir l'ID du conteneur.docker ps
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>
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>
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.
Ouvrez le tableau de bord et passez la souris sur le conteneur de l'application pour voir la liste des actions sur la droite.
Cliquez sur le bouton Corbeille pour supprimer le conteneur.
Confirmez la suppression et vous avez terminé.
docker run -dp 3000:3000 getting-started
Bien que j'aie pu mettre à jour l'application, il y avait deux choses à noter.
Toutes les listes ToDo existantes ont disparu. Ce n'est pas une bonne application. J'en parlerai dans un proche avenir.
Malgré les petits changements, de nombreuses mesures ont dû être prises. Dans le chapitre suivant, nous vous montrerons comment mettre à jour votre code sans avoir à reconstruire et démarrer un nouveau conteneur à chaque fois que vous apportez une modification.
Avant de parler de permanence, apprenons à partager une image avec les autres.
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à.
Pour pousser une image, vous devez d'abord créer un référentiel sur Docker Hub.
Accédez à Docker Hub (https://hub.docker.com/) et connectez-vous si nécessaire.
Cliquez sur le bouton ** Créer un référentiel **.
Spécifiez «Getting-started» comme nom du référentiel. Assurez-vous que le niveau de publication est «Public».
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.
$ 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
Connectez-vous à Docker Hub à l'aide de la commande docker login -u YOUR-USER-NAME
.
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
tagname
. Si vous ne spécifiez pas de balise, Docker utilise la balise «latest».docker push YOUR-USER-NAME/getting-started
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.
Ouvrez Play with Docker (http://play-with-docker.com/) dans votre navigateur.
Connectez-vous avec votre compte Docker Hub.
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.
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.
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.
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.
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.
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.
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
.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.
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.
docker rm -f
.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.
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.
docker volume create
.docker volume create todo-db
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.
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
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.
Démarrez un nouveau conteneur en utilisant la même commande que ci-dessus.
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.
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.
À 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.
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.
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( -v utilisation) |
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 |
Commençons un conteneur qui peut être utilisé dans la phase de développement. Procédez comme suit:
Alors, commençons.
Assurez-vous que le conteneur de démarrage que vous avez utilisé jusqu'à présent n'est pas démarré.
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"
-dp 3000: 3000
: comme avant. Démarrez en mode détaché (arrière-plan) et créez un mappage de port.
-w / app
: Spécifiez le" répertoire de travail "ou le répertoire courant où la commande sera exécutée.
-v" $ (pwd): / app "
: À partir de l'hôte du conteneur, lier le montage du répertoire courant au répertoire / app
.
node: 12-alpine
: L'image à utiliser. Veuillez noter que cette image est l'image de base de l'application telle que spécifiée dans le Dockerfile.
sh -c" yarn install && yarn run dev "
: commande. J'utilise sh
(alpine n'a pas bash
) pour lancer le shell, installer toutes les dépendances avec yarn install
, puis exécuter yarn run dev
. Si vous regardez package.json
, vous pouvez voir que le script dev
lance nodemon
.
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
.
src / static / js / app.js
en" Ajouter ". C'est sur la ligne 109.- {submitting ? 'Adding...' : 'Add Item'}
+ {submitting ? 'Adding...' : 'Add'}
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.
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.
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 est probable que l'API et le front-end seront étendus d'une manière différente de celle de la base de données.
En séparant les conteneurs, vous pouvez mettre à jour la version séparément.
Vous pouvez utiliser un conteneur de base de données local, mais dans un environnement de production, vous pouvez utiliser un service qui gère la base de données. Dans ce cas, le moteur de base de données n'a pas besoin d'être inclus dans le produit avec l'application.
Pour exécuter plusieurs processus, vous avez besoin d'un gestionnaire de processus (le conteneur ne démarre qu'un seul processus), ce qui complique le démarrage / l'arrêt du conteneur.
Il y a aussi d'autres raisons. Donc, je vais mettre à jour l'application pour qu'elle fonctionne comme ça.
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.
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é.
docker network create todo-app
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 commandedocker volume create
. Docker a reconnu que nous allions utiliser un volume nommé et a créé le volume automatiquement.
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
.
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.
docker run -it --network todo-app nicolaka/netshoot
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.
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.
MYSQL_HOST
: Le nom d'hôte du serveur MySQL en cours d'exécution.
MYSQL_USER
: Le nom d'utilisateur utilisé pour se connecter.
MYSQL_PASSWORD
: Le mot de passe utilisé pour se connecter.
MYSQL_DB
: La base de données à utiliser après la connexion.
** 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.
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"
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
Ouvrez l'application dans votre navigateur et essayez d'ajouter des applications à votre liste de tâches.
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.
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.
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.
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éez un fichier appelé docker-compose.yml
à la racine du projet de votre application.
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
version: "3.7"
services:
Ensuite, déplaçons le service vers un fichier Compose.
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"
version: "3.7"
services:
app:
image: node:12-alpine
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
-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
-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
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é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
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
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:
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:
Maintenant que vous avez docker-compose.yml
, tout ce que vous avez à faire est de le démarrer.
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>
.)
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
dansmysql: latest
au début.docker volume rm app_todo-mysql-data
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.
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
.
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 «
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?
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.
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.
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.
--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
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?
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"]
.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 /).
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.
Modifiez le fichier src / static / index.html
(changez le contenu de <title>
en "The Awesome Todo App").
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.
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:
Vous pouvez séparer les dépendances d'exécution et les dépendances de temps de construction.
Réduisez la taille globale de l'image en ne disposant que de ce qui est nécessaire au lancement de l'application.
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
).
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?
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.
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.
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.
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