Docker : premiers pas - créer une app
https://docs.docker.com/get-started/part2/
Pour créer une application, on va commencer par le bas de :
- Stack : définition des interactions des services
- Services : comment le container se comporte en prod
- Container (on est là)
Le fichier Dockerfile
définit ce qui se passe dans l'env dans le conteneur (car quand on est dans un container, accéder à son nom retourne l'ID du container) :
FROM (un run time officiel) ; WORKDIR /app
; ADD . /app
; RUN ... ; EXPOSE 80
(port 80 dispo) ...
Sur son ordi, créer un dossier, avec dedans, les 3 fichiers zippées en PJ (dont le fichier Dockerfile), etre dans ce dossier (cd PATH) et (construit une image "coucou") docker build -t coucou .
Un docker image ls
va montrer coucou (en colonne REPOSITORY, avec le TAG latest, ID de l'image, idée d'age et taille). On peux alors :
-
docker run -p 4000:80 coucou
lancer (sur le :4000 de son pc, 80 exposé du contener).
Est affiché via python le message à "http://0.0.0.0:80"
(mais en fait pour nous à http://localhost:4000/). On peux trouver ip avecdocker-machine ip
-
docker run -d -p 4000:80
lancer en background, en mode détachédocker container ls
-
docker container stop ID
A chaque fois, le Hostname affiché est différent - c'est le CONTAINER ID
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d3cd31c2004d coucou "python app.py" 2 minutes ago Up 2 minutes 0.0.0.0:4000->80/tcp dazzling_jepsen
Donc ici : docker container stop d3cd31c2004d
Publication (sur un repository)
docker login
# Def tag : docker tag image username/repository:tag
docker tag coucou username/get-started:part2
docker push username/repository:tag
De n'importe quelle machine, on peux maintenant faire (si l'image n'est pas en local, docker ira la chercher): docker run -p 4000:80 username/
get-started:part2
Services
https://docs.docker.com/get-started/part3/
On va ici activer le load-balancing.
Les services sont des conteneurs, un service lance une seule image en la controlant (ports utilisés, nb replicas...). On va ici changer le nb d'instances de tel contener etc...
docker-compose.yml
définit comment le conteneur (service) doit se comporter. Celui ci :
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- webnet
networks:
webnet:
- dl du registre l'image qu'on avait envoyée
-
lance sur un service nommé web : 5 instance de cette image (
replicas: 5)
- en limitant la charge (10% cpu, 50 M ram avecresources:
etlimits:
) -
relance de suite un container qui tomberait (
restart_policy:
condition: on-failure)
- map des ports : 80:80
-
indique aux containers de web qu'il faut partager le :80 via le réseau load-balanced nommé
webnet
- et définit le réseau webnet avec les paramètres par défaut
Avant de pouvoir faire un 1er stack deploy
il faut d'abord lancer un docker swarm init
Pour la lancer, il faut lui donner un nom, ici getstartedlab
=> docker stack deploy -c docker-compose.yml getstartedlab
Un container qui fait tourner un service est une tâche ou task. Les tâches ont un ID unique (qui s'incrémente), jusqu'au nb de replicas
qu'on a indiqué dans le docker-compose.yml
.
Pour voir les tasks de son service: docker service ps getstartedlab_web
On les voit quand on liste les containeurs, à moins d'utiliser un filtre sur les services : docker container ls -q
Voir sur un navigateur ou en ligne (curl -4 http://localhost
) le résultat pour voir l'ID du conteneur changer (affiché après le hostname) et le load-balancing fonctionner.
Changer les paramètres dans docker-compose.yml
et redéployer avec docker stack deploy -c docker-compose.yml getstartedlab
Pour voir le résultat : docker container ls -q
On arrete
pour l'appli : docker stack rm
getstartedlab
pour le swarm : docker swarm leave --force
Les clusters Swarm, manager swarm et nodes
https://docs.docker.com/get-started/part4/
Un swarm (essaim) est un groupe de machines (physiques ou vm, on les appelle nodes) qui executent Docker et qui sont dans un cluster. A partir de maintenant les commandes dockers habituelles sont lancées sur un cluster par le manager swarm.
Les managers swarm peuvent utiliser plusieurs stratégies (fichier Compose) pour faire tourner les containers - citons :
- “emptiest node” : remplir les machines les moins utilisées
- "global" : chaque machine a exactement une instance d'un contener spécifié
Les managers Swarw sont les seules machines qui peuvent exe vos commandes, ou authoriser d'autres machines à joindre le swarw en tant que workers. Le port du management swarm est 2377.
Quand le mode swarm est activé, c'est la machine qui l'active qui devient automatiquement le manager swarm.
Définir son swarm : docker swarm init
sur les autres machines (qui seront des workers): docker swarm join
Pour quitter un swarm (quand on est dans un node) : docker swarm leave
créer un cluster (avec une vm) en créant des vm virtualbox (vb) nommées myvm1 et myvm2
docker-machine create --driver virtualbox myvm1
docker-machine create --driver virtualbox myvm2
Voir machines et leurs ip : docker-machine ls
ini swarm et ajout nodes
(rappel : la 1ere machine est le manager, la seconde est worker)
On peux envoyer des commandes aux vm avec docker-machine ssh
. Ici, on a dire à myvm1 d'être le manager swarm (avec un docker swarm init
)
$ docker-machine ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>"
Swarm initialized: current node <node ID> is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token <token> \
<myvm ip>:<port>
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Il faut toujours lancer swarm init et swarm join sur :2377, ou sans préciser de port (conf par défaut). Le :2376 est le port réservé du dockerd. En cas de soucis ssh quand on envoi des commandes au manager swarm, tenter docker-machine --native-ssh ssh myvm1 ...
Le docker swarm init a lancé automatiquement un docker swarm join
préconfiguré à lancer sur les nodes qu'on voudrait ajouter (copier cette commande, la coller en adaptant). Ici, on ajouter myvm2 en worker :
$ docker-machine ssh myvm2 "docker swarm join \
--token <token> \
<ip>:2377"
This node joined a swarm as a worker.
Sur le manager (myvm1), lancer docker node ls
pour voir les nodes de ce swarm :
$ docker-machine ssh myvm1 "docker node ls"
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
brtu9urxwfd5j0zrmkubhpkbd myvm2 Ready Active
rihwohkh3ph38fhillhhb84sk * myvm1 Ready Active Leader
Déployer son app sur un cluster swarm
En gros, on va répéter les actions de la partie "service" (docker stack deploy -c docker-compose.yml getstartedlab
)
On a utilisé docker-machine ssh
pour parle aux vm. On peux aussi configurer son shell "docker-machine"
via docker-machine env <machine>
qui indique à son shell qu'il faut parler au daemon Docker qui tourne sur une vm. C'est ici ce que l'on va faire, car cela nous facilite l'action suivante (car cela va nous permettre d'utiliser le fichier local docker-compose.yml
pour déployer l'application à distance, sans avoir à copier ce fichier nulle part).
Faire un docker-machine env myvm1
-> la dernière ligne affiche ce qu'il nous faut pour parler au manager swarm (à copier/coller et lancer) :
$ docker-machine env myvm1
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/sam/.docker/machine/machines/myvm1"
export DOCKER_MACHINE_NAME="myvm1"
# Run this command to configure your shell:
# eval $(docker-machine env myvm1)
Vérification :
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
myvm1 * virtualbox Running tcp://192.168.99.100:2376 v17.06.2-ce
myvm2 - virtualbox Running tcp://192.168.99.101:2376 v17.06.2-ce
myvm1 est le manager swarm, on a localement le fichier docker-compose.yml, et myvm1
va déployer notre appli (ce qui prend un certain temps).
Sur le manager swarm on peux vérifier que tous les services ont été déployés avec docker service ps <service_name>
Etre dans le dossier où est le docker-compose.yml
et déployer l'appli sur myvm1 avec docker stack deploy -c docker-compose.yml getstartedlab
Si l'image est sur un registre privé et non sur le Hub Docker, se loguer (docker login reg.ex.com)
et ajouter --with-registry-auth
: docker stack deploy --with-registry-auth -c docker-compose.yml getstartedlab
Ca envoie le token de login de son client local vers les nodes du swarm où le service est déployé, en utilisant les logs WAL cryptés. Avec cette info, les nodes peuvent mettre leurs logs dans le registre et pull/récupérer l'image.
Ici, il est conseiller de relire et refaire la partie 3 (services).
$ docker stack ps getstartedlab
ID NAME IMAGE NODE DESIRED STATE
jq2g3qp8nzwx getstartedlab_web.1 john/get-started:part2 myvm1 Running
88wgshobzoxl getstartedlab_web.2 john/get-started:part2 myvm2 Running
vbb1qbkb0o2z getstartedlab_web.3 john/get-started:part2 myvm2 Running
ghii74p9budx getstartedlab_web.4 john/get-started:part2 myvm1 Running
0prmarhavs87 getstartedlab_web.5 john/get-started:part2 myvm2 Running
Parler aux vm avec docker-machine env
et docker-machine ssh
Voir les ip des vm docker-machine ls
Pour parler à vm2 :
-
docker-machine env myvm2
et lancer la commande affichée. Ca ne marche que dans le shell où on a lancé la commande. Undocker-machine ls
montre état, IP, et à avec qui on parle (si on est connecté à une machine). -
docker-machine ssh <machine> "<command>"
on se logue sur une vm (on n'a plus accès aux fichiers locaux de son poste) -
docker-machine scp <file> <machine>:~
pour copier des fichiers sur des machines
Accéder à son cluster (navigateur ou curl) : via l'IP, myvm1 ou myvm2 - on a bien 5 ID de containers affichés, en mode aléatoire. Il y a un routage d'entrée routing mesh, qui assure que pour un service déployé dans un swarm, le port réfère toujours lui-meme, quelque soit le node qui execute le contener.
soucis réseau ? pour que le routage fonctionne dans un swarm, il faut que les nodes écoutent tous 7946 sur tcp/udp (découverte réseau du contener) et 1789 udp (entrée du réseau du contener) avant d'activer le mode swarm.
Utiliser le .yml pour modifier l'appli, pratiquer les part 2 et part 3.
Nettoyage et reboot
Stacks et swarms
Casser le stack docker stack rm getstartedlab
La partie 5 a besoin du swarm. Sinon, pour l'effacer (sur workers et le manager vm2):docker-machine ssh myvm2 "docker swarm leave"
; docker-machine ssh myvm1 "docker swarm leave --force
Défaire la conf du shell (et déconnecte le shell de la vm) : eval $(docker-machine env -u)
Plus à https://docs.docker.com/machine/get-started/#unset-environment-variables...
Relancer les machines docker : docker-machine start <machine-name>
Stack (pile)
https://docs.docker.com/get-started/part5/
Ajout d'un service (sans dépendance) et redeploy
Pour voir comment notre swarm gère les conteners, ouvrir le fichier docker-compose.yml et remplacer son contenu par
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
restart_policy:
condition: on-failure
resources:
limits:
cpus: "0.1"
memory: 50M
ports:
- "80:80"
networks:
- webnet
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
- webnet
networks:
webnet:
Y est ajouté un service lié à web, nommé visualizer : volumes est une clef, donnant au visionneur accès à docker au fichier socket de l'hote + placement, qui assure que ce service ne tournera que sur le manager - jamais sur un worker.
S'assurer que l'environnement est ok, que son shell parle au manager (* sur vm1 sur la sortie d'un docker-machine ls sinon ) ; si ok alors relancer sur le manager docker stack deploy
... Le visionneur est dispo à IP:8080 (pour trouver ip d'un node : docker-machine ls
), à comparer avec le résultat de
docker stack ps getstartedlab
Ce service fonctionne tout seul, on peux le lancer dans toute appli qui l'inclut dans la pile (stack). On va maintenant créer un service qui a une dépendance : le service Redis, qui a un compteur de visite.
Ajout d'une db Redis (avec dépendance)
Cette db va garder les données de l'appli. Le fichier complet en en PJ, on ne montre ici que les ajouts :
redis:
image: redis
ports:
- "6379:6379"
volumes:
- "/home/docker/data:/data"
deploy:
placement:
constraints: [node.role == manager]
command: redis-server --appendonly yes
Les 1eres lignes sont liées à l'image, ce qui est important est la persistance des données de cette pile :
- redis tourne toujours sur le manager et donc utilise toujours le meme fs
- redis accède à un dossier dans le fs de l'hote en tant que /data (de l'interieur du conteneur), c'est là où redis stocke les données
Ensemble, ces lignes créent pour la db Redis un endroit sécure pour y stocker ses données. Sans, redis stocke les données dans le /data du fs du conteneur - qui est effacé si on redeploy par la suite.
Il ne reste qu'à créer le dossier sur le manager : docker-machine ssh myvm1 "mkdir ./data"
S'assurer que son shell parle bien au manager myvm1 et docker stack deploy -c docker-compose.yml getstartedlab
s'assurer que les 3 services tournent avec
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
x7uij6xb4foj getstartedlab_redis replicated 1/1 redis:latest *:6379->6379/tcp
n5rvhm52ykq7 getstartedlab_visualizer replicated 1/1 dockersamples/visualizer:stable *:8080->8080/tcp
mifd433bti1d getstartedlab_web replicated 5/5 orangesnap/getstarted:latest *:80->80/tcp
Naviguer sur quelques pages avec la visioneuse sur une des ip :8080
Déployer son appli
https://docs.docker.com/get-started/part6/
Pour la partie 6, on choisi Docker CE avec Docker Cloud (vers AWS Amazon Web Services, DigitalOcean, et Microsoft Azure).
Pour configurer et déployer, 3 points:
- relier Docker Cloud avec son fournisseur préféré (plusieurs possibilités), en donnant la perm à Docker Cloud d'aprovisionner automatiquement et de dockeriser les vm à notre place
- utiliser Docker Cloud pour créer ses ressources et créer son swarm
- déployer son appli
Le Docker Cloud a 2 modes : le mode swarm (qui est maintenant le mode par défaut) et standard.
Quand on est pret à créer son swarm (le cas en mode swarm) : créer ses nodes (https://docs.docker.com/docker-cloud/getting-started/your_first_node/). Cliquer sur Launch node cluster (attendre) pour provisionner ce node de cluster. Pour voir la progression : clic node, puis Timeline et ouvrir Node Cluster Deploy
Via la vue détaillée Node cluster : voir les statut des nodes, del un node ou tout le cluster, upgrade d'un node, modif le cluster de 1 à 10 nodes.
Une fois déployé (au moins) un node, on peux déployer son 1er service (groupe de conteneurs qui utilisent le meme conteneur image).
Docker c'est :
- une plateforme (isolation...),
-
Docker Engine : appli client/server à 3 composants majeurs :
- dockerd (crée et gère les objets : images, conteners, networks, volumes),
- une API REST (quelles interfaces les programmes utilisent pour parler au daemon et lui dire quoi faire) et
- un client CLI "docker" (qui utilise l'api pour controler dockerd)
https://docs.docker.com/engine/docker-overview/#docker-architecture
https://docs.docker.com/machine/get-started/#unset-environment-variables...