Série de webinaires: Création d’applications conteneurisées

introduction

Dans le dernier tutoriel, Comment installer et configurer Docker, nous avons exploré une méthode de conversion de https: // www .digitalocean.com / community / tutorials / comment-installer-et-configurer-docker # step-2-% E2% 80% 94-launching-containers [Conteneurs Docker] dans https://www.digitalocean.com/ communauté / didacticiels / comment-installer-et-configurer-docker # step-4-% E2% 80% 94-building-images [Images Docker]. Bien que la méthode utilisée ait fonctionné, ce n’est pas toujours la manière optimale de construire des images.

Dans de nombreux cas, vous souhaiterez intégrer le code existant dans des images de conteneur, ainsi qu’un mécanisme reproductible et cohérent pour la création d’images Docker synchronisées avec la dernière version de votre base de code.

Un Dockerfile répond à ces exigences en fournissant un moyen déclaratif et cohérent de création d’images Docker.

De plus, vous souhaiterez parfois conteneuriser des applications entières composées de plusieurs conteneurs hétérogènes déployés et gérés ensemble.

Docker Compose, comme un fichier Docker, adopte une approche déclarative pour vous fournir une méthode permettant de définir une pile technologique complète, y compris les exigences de réseau et de stockage. Cela facilite non seulement la création d’applications conteneurisées, mais facilite également leur gestion et leur mise à l’échelle.

Dans ce didacticiel, vous utiliserez un exemple d’application Web basé sur Node.js et MongoDB pour créer une image Docker à partir d’un fichier Docker. créera un réseau personnalisé qui permettra à vos conteneurs Docker de communiquer et vous utiliserez Docker Compose pour lancer et mettre à l’échelle une application conteneurisée.

Conditions préalables

Pour suivre ce tutoriel, vous aurez besoin de:

Étape 1 - Construire une image avec un fichier Docker

Commencez par accéder à votre répertoire personnel, puis utilisez Git pour cloner l’exemple d’application Web de ce didacticiel à partir de son official repository sur GitHub.

cd ~
git clone https://github.com/janakiramm/todo-app.git

Ceci copiera l’exemple d’application dans un nouveau répertoire nommé + todo-app +.

Basculez sur + todo-app + et utilisez + ls + pour afficher le contenu du répertoire.

cd todo-app
ls

Le nouveau répertoire contient deux sous-répertoires et deux fichiers:

  • + app + - le répertoire où est stocké le code source de l’exemple d’application

  • + compose + - le répertoire dans lequel le fichier de configuration de Docker Compose est stocké

  • + Dockerfile + - un fichier contenant des instructions pour construire l’image Docker

  • + README.md + - un fichier contenant un résumé en une phrase de l’exemple d’application

Lancer + cat Dockerfile + nous montre ce qui suit:

~ / todo-app / Dockerfile

FROM node:slim
LABEL maintainer = "[email protected]"
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY ./app/ ./
RUN npm install
CMD ["node", "app.js"]

Jetons un coup d’œil au contenu de ce fichier plus en détail:

  • + FROM + indique l’image de base à partir de laquelle vous créez l’image personnalisée. Dans cet exemple, l’image est basée sur + node: slim +, une image public Node.js contenant uniquement les paquets nécessaires à l’exécution de `+ node +. `.

  • + LABEL + est une paire clé-valeur généralement utilisée pour ajouter des informations descriptives. Dans ce cas, il contient l’adresse email du mainteneur.

  • + RUN + exécute des commandes dans le conteneur. Cela inclut des tâches telles que la création de répertoires et l’initialisation du conteneur en exécutant des commandes Linux de base. La première commande + RUN + de ce fichier est utilisée pour créer le répertoire + / usr / src / app + qui contient le code source.

  • + WORKDIR + définit le répertoire dans lequel toutes les commandes sont exécutées. Il s’agit généralement du répertoire dans lequel le code est copié.

  • + COPY + copie les fichiers de la machine hôte dans l’image du conteneur. Dans ce cas, vous copiez l’intégralité du répertoire + app + dans l’image.

  • La deuxième commande + RUN + exécute + npm install + pour installer les dépendances de l’application telles que définies dans + package.json +.

  • + CMD + exécute le processus qui maintiendra le conteneur en cours d’exécution. Dans cet exemple, vous exécuterez + node + avec le paramètre + app.js +.

