Docker Command Not Found sur Mac : Dépannage et Configuration de Votre Environnement

DockerBeginner
Pratiquer maintenant

Introduction

Docker a révolutionné le développement d'applications en permettant aux développeurs de créer, déployer et exécuter des applications dans des environnements isolés appelés conteneurs (containers). Les utilisateurs de Mac rencontrent parfois l'erreur "docker command not found", ce qui peut être frustrant lorsqu'on débute avec la conteneurisation. Ce lab vous guidera à travers la compréhension des concepts de Docker, la vérification de votre installation de Docker, le dépannage des problèmes courants et la configuration d'un environnement Docker approprié pour votre travail de développement.

Comprendre les bases de Docker et vérifier l'installation

Docker fournit une méthode standardisée pour empaqueter les applications et leurs dépendances dans des conteneurs (containers), les rendant portables sur différents environnements. Avant de dépanner tout problème Docker, assurons-nous de comprendre les bases et de vérifier notre installation.

Qu'est-ce que Docker ?

Docker est une plateforme qui utilise la technologie de conteneurisation pour faciliter la création, le déploiement et l'exécution d'applications. Contrairement aux machines virtuelles, les conteneurs Docker partagent le noyau du système hôte, mais s'exécutent dans des environnements isolés, ce qui les rend légers et efficaces.

Les principaux composants de Docker incluent :

  • Docker Engine : Le runtime qui construit et exécute les conteneurs
  • Docker Images : Des modèles en lecture seule utilisés pour créer des conteneurs
  • Docker Containers : Des instances en cours d'exécution des images Docker
  • Docker Registry : Un référentiel pour stocker et partager des images Docker
  • Dockerfile : Un fichier texte contenant des instructions pour construire une image Docker

Vérification de l'installation de Docker

Notre environnement de lab a déjà Docker installé. Vérifions cela en vérifiant la version de Docker :

docker --version

Vous devriez voir une sortie similaire à :

Docker version 20.10.21, build 20.10.21-0ubuntu1~22.04.3

Maintenant, vérifions si le démon Docker est en cours d'exécution :

sudo systemctl status docker