Il est maintenant temps de construire l’image à partir du + Dockerfile +. Utilisez le commutateur + -t + pour baliser l’image avec le nom d’utilisateur du registre, le nom de l’image et une balise facultative.

docker build -t /todo-web .

La sortie confirme que l’image est + avec succès construit + et étiquetée de manière appropriée.

Output from docker build -tSending build context to Docker daemon  8.238MB
Step 1/7 : FROM node:slim
---> 286b1e0e7d3f
Step 2/7 : LABEL maintainer = "[email protected]"
---> Using cache
---> ab0e049cf6f8
Step 3/7 : RUN mkdir -p /usr/src/app
---> Using cache
---> 897176832f4d
Step 4/7 : WORKDIR /usr/src/app
---> Using cache
---> 3670f0147bed
Step 5/7 : COPY ./app/ ./
---> Using cache
---> e28c7c1be1a0
Step 6/7 : RUN npm install
---> Using cache
---> 7ce5b1d0aa65
Step 7/7 : CMD node app.js
---> Using cache
---> 2cef2238de24
2cef2238de24
/todo-web:latest

Nous pouvons vérifier que l’image est créée en exécutant la commande + docker images +.

docker images

Ici, nous pouvons voir la taille de l’image avec le temps écoulé depuis sa création.

Output from docker imagesREPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE
/todo-web                                   latest              81f5f605d1ca        9 minutes ago       236MB

Comme nous avons également besoin d’un conteneur MongoDB pour exécuter l’exemple d’application Web, transmettons-le à notre ordinateur.

docker pull mongo:latest

La sortie indique exactement quelle image a été extraite avec l’état du téléchargement.

Output from docker pulllatest: Pulling from library/mongo
Digest: sha256:18b239b996e0d10f4ce2b0f64db6f410c17ad337e2cecb6210a3dcf2f732ed82
Status: Downloaded newer image for mongo:latest

Nous avons maintenant tout ce dont nous avons besoin pour exécuter l’exemple d’application. Nous allons donc créer un réseau personnalisé qui permettra à nos conteneurs de communiquer les uns avec les autres.

Étape 2 - Création d’un réseau pour lier des conteneurs

Si nous lançions indépendamment les conteneurs d’applications Web et de bases de données via la commande + docker run +, ils ne pourraient pas se trouver.

Pour savoir pourquoi, affichez le contenu du fichier de configuration de la base de données de l’application Web.

cat app/db.js

Après avoir importé Mongoose - une bibliothèque de modélisation d’objet MongoDB pour Node.js - et défini un nouveau https://www.digitalocean.com/community/tutorials/understanding-sql-and-nosql -databases-and-different-database-models [schéma de base de données], l’application Web tente de se connecter à la base de données au nom d’hôte + db +, qui n’existe pas encore.

~ / todo-app / app / db.js

var mongoose = require( 'mongoose' );
var Schema   = mongoose.Schema;

var Todo = new Schema({
   user_id    : String,
   content    : String,
   updated_at : Date
});

mongoose.model( 'Todo', Todo );

mongoose.connect( 'mongodb:///express-todo' );

Pour que les conteneurs appartenant à la même application se découvrent, nous devons les lancer sur le même réseau.

Docker offre la possibilité de créer des réseaux personnalisés en plus des default networks créés lors de l’installation.

Vous pouvez vérifier vos réseaux actuellement disponibles avec la commande suivante:

docker network ls