Vous devriez voir une sortie indiquant que Docker est actif (en cours d'exécution). La sortie ressemblera à :

● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since ...

Appuyez sur q pour quitter l'affichage de l'état.

Si, pour une raison quelconque, Docker n'est pas en cours d'exécution, vous pouvez le démarrer avec :

sudo systemctl start docker

Exécution de votre premier conteneur

Vérifions que Docker fonctionne correctement en exécutant un simple conteneur "hello-world" :

docker run hello-world

Cette commande télécharge l'image hello-world si elle n'est pas déjà disponible localement et l'exécute dans un conteneur. Vous devriez voir une sortie similaire à :

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

La sortie explique ce que Docker a fait pour exécuter ce conteneur, fournissant une bonne introduction au fonctionnement de Docker.

Vérification des conteneurs en cours d'exécution

Pour voir tous les conteneurs actuellement en cours d'exécution, utilisez :

docker ps

Étant donné que le conteneur hello-world se ferme immédiatement après avoir affiché son message, vous ne le verrez probablement pas dans cette liste. Pour voir tous les conteneurs, y compris ceux qui se sont arrêtés, utilisez :

docker ps -a

Cela affiche tous les conteneurs, leurs ID, les images à partir desquelles ils ont été créés, quand ils ont été créés et leur état actuel.

Vous avez maintenant vérifié que Docker est installé et fonctionne correctement dans votre environnement, et vous avez exécuté votre premier conteneur !

Travailler avec les images et les conteneurs Docker

Maintenant que vous avez vérifié que Docker fonctionne correctement, apprenons à travailler avec les images et les conteneurs Docker plus en détail.

Comprendre les images Docker

Les images Docker sont les plans des conteneurs. Elles contiennent le code de l'application, les bibliothèques, les dépendances, les outils et autres fichiers nécessaires à l'exécution d'une application.

Explorons les images Docker en utilisant quelques commandes de base :

Lister les images disponibles

Pour voir toutes les images Docker disponibles sur votre système :

docker images

Vous devriez voir une sortie similaire à :

REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   X months ago    13.3kB

Extraire des images de Docker Hub

Docker Hub est un service de registre basé sur le cloud où vous pouvez trouver et partager des images Docker. Extrayons une image populaire :

docker pull nginx

Cette commande télécharge la dernière image du serveur web nginx. Vous verrez une sortie de progression au fur et à mesure que différentes couches de l'image sont téléchargées :

Using default tag: latest
latest: Pulling from library/nginx
...
Digest: sha256:...
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

Exécutez docker images à nouveau pour voir l'image nginx nouvellement téléchargée dans votre liste.

Travailler avec les conteneurs

Maintenant que nous avons des images, apprenons à créer et à gérer des conteneurs.

Exécution d'un conteneur

Exécutons un conteneur nginx qui servira une page web :

docker run --name my-nginx -p 8080:80 -d nginx

Cette commande fait plusieurs choses :

  • --name my-nginx : Nomme le conteneur "my-nginx"
  • -p 8080:80 : Mappe le port 8080 sur votre hôte vers le port 80 dans le conteneur
  • -d : Exécute le conteneur en mode détaché (en arrière-plan)
  • nginx : Spécifie l'image à utiliser

Vérification que le conteneur est en cours d'exécution

Vérifiez que votre conteneur est en cours d'exécution :

docker ps

Vous devriez voir votre conteneur nginx dans la liste des conteneurs en cours d'exécution :

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                  NAMES
a1b2c3d4e5f6   nginx     "/docker-entrypoint.…"   X seconds ago    Up X seconds    0.0.0.0:8080->80/tcp   my-nginx

Accès au serveur web

Vous pouvez accéder au serveur web nginx en ouvrant un navigateur web dans votre environnement de machine virtuelle LabEx et en accédant à :

http://localhost:8080

Alternativement, vous pouvez utiliser curl depuis le terminal :

curl http://localhost:8080

Vous devriez voir la page HTML de bienvenue par défaut de nginx.

Affichage des journaux du conteneur

Pour voir les journaux de votre conteneur :

docker logs my-nginx

Cela affiche les journaux d'accès pour le serveur nginx.

Arrêt et suppression des conteneurs

Pour arrêter un conteneur en cours d'exécution :

docker stop my-nginx

Pour supprimer un conteneur (il doit d'abord être arrêté) :

docker rm my-nginx

Vérifiez que le conteneur a été supprimé :

docker ps -a

Le conteneur nommé "my-nginx" ne devrait plus apparaître dans la liste.

Vous comprenez maintenant les bases du travail avec les images et les conteneurs Docker. Vous avez extrait des images de Docker Hub, exécuté des conteneurs, mappé des ports, affiché des journaux et géré les cycles de vie des conteneurs.

Créer vos propres images Docker avec les Dockerfiles

Jusqu'à présent, nous avons utilisé des images Docker pré-construites de Docker Hub. Maintenant, apprenons à créer nos propres images Docker personnalisées en utilisant les Dockerfiles.

Qu'est-ce qu'un Dockerfile ?

Un Dockerfile est un fichier texte qui contient des instructions pour construire une image Docker. Il spécifie l'image de base, ajoute des fichiers, installe des logiciels, définit des variables d'environnement et configure le conteneur qui sera créé à partir de l'image.

Création de votre premier Dockerfile

Créons une simple application web en utilisant Node.js et empaquetons-la en tant qu'image Docker.

Tout d'abord, créez un nouveau répertoire pour votre projet :

mkdir -p ~/project/node-app
cd ~/project/node-app

Maintenant, créez une simple application Node.js. Tout d'abord, créez un fichier nommé app.js :

nano app.js

Ajoutez le code suivant au fichier :

const http = require("http");

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain");
  res.end("Hello World from Docker!\n");
});

const port = 3000;
server.listen(port, () => {
  console.log(`Server running at http://localhost:${port}/`);
});

Enregistrez le fichier en appuyant sur Ctrl+O, puis sur Entrée, et quittez nano avec Ctrl+X.

Ensuite, créez un fichier package.json pour définir votre application Node.js :

nano package.json

Ajoutez le contenu suivant :

{
  "name": "docker-node-app",
  "version": "1.0.0",
  "description": "A simple Node.js app for Docker",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "author": "",
  "license": "ISC"
}

Enregistrez et quittez nano.

Maintenant, créez un Dockerfile :

nano Dockerfile

Ajoutez le contenu suivant :

## Use an official Node.js runtime as the base image
FROM node:14-alpine

## Set the working directory in the container
WORKDIR /usr/src/app

## Copy package.json and package-lock.json
COPY package.json ./

## Install dependencies
RUN npm install

## Copy the application code
COPY app.js ./

## Expose the port the app runs on
EXPOSE 3000

## Command to run the application
CMD ["npm", "start"]

Enregistrez et quittez nano.

Construction de votre image Docker

Maintenant que vous avez un Dockerfile, vous pouvez construire votre image Docker :