Chaque réseau créé par Docker est basé sur un driver. Dans la sortie suivante, nous voyons que le réseau nommé + bridge + est basé sur le pilote + bridge +. L’étendue + local + indique que le réseau est disponible uniquement sur cet hôte.

Output from docker network lsNETWORK ID          NAME                DRIVER              SCOPE
5029df19d0cf
367330960d5c        host                host                local
f280c1593b89        none                null                local

Nous allons maintenant créer un réseau personnalisé nommé + todo_net + pour notre application, puis nous lancerons des conteneurs sur ce réseau.

docker network create todo_net

La sortie nous indique le hachage du réseau créé.

Output from docker network createC09f199809ccb9928dd9a93408612bb99ae08bb5a65833fefd6db2181bfe17ac

Maintenant, listez à nouveau les réseaux disponibles.

docker network ls

Nous voyons ici que + todo_net + est prêt à être utilisé.

Output from docker network lsNETWORK ID          NAME                DRIVER              SCOPE
c51377a045ff        bridge              bridge              local
2e4106b07544        host                host                local
7a8b4801a712        none                null                local

Lorsque vous utilisez la commande + docker run +, nous pouvons maintenant faire référence à ce réseau avec le commutateur + - network +. Lançons les conteneurs Web et de base de données avec des noms d’hôte spécifiques. Cela garantira que les conteneurs peuvent se connecter les uns aux autres via ces noms d’hôte.

Commencez par lancer le conteneur de base de données MongoDB.

docker run -d \
--name=db \
--hostname=db \
--network=todo_net \
mongo

En regardant de plus près cette commande, nous voyons:

  • Le commutateur + -d + exécute le conteneur en detached mode.

  • Les commutateurs + - name + et + - hostname + attribuent un nom défini par l’utilisateur au conteneur. Le commutateur + - hostname + ajoute également une entrée au service DNS géré par Docker. Cela aide à résoudre le conteneur par nom d’hôte.

  • Le commutateur + - network + indique à Docker Engine de lancer le conteneur sur un réseau personnalisé au lieu du réseau de pont par défaut.

Lorsque nous voyons une longue chaîne en sortie de la commande + docker run +, nous pouvons supposer que le conteneur a été lancé avec succès. Toutefois, cela ne garantit pas nécessairement que le conteneur est en cours d’exécution.

Output docker runaa56250f2421c5112cf8e383b68faefea91cd4b6da846cbc56cf3a0f04ff4295

Vérifiez que le conteneur + db + est opérationnel avec la commande + docker logs +.

docker logs db

Ceci affiche les journaux du conteneur sur + stdout. La dernière ligne du journal indique que MongoDB est prêt et + en attente de connexions +.