docker build -t my-node-app .

Cette commande construit une image à partir de votre Dockerfile :

  • -t my-node-app : Tague l'image avec le nom "my-node-app"
  • . : Spécifie que le Dockerfile se trouve dans le répertoire courant

Vous verrez une sortie montrant la progression de la construction :

Sending build context to Docker daemon  X.XXkB
Step 1/7 : FROM node:14-alpine
 ---> XXXXXXXXXX
Step 2/7 : WORKDIR /usr/src/app
 ---> XXXXXXXXXX
...
Successfully built XXXXXXXXXX
Successfully tagged my-node-app:latest

Exécution de votre image Docker personnalisée

Maintenant, exécutez un conteneur en utilisant votre image nouvellement construite :

docker run --name node-app-container -p 3000:3000 -d my-node-app

Vérifiez que le conteneur est en cours d'exécution :

docker ps

Vous devriez voir votre conteneur dans la liste :

CONTAINER ID   IMAGE         COMMAND         CREATED          STATUS          PORTS                    NAMES
XXXXXXXXXX     my-node-app   "npm start"     X seconds ago    Up X seconds    0.0.0.0:3000->3000/tcp   node-app-container

Test de votre application

Testez l'application en effectuant une requête HTTP vers celle-ci :

curl http://localhost:3000

Vous devriez voir :

Hello World from Docker!

Comprendre le Dockerfile

Passons en revue les principaux composants de notre Dockerfile :

  1. FROM node:14-alpine : Spécifie l'image de base à utiliser
  2. WORKDIR /usr/src/app : Définit le répertoire de travail à l'intérieur du conteneur
  3. COPY package.json ./ : Copie les fichiers de l'hôte vers le conteneur
  4. RUN npm install : Exécute une commande à l'intérieur du conteneur pendant le processus de construction
  5. EXPOSE 3000 : Documente que le conteneur écoute sur le port 3000
  6. CMD ["npm", "start"] : Spécifie la commande à exécuter lorsque le conteneur démarre

Nettoyage

Nettoyons en arrêtant et en supprimant le conteneur :

docker stop node-app-container
docker rm node-app-container

Vous avez maintenant appris à créer vos propres images Docker en utilisant les Dockerfiles, à construire ces images et à exécuter des conteneurs basés sur celles-ci. C'est une compétence fondamentale pour le développement Docker.

Gérer les données avec les volumes Docker

L'un des défis lorsque l'on travaille avec les conteneurs Docker est la persistance des données. Les conteneurs sont éphémères, ce qui signifie que toutes les données créées à l'intérieur d'un conteneur sont perdues lorsque le conteneur est supprimé. Les volumes Docker résolvent ce problème en offrant un moyen de persister les données en dehors des conteneurs.

Comprendre les volumes Docker

Les volumes Docker sont le mécanisme privilégié pour la persistance des données générées et utilisées par les conteneurs Docker. Ils sont entièrement gérés par Docker et sont isolés de la structure de répertoire du système de fichiers de l'hôte.

Les avantages de l'utilisation des volumes incluent :

  • Les volumes sont plus faciles à sauvegarder ou à migrer que les bind mounts
  • Vous pouvez gérer les volumes à l'aide des commandes de l'interface de ligne de commande (CLI) Docker
  • Les volumes fonctionnent sur les conteneurs Linux et Windows
  • Les volumes peuvent être partagés plus en toute sécurité entre plusieurs conteneurs
  • Les volume drivers vous permettent de stocker des volumes sur des hôtes distants, des fournisseurs de cloud ou de chiffrer le contenu des volumes

Création et utilisation des volumes Docker

Créons un simple conteneur de base de données MySQL qui utilise un volume pour persister ses données.

Création d'un volume

Tout d'abord, créez un volume Docker :

docker volume create mysql-data

Vous pouvez lister tous les volumes avec :

docker volume ls

Vous devriez voir votre nouveau volume dans la liste :

DRIVER    VOLUME NAME
local     mysql-data

Exécution d'un conteneur avec un volume

Maintenant, exécutons un conteneur MySQL qui utilise ce volume :

docker run --name mysql-db -e MYSQL_ROOT_PASSWORD=mysecretpassword -v mysql-data:/var/lib/mysql -p 3306:3306 -d mysql:5.7

Cette commande :

  • --name mysql-db : Nomme le conteneur "mysql-db"
  • -e MYSQL_ROOT_PASSWORD=mysecretpassword : Définit une variable d'environnement pour configurer MySQL
  • -v mysql-data:/var/lib/mysql : Monte le volume "mysql-data" dans le répertoire où MySQL stocke ses données
  • -p 3306:3306 : Mappe le port 3306 sur l'hôte vers le port 3306 dans le conteneur
  • -d : Exécute le conteneur en mode détaché
  • mysql:5.7 : Spécifie l'image à utiliser

Attendez un instant que le conteneur démarre, puis vérifiez qu'il est en cours d'exécution :

docker ps

Interaction avec la base de données

Créons une base de données et une table pour démontrer la persistance des données. Tout d'abord, connectez-vous au conteneur MySQL :

docker exec -it mysql-db bash

À l'intérieur du conteneur, connectez-vous au serveur MySQL :

mysql -u root -pmysecretpassword

Créez une nouvelle base de données et une table :

CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255));
INSERT INTO users (name) VALUES ('John'), ('Jane'), ('Bob');
SELECT * FROM users;

Vous devriez voir les données insérées :

+----+------+
| id | name |
+----+------+
|  1 | John |
|  2 | Jane |
|  3 | Bob  |
+----+------+

Quittez l'invite MySQL et le conteneur :

exit
exit

Test de la persistance du volume

Maintenant, arrêtons et supprimons le conteneur, puis créons-en un nouveau en utilisant le même volume :

docker stop mysql-db
docker rm mysql-db

Créez un nouveau conteneur en utilisant le même volume :

docker run --name mysql-db-new -e MYSQL_ROOT_PASSWORD=mysecretpassword -v mysql-data:/var/lib/mysql -p 3306:3306 -d mysql:5.7

Connectez-vous maintenant au nouveau conteneur et vérifiez si nos données ont persisté :

docker exec -it mysql-db-new bash
mysql -u root -pmysecretpassword
USE testdb
SELECT * FROM users

Vous devriez voir les mêmes données que nous avons insérées précédemment :

+----+------+
| id | name |
+----+------+
|  1 | John |
|  2 | Jane |
|  3 | Bob  |
+----+------+

Quittez l'invite MySQL et le conteneur :

exit
exit

Cela démontre que les données ont persisté même après la suppression du conteneur d'origine, car elles étaient stockées dans un volume Docker.

Inspection et gestion des volumes

Vous pouvez inspecter un volume pour obtenir plus d'informations à son sujet :

docker volume inspect mysql-data

Cela affichera des détails tels que le point de montage et le driver utilisé :

[
  {
    "CreatedAt": "YYYY-MM-DDTHH:MM:SS+00:00",
    "Driver": "local",
    "Labels": {},
    "Mountpoint": "/var/lib/docker/volumes/mysql-data/_data",
    "Name": "mysql-data",
    "Options": {},
    "Scope": "local"
  }
]

Pour nettoyer, arrêtons et supprimons le conteneur :

docker stop mysql-db-new
docker rm mysql-db-new

Si vous souhaitez également supprimer le volume :

docker volume rm mysql-data

Vous avez maintenant appris à utiliser les volumes Docker pour persister les données entre les cycles de vie des conteneurs, ce qui est essentiel pour les applications avec état telles que les bases de données.

Explorer la mise en réseau Docker

La mise en réseau Docker permet aux conteneurs de communiquer entre eux et avec le monde extérieur. Comprendre les capacités de mise en réseau de Docker est crucial pour la construction d'applications multi-conteneurs.

Types de réseaux Docker

Docker fournit plusieurs network drivers prêts à l'emploi :

  • bridge : Le network driver par défaut. Les conteneurs sur le même réseau bridge peuvent communiquer.
  • host : Supprime l'isolation réseau entre le conteneur et l'hôte.
  • none : Désactive toute mise en réseau pour un conteneur.
  • overlay : Connecte plusieurs daemons Docker et permet aux services Swarm de communiquer.
  • macvlan : Attribue une adresse MAC à un conteneur, ce qui lui donne l'apparence d'un périphérique physique sur le réseau.

Explorer le réseau bridge par défaut

Lorsque vous installez Docker, il crée automatiquement un réseau bridge par défaut. Explorons-le :

docker network ls

Vous devriez voir une sortie similaire à :

NETWORK ID     NAME      DRIVER    SCOPE
XXXXXXXXXXXX   bridge    bridge    local
XXXXXXXXXXXX   host      host      local
XXXXXXXXXXXX   none      null      local

Vous pouvez inspecter le réseau bridge par défaut :

docker network inspect bridge

Cette commande fournit des informations détaillées sur le réseau, y compris les conteneurs qui y sont connectés, la plage d'adresses IP et la passerelle.