Output from docker logs2017-12-10T02:55:08.284+0000 I CONTROL  [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=db
. . . .
2017-12-10T02:55:08.366+0000 I NETWORK  [initandlisten]  on port 27017

Lançons maintenant le conteneur Web et vérifions-le. Cette fois, nous incluons également + - publish = 3000: 3000 + qui publie le port de l’hôte + 3000 + sur le port du conteneur + 3000 +.

docker run -d \
--name=web \
--publish=3000:3000 \
--hostname=web \
--network=todo_net \
/todo-web

Vous recevrez une longue chaîne en sortie comme auparavant.

Vérifions également que ce conteneur est opérationnel.

docker logs web

La sortie confirme que Express - la structure Node.js sur laquelle notre application de test repose - est + écoute sur le port 3000 +.

Output from docker logsExpress server listening on port 3000

Vérifiez que le conteneur Web est capable de communiquer avec le conteneur de base de données avec une commande + ping +. Pour ce faire, exécutez la commande + docker exec + dans un mode interactif (+ -i +) associé à un pseudo-TTY (+ -t +).

docker exec -it web ping db

La commande produit une sortie standard + ping + et nous indique que les deux conteneurs peuvent communiquer l’un avec l’autre.

Output from docker exec -it web ping dbPING db (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.210 ms
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.095 ms
...

Appuyez sur les touches + CTRL + C + pour arrêter la commande + ping +.

Enfin, accédez à l’exemple d’application en faisant pointer votre navigateur Web sur + http: // your_server_ip: 3000 +. Vous verrez une page Web avec une étiquette indiquant * Containers Todo Example * avec une zone de texte qui accepte une tâche en tant qu’entrée.

Pour éviter les conflits de noms, vous pouvez maintenant arrêter les conteneurs et nettoyer les ressources avec les commandes + docker rm + et + + docker network remove + `.

docker rm -f db
docker rm -f web
docker network remove todo_net

À ce stade, nous disposons d’une application Web conteneurisée composée de deux conteneurs distincts. Dans la prochaine étape, nous explorerons une approche plus robuste.

Étape 3 - Déploiement d’une application multi-conteneurs

Bien que nous ayons pu lancer des conteneurs liés, ce n’est pas la manière la plus élégante de traiter des applications multi-conteneurs. Nous avons besoin d’un meilleur moyen de déclarer tous les conteneurs associés et de les gérer comme une seule unité logique.

Docker Compose est un framework à la disposition des développeurs pour gérer des applications multi-conteneurs. Comme Dockefile, c’est un mécanisme déclaratif pour définir la pile entière. Nous allons maintenant convertir nos applications Node.js et MongoDB en une application basée sur Docker Compose.

Commencez par installer Docker Compose.

sudo apt-get install -y docker-compose

Examinons le fichier + docker-compose.yaml + situé dans le répertoire + compose + de l’application Web exemple.

cat compose/docker-compose.yaml

Le fichier + docker-compose.yaml + regroupe tout. Il définit le conteneur MongoDB dans le bloc + db: +, le conteneur Web Node.js dans le bloc + web: + et le réseau personnalisé dans le bloc + networks: +.

Notez qu’avec la directive + build: ../.+, nous pointons Compose sur le + Dockerfile + dans le répertoire + app +. Ceci indiquera à Compose de construire l’image avant de lancer le conteneur Web.

~ / todo-app / compose / docker-compose.yml

version: '2'
services:
 db:
   image: mongo:latest
   container_name: db
   networks:
     - todonet
 web:
   build: ../.
   networks:
     - todonet
   ports:
    - "3000"
networks:
 todonet:
   driver: bridge

Passez maintenant dans le répertoire + composer et lancez l’application avec la commande` + docker-compose up`. Comme avec + docker run +, le commutateur + -d + démarre le conteneur en mode détaché.

cd compose
docker-compose up -d

La sortie indique que Docker Compose a créé un réseau appelé + compose_todonet + et a lancé les deux conteneurs dessus.

Output from docker-compose up -dCreating network "compose_todonet" with driver "bridge"
Creating db
Creating compose_web_1

Notez que nous n’avons pas fourni le mappage de port d’hôte explicite. Cela obligera Docker Compose à attribuer un port aléatoire pour exposer l’application Web sur l’hôte. Nous pouvons trouver ce port en lançant la commande suivante:

docker ps

Nous voyons que l’application Web est exposée sur le port hôte + 32782 +.

Output from docker psCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
6700761c0a1e        compose_web         "node app.js"            2 minutes ago       Up 2 minutes        0.0.0.0:->3000/tcp   compose_web_1
ad7656ef5db7        mongo:latest        "docker-entrypoint..."   2 minutes ago       Up 2 minutes        27017/tcp                 db

Vérifiez cela en naviguant dans votre navigateur Web jusqu’à + http: // votre_serveur_serveur: 32782 +. Ceci affichera l’application Web exactement comme vous l’avez vu à la fin du lien: # step-2-% E2% 80% 94-créer un réseau à des conteneurs de liens [Étape 2].

Avec notre application multi-conteneurs opérationnelle via Docker Compose, examinons la gestion et la mise à l’échelle de notre application.

Étape 4 - Gestion et mise à l’échelle de l’application

Docker Compose facilite la mise à l’échelle d’applications Web sans état. Nous pouvons lancer 10 instances de notre conteneur + web + avec une seule commande.

docker-compose scale web=10

La sortie nous permet de regarder les instances en cours de création et de démarrage en temps réel.

Output from docker-compose scaleCreating and starting compose_web_2 ... done
Creating and starting compose_web_3 ... done
Creating and starting compose_web_4 ... done
Creating and starting compose_web_5 ... done
Creating and starting compose_web_6 ... done
Creating and starting compose_web_7 ... done
Creating and starting compose_web_8 ... done
Creating and starting compose_web_9 ... done
Creating and starting compose_web_10 ... done

Vérifiez que l’application Web est mise à l’échelle sur 10 instances en exécutant + docker ps +.

docker ps

Notez que Docker a assigné un port aléatoire pour exposer chaque conteneur + web + sur l’hôte. Chacun de ces ports peut être utilisé pour accéder à l’application.

Output from docker psCONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                     NAMES
cec405db568d        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_9
56adb12640bb        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_10
4a1005d1356a        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_7
869077de9cb1        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_8
eef86c56d16f        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_4
26dbce7f6dab        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_5
0b3abd8eee84        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_3
8f867f60d11d        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_6
36b817c6110b        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_2
6700761c0a1e        compose_web         "node app.js"            7 minutes ago        Up 7 minutes        0.0.0.0:->3000/tcp   compose_web_1
ad7656ef5db7        mongo:latest        "docker-entrypoint..."   7 minutes ago        Up 7 minutes        27017/tcp                 db

Vous pouvez également faire évoluer le conteneur Web avec la même commande.

docker-compose scale web=2

Cette fois, nous voyons les instances supplémentaires supprimées en temps réel.

Output from docker-composeStopping and removing compose_web_3 ... done
Stopping and removing compose_web_4 ... done
Stopping and removing compose_web_5 ... done
Stopping and removing compose_web_6 ... done
Stopping and removing compose_web_7 ... done
Stopping and removing compose_web_8 ... done
Stopping and removing compose_web_9 ... done
Stopping and removing compose_web_10 ... done

Enfin, vérifiez à nouveau les instances.

docker ps

La sortie confirme qu’il ne reste que deux instances.

Output from docker psCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
36b817c6110b        compose_web         "node app.js"            3 minutes ago       Up 3 minutes        0.0.0.0:32787->3000/tcp   compose_web_2
6700761c0a1e        compose_web         "node app.js"            9 minutes ago       Up 9 minutes        0.0.0.0:32782->3000/tcp   compose_web_1
ad7656ef5db7        mongo:latest        "docker-entrypoint..."   9 minutes ago       Up 9 minutes        27017/tcp                 db

Vous pouvez maintenant arrêter l’application et, comme avant, vous pouvez également nettoyer les ressources pour éviter les conflits de noms.

docker-compose stop
docker-compose rm -f
docker network remove compose_todonet

Conclusion

Ce tutoriel vous a présenté Dockerfiles et Docker Compose. Nous avons commencé avec un fichier Docker comme mécanisme déclaratif de construction d’images, puis nous avons exploré les bases du réseau Docker. Enfin, nous avons mis à l’échelle et géré des applications multi-conteneurs avec Docker Compose.

Pour étendre votre nouvelle configuration, vous pouvez ajouter un Nginx reverse proxy s’exécutant dans un autre conteneur. pour acheminer les demandes vers l’un des conteneurs d’applications Web disponibles. Ou, vous pouvez tirer parti de DigitalOcean’s Block Storage et de https://www.digitalocean.com/ communauté / didacticiels / une-introduction à l’équilibreur de charge digitalocean [Load Balancers] pour apporter durabilité et évolutivité aux applications conteneurisées.