Création et utilisation de réseaux bridge personnalisés

Créons un réseau bridge personnalisé pour une meilleure isolation des conteneurs :

docker network create my-network

Vérifiez que le réseau a été créé :

docker network ls

Vous devriez voir votre nouveau réseau dans la liste :

NETWORK ID     NAME           DRIVER    SCOPE
XXXXXXXXXXXX   bridge         bridge    local
XXXXXXXXXXXX   host           host      local
XXXXXXXXXXXX   my-network     bridge    local
XXXXXXXXXXXX   none           null      local

Maintenant, exécutons deux conteneurs sur ce réseau et démontrons la communication entre eux.

Tout d'abord, démarrez un conteneur NGINX sur le réseau personnalisé :

docker run --name web-server --network my-network -d nginx

Ensuite, exécutons un conteneur Alpine Linux et utilisons-le pour tester la connectivité au conteneur NGINX :

docker run --name alpine --network my-network -it alpine sh

À l'intérieur du conteneur Alpine, installez curl et testez la connectivité au conteneur NGINX :

apk add --update curl
curl web-server

La sortie devrait être le code HTML de la page d'accueil NGINX. Cela fonctionne car Docker fournit un DNS intégré pour les conteneurs dans les réseaux personnalisés, leur permettant de résoudre les noms de conteneurs en adresses IP.

Tapez exit pour quitter le conteneur Alpine :

exit

Connecter des conteneurs à plusieurs réseaux

Les conteneurs peuvent être connectés à plusieurs réseaux. Créons un autre réseau :

docker network create another-network

Connectez le conteneur web-server existant à ce nouveau réseau :

docker network connect another-network web-server

Vérifiez que le conteneur est maintenant connecté aux deux réseaux :

docker inspect web-server -f '{{json .NetworkSettings.Networks}}' | json_pp

Vous devriez voir que le conteneur est connecté à la fois à my-network et à another-network.

Exécution de conteneurs avec la publication de ports

Lorsque vous souhaitez rendre le service d'un conteneur accessible depuis l'extérieur de l'hôte Docker, vous devez publier ses ports :

docker run --name public-web -p 8080:80 -d nginx

Cette commande mappe le port 8080 sur l'hôte vers le port 80 dans le conteneur. Vous pouvez accéder au serveur web NGINX en utilisant :

curl http://localhost:8080

Vous devriez voir la page d'accueil NGINX.

Nettoyage

Nettoyons les conteneurs et les réseaux que nous avons créés :

docker stop web-server alpine public-web
docker rm web-server alpine public-web
docker network rm my-network another-network

Vérifiez que les conteneurs et les réseaux ont été supprimés :

docker ps -a
docker network ls

Comprendre la communication entre conteneurs

Cette étape a démontré comment la mise en réseau Docker permet :

  1. La communication de conteneur à conteneur en utilisant des réseaux personnalisés
  2. La résolution DNS en utilisant les noms de conteneurs
  3. La connexion de conteneurs à plusieurs réseaux
  4. L'exposition des services de conteneurs au monde extérieur en utilisant la publication de ports

Ces capacités de mise en réseau sont essentielles pour la construction d'applications complexes et multi-conteneurs où les composants doivent communiquer entre eux et avec des services externes.

Résumé

Félicitations pour avoir terminé ce lab Docker ! Vous avez appris des concepts et des compétences Docker essentiels qui constituent les fondements du développement et du déploiement basés sur les conteneurs.

Dans ce lab, vous avez :

  • Vérifié l'installation de Docker et exécuté votre premier conteneur
  • Travaillé avec les images et les conteneurs Docker, y compris l'extraction d'images depuis Docker Hub et la gestion des cycles de vie des conteneurs
  • Créé votre propre image Docker personnalisée en utilisant un Dockerfile
  • Utilisé les volumes Docker pour persister les données entre les cycles de vie des conteneurs
  • Exploré la mise en réseau Docker pour permettre la communication de conteneur à conteneur

Ces compétences vous permettront de :

  • Emballer les applications et leurs dépendances dans des conteneurs portables
  • Créer des environnements standardisés pour le développement, les tests et la production
  • Mettre en œuvre des architectures de microservices où chaque composant s'exécute dans son propre conteneur
  • Assurer la persistance des données pour les applications avec état
  • Construire des applications multi-conteneurs complexes avec une isolation et une communication appropriées

Docker est devenu un outil essentiel dans le développement logiciel moderne, et les connaissances que vous avez acquises seront précieuses dans un large éventail de scénarios de développement et d'opérations.