Docker*¶
- Auteur:
J.Soranzo
- Date:
Janvier 2020 2019
- Societe:
VoRoBoTics
- Entity:
VoLAB
Start-up /install¶
Pas la même install qu’il s’agisse de Windwos10pro d’un côté et Windwos10 family ou 7 de l’autre
Je me permet un petit commentaire sur ce cours. Il n’est vraiment pas terrible !
Une pauvre recette de cuisine sur dockerfile et sur compose très incomplète.
Par exemple on y évoque pas le partage de volume.
L’exercice de fin de chapitre sur nginx est juste une blague ! Attention tips, on ne demande pas de démarrer le serveur nginx ni même de la paraméter, juste de l’installer ! Faites au plus simple
Docker Community Edition (Linux seulement) ;
Docker Desktop (Mac ou Windows) ;
Docker Enterprise (Linux seulement).
Docker toolbox (Pour wondows 7 par exemple)
Un bon tut, je crois : docker-curriculum [3]
Au cours de ce tutoriel en englais on apprends à déployer une apppli web static et 2 appli dynamiques
Dockerhub¶
Le site docker hub [4] directement sur la page de recherche/exploration
3 702 709 available images le 06/07/2020.
on y trouve par exemple une image nommée gcc, gitlab, nextcloud, owncloud, mongo-express, drupal…
Notes¶
Définitions¶
J’aime bien cette définition : Quand une application tourne dans un conteneur, elle a l’illusion d’être la seule à avoir accès au système (sous-entendu l’OS). Ceci n’est pas sans rappeler la virtualisation, où un OS invité a l’illusion d’être le seul à exploiter le hardware sous-jacent.
Par principe Docker ne doit faire tourner qu’un seul processus.
Ainsi, dans le cas d’une stack LAMP (Linux, Apache, MySQL, PHP), nous devons créer 3 conteneurs différents, un pour Apache, un pour MySQL et un dernier pour PHP.
Immutable
Ce que c’est
Docker is a platform for developers and sysadmins to build, share, and run applications.
ça c’est la définition officielle [5] . Cela ne dit pas « développer » de quelles applications. Le gros sous entendu c’est que ce sont des applications plutôt à forte propension WEB.
Article très intéressant Docker est mort, vive Docker [6] sur le fonctionnement de docker (2019)
Images: la carcasse: quand on fait un docker build on crée une image « An image is a read-only template »
Container: l’image en cours d’exécuton : quand on fait docker run « A container is a runnable instance of an image »
Layer: chaque commande d’un dockerfile.
Ma présentation rapide pratique¶
Docker ça fait tourner des images que l’on peut récupérer sur dockerhub ou dans un autre dépôt. Ok c’est cool mais ce qui est encore plus cool c’est qu’on peut construire de nouvelles images basées sur des images existantes à la façon des poupées russes (c’est le rôle des dockerfiles voir Créer une image ). ça c’est déjà pas mal mais ce n’est pas suffisant.
En effet, comme docker ne fait tourner qu’une seule tâche, process… ou quelque soit le terme utilisé, on pourrait dire aussi un seul truc, eh bien il faut en lancer plusieurs, le cas type est le serveur web qui utilise une base de données au travers de php pour cela il faut lancer 3 images. C’est la qu’intervient docker compose voir Docker compose
Une images n’est pas un container et inversement. Donc, il faut apprendre à manipuler les 2. On peut créer une image sans pour autant la lancer et on peut lancer une image sans la créer. On peut également effacer des images et des container de son système, on peut lister les 2 mais pas avec les mêmes commandes !
Quelques part c’est un peu frustrant au début. Exemple:
docker run --interactive --tty ubuntu bash
On a alors un Ubuntu mais c’est une coquille vide. Les principales commandes n’y sont pas ! Il faut alors soit devenir un gourou des images du docker hub ou le roi des fichiers dockerfile
Après quelques temps je me rends compte que Docker c’est bien mais tout est éphémère ! Exemple
docker run -it busybox sh
puis on pass des commandes, on peut créer des fichier...
exit
et quand on revient il n'y a plus rien !
Cela dit ce n'est pas un handicap, c'est même voulu mais c'est déroutant pour les novices
Grands principes¶
Tiré de Docker Architecture dans la doc officielle [7]
dockerd : docker deamon gère les images, container, réseaux et volumes
dockerapi : s’adresse à dockerd pour éxécuter les choses
dockercli ou docker client s’adresse à l’api qui s’adresse …
docker registry : dépôt : docker hub est le registry par défaut mais on peut utiliser son propre registry
Les layers: chaque instructions d’un dockerfile constitue un layer, chaque layer sauf le tout dernier est en read-only. Chaque nouveau layer est constitué d’un petit nombre de différences par rapport au précédent. Les layers sont empilés les uns au dessus des autres avec en plus au dessus un layer dit container layer en lecture/écriture dans lequel sont fait les modifs.
La majeur différence entre une images et un container est en fait représentée par ce dernier layer en lecture écriture dont le contenu disparaît quand le container est arrêté.
Ma vision du fonctionnement¶
docker run : regarde si une image correspondant au nom fourni existe et la lance
(devient un container)
Si elle n’existe pas en local, docker essais de la trouver sur le dépôt officiel et la charge avant de la lancer et ainsi de créer le container. Dans ce cas on parle d’image de base. Docker run attribue automatiquement un nom au container ainsi qu’un id.
L’étape suivent et de créer ses propres images en dérivant des images de base. C’est le rôle de la
commande build. En général, on lui fourni un nom pour reconnaître son image qui après construction
se retrouve dans la liste forunie par docker images
docker bu
Documentation¶
Officiellement c’est là : Docker’s documentation [9]
Mais c’est mieux de commencer par l”onglet Product manual [10] et plus particulièrement avec les
docker for Windows [11], docker for Mac [12]
La référence pour les options et commandes de la ligne de commande est: Use the Docker command line [13]
Retour dans la doc officielle.¶
Rappel du chemin vers la doc officielle [14]
Use multi-stage builds to keep your images lean : c’est déjà du Docker de haut vol !
Manage application data using volumes and bind mounts
Scale your app with Kubernetes
Scale your app as a Swarm service
General application development best practices
J’attaque le premier point mais c’est plus le deuxième qui m’intéresse
Commandes principales¶
Il y a des centaines de commandes docker (61 commandes principale en version 19.03). Caractéristiques : elles commence toutes par docker. Et même la plupart on des sous commandes. Au total, ça doit peut-être même faire des milliers avec Chacune des dizaines d’options.
Voir sur Note Docker Pierre [1] il y a tout ce qu’il faut !
Cheatsheet ?
docker run -d -p 8080:80 nginx
docker images <=> docker image ls
docker ps : shows you all containers that are currently running
docker ps -a : shows all containers (y compris les container stoppés)
docker rmi : efface une ou plusieurs images
docker rm : efface un container
docker start -i container_name
docker restart
docker build -t _nom .
docker container prune <=> docker rm $(docker ps -a -q -f status=exited)
docker run --interactive --tty ubuntu bash
docker inspect container_name
docker stop _nom
docker volume create nomDuVolume
docker volume ls
docker volume inspect nomDuVolume
docker create : comme run mais sans start
docker network ls : liste les réseaux
docker exec -it container_id bash : permet de passer en CLI dans un container encours
On ne le dira jamais assez :
Danger
Do not use PowerShell ISE
Interactive terminals do not work in PowerShell ISE (but they do in PowerShell). See docker/for-win/issues/223.
Créer une image¶
Dans un répertoire vierge créer un fichier nommer dockerfile
Lancer la commande docker build (éventuellement avec -t pour préciser un nom d’image)
Syntaxe des fichiers Dockerfile¶
Les commandes dans les dockerfile ne sont pas sensibles à la casse mais par convention on les met en majuscules pour les distinguer des arguments.
Les lignes de commentaire COMMENCE par un #
La commande pour compiler, la plus simple, est alors
docker build .
Il est bon aussi de bien lire : Best practices for writing Dockerfiles [17] :
Mouais, build through stdin ou Understand build context sont plus des possibilités offertes qu’il faut connaître à mes yeux que des best practices. En revenche ensuite, se trouve de vraies best practices [15]
comme : ne pas faire apt-get upgrade
Le build ne dispense pas de faire un run ensuite
Les principale commandes:
ARG : défini une variable qui peut être redéfinie dans la ligne de commande (disparait après un FROM)
ENV : défini une varibale qui persiste dans l'image finale
FROM
RUN exécute une commande system dans un layer au dessus du layer actuel
COPY / ADD : copie les fichiers de <src> vers image <dest path> (absolu ou relatif a WORKDIR)
WORKDIR
EXPOSE
VOLUME
CMD : 1 par Dockerfile, son interêt principal est de passer des param par defaut à ENTRYPOINT
ENTRYPOINT : exécute un process dans le container (auquel on passer des paramètres dans la CLI)
ADD vs COPY: ADD permet de spécifier un url en tant que src et de détarer.
Un exercice¶
un ubuntu installer nano copier un fichier texte et se retrouver dans le prompt
Solution:
dockerfile
FROM ubuntu
RUN apt-get update -yq \
&& apt-get install nano -yq
docker build -t mybuntu
docker run -ti mybuntu
Docker compose¶
Docker compose permet de lancer plusieurs images en même temps.
Dans un répertoire vide (conseillé) créer un fichier docker-compose.yml
Compose file version 3 reference [19]
Pour exécuter les fichier yml la commande minimum est:
docker-compose up
On peut aussi ajouter un fichier pour des variables [20] . Le nom de ce fichier par défaut est .env
Petit trucs sur la substitution des variables denvironnement:
On peut préciser une valeur par défaut [21] : ${WORDPRESS_DATA_DIR:-./wordpress}:/var/www/html
Piloter un port série de la machine hote¶
https://www.losant.com/blog/how-to-access-serial-devices-in-docker
volumes et bind mounts¶
Ce sont 2 manières différentes d’avoir des données persistantes.
Les volumes sont mieux que les binds mounts:
- Volumes are easier to back up or migrate than bind mounts.
- You can manage volumes using Docker CLI commands or the Docker API.
- Volumes work on both Linux and Windows containers.
- Volumes can be more safely shared among multiple containers.
- Volume drivers let you store volumes on remote hosts or cloud providers, to encrypt the
contents of volumes, or to add other functionality.
- New volumes can have their content pre-populated by a container.
Les volumes sont indépendants de la structure du filesystem de la machine hôte.
When you use a bind mount, a file or directory on the host machine is mounted into a container.
Il y a 2 syntaxes possibles –mount ou –volume (abrégeable en -v). La syntaxe –mount est plus simple
Les volumes sont stockés quelque part dans le système Docker mais on ne sait pas trop bien où. Non, on pourrait préciser un répertoire dans la commande -v mais ce n’est pas claire dans la doc C’est sous-entendu sur le site de AJDAINI Hatim article sur les volumes [22]
Avertissement
Les options de syntaxe -v ou –mount peuvent aussi bien être utilisées pour monter un volume que pour faire du bind mount
On peut soit créer un volume avec des commandes Docker docker volume create ou directement quand on lance un container avec l’option -v de la commande run
when you use a volume, a new directory is created within Docker’s storage directory on the host
machine, and Docker manages that directory’s contents.
Doc officielle sur les volumes [23] et référence officielle des commandes docker volume [24]
Avertissement
Fonctionne sous windows10: docker run -ti -v %cd%:/tmp mybuntu (à condition d’être dans le bon répertoire)
La syntaxe powershell est différent ainsi que sous Linux
Syntaxe current dir sous Stackoverflow [25]
Encore quelques informations tirées de la doc officielle sur les volumes:
Un volume peut être créé ou monté en read only, par plusieurs container en même temps.
Les volumes drivers sont des plugin qui permettent de créer des volumes à l’extérieur du système Docker comme vieux/sshfs plugin
Volume et sauvegarde¶
En parcourant la doc sur les volumes, après start a container with volume, je suis tombé sur : start a service with volumes ! ? Qu’est-ce donc que cette histoire de service ? Voir Docker services/Swarm
La sauvegarde :
En fait, l’idée est de monter un container avec un bind et un –volume-from un autre container nommé et de faire un tar cvf du volume vers le bind !!
Tout ceci expliqué dans la doc officielle [27]
Et pour la restauration, on procède de manière inverse.
Networks¶
Doc officielle networking [28]
Tout d’abord, il faut savoir qu’il y a 5 type de driver de réseau dans Docker:
User-defined bridge networks are best when you need multiple containers to communicate on the same Docker host.
Host networks are best when the network stack should not be isolated from the Docker host, but you want other aspects of the container to be isolated.
Overlay networks are best when you need containers running on different Docker hosts to communicate, or when multiple applications work together using swarm services.
Macvlan networks are best when you are migrating from a VM setup or need your containers to look like physical hosts on your network, each with a unique MAC address.
Third-party network plugins allow you to integrate Docker with specialized network stacks.
Pour mon usage, le driver par défaut semble suffisant. Les autres drivers sont surtout utile pour des container fonctionnant sur des démon différents. Et surtout les user-define bridge apparemment.
Par défaut docker crée un bridge nommé bridge.
Il y a comme pour les volumes des commandes pour gérer les network:
docker network ls
docker network inspect avec un nom
docker network create
docker network connect et disconnect
Doc officielle docker network bridge [29]
Et aussi la référence de la ligne de commande docker network create [30]
Docker services/Swarm¶
Notion de Swarm : Un Swarm est un groupe de machines exécutant le moteur Docker et faisant partie du même cluster. Docker swarm vous permet de lancer des commandes Docker auxquelles vous êtes habitué sur un cluster depuis une machine maître nommée manager/leader Swarm. Quand des machines rejoignent un Swarm, elles sont appelés nœuds.
General application development best practices¶
Page officielle Docker development best practices [33]
On this page:
How to keep your images small
Where and how to persist application data
Use CI/CD for testing and deployment
Differences in development and production environments
Il s’agit de règles de bon sens : commencer avec une image appropriée…
Un point intéressant dans la première partie How to keep your images small est
To keep your production image lean but allow for debugging, consider using the production image as
the base image for the debug image. Additional testing or debugging tooling can be added on top
of the production image.
Dans la deuxième partie:
Avoid storing application data in your container’s writable layer using storage drivers
Je ne savais même pas qu’on pouvait le faire !
One case where it is appropriate to use bind mounts is during development. For production, use a volume instead,
Accéder aux données cachées de Docker sous Windows y compris les volumes¶
Indication
If you have linux containers on a Windows 10 machine, containers are stored in the MobyLinuxVM.vhdx file. You can’t mount or explore that file AFAIK, but you can still list the containers inside that machine using this “blue pill” trick blog.jongallant.com/2017/11/ssh-into-docker-vm-windows by default containers are stored in the linux path /var/lib/docker in that virtual machine (you can confirm that linux path from a docker info command)
Et effectivement j’ai testé:
docker run --privileged -it -v /var/run/docker.sock:/var/run/docker.sock jongallant/ubuntu-docker-client
On se retrouve alors dans un container (option -it) où on lance un deuxième container:
docker run --net=host --ipc=host --uts=host --pid=host -it --security-opt=seccomp=unconfined --privileged --rm -v /:/host alpine /bin/sh
On a alors un prompt et on peut y taper chroot /host… Nouveau prompt mais d’aspect identique au précédent (seul un ls peut révéler qu’on a changé d’endroit).
Dans cet endroit un ls à la racine donne des choses bizarre ! Mais ce qui importe c’est ce qui se trouve dans le dossier /var/lib/docker
La cession complète:
docker run --privileged -it -v /var/run/docker.sock:/var/run/docker.sock jongallant/ubuntu-docker-client
root@693563b5330f:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@693563b5330f:/# docker run --net=host --ipc=host --uts=host --pid=host -it --security-opt=seccomp=unconfined --privileged --rm -v /:/host alpine /bin/sh
/ # ls
bin dev etc home host lib media mnt opt proc root run sbin srv sys tmp usr var
/ # chroot /host
/ # pwd
/
/ # ls
A C E G I K M O Q S U W Y a bin d e f h host_mnt j l m mnt o p q root s sendtohost sys tmp usr var x z
B D F H J L N P R T V X Z b c dev etc g home i k lib media n opt proc r run sbin srv t u v w y
/ # cd /var/lib/docker
/var/lib/docker # ls
builder buildkit containerd containers image network overlay2 plugins runtimes swarm tmp trust volumes
My tips¶
Mode interractif : je suis resté blocké sur ce pb: soit un nginx lancer en mode ti avec en plus -d Comment on interagit avec le container (à part par le navigateur)
Comment sait-on qu’un container a été lancé en mode ti ?
Disque image locations : peut-être configurer dans la fenêtre setting de docker onglet Ressources/ advanced
Partage de données entre hôte et containers:
File sharing is required for mounting volumes in Linux containers, not for Windows containers.
For Linux containers, you need to share the drive where the Dockerfile and volume are located.
Otherwise, you get file not found or cannot start service errors at runtime.
See Volume mounting requires shared drives for Linux containers.
Docker dashboard : gestion intéractive graphique des container/appli compose en cours d’éxécution
Docker port¶
Dans docker port container_name L’affichage produit est
container --> localhost:port
Alors que dans:
docker run -p 8888:80 site
On a d’abord le port de l’hôte suivi du port de l’image !
Faire du python2 sans l’installer¶
docker run -i -t python:2
docker run, start and restart¶
run créé un nouveau container avec un nouveau top layer vierge.
start permet de relancer un container arrêté sans perdre les données temporaire
restart fair un stop puis un start !
Savoir si une image a été montée avec un volume ou un bind¶
docker inspect container_name
Docker run –name –rm¶
Tout est dans le titre, on peut donner un titre à container ! ne s’abrège pas.
–rm le supprime quand on sort, très pratique pour les tests de la commande run elle-même
Portainer¶
Repository locaux¶
Voir Docker à l’oeuvre¶
L”exemple de prakhar1989 catnip [37] dont le fichier dockerfile est accessible sous github.
Vocabulaire¶
Stateful vs Stateless : se dit à propos d’une application ou d’un service et par extension cela s’applique aux container.
Stateless vs Stateful article sur contino.io [39]
A stateless application is one that neither reads nor stores information about its state from one time that it is run to the next.
Une explication sur Publicis Sapiens [40]
Un moyen de stockage est nécessaire pour une application, un service stateful.
Images :
Base images are images that have no parent image, usually images with an OS like ubuntu, busybox or debian.
Child images are images that build on base images and add additional functionality.
Then there are official and user images, which can be both base and child images.
Official images are images that are officially maintained and supported by the folks at Docker. These are typically one word long. In the list of images above, the python, ubuntu, busybox and hello-world images are official images.
User images are images created and shared by users like you and me. They build on base images and add additional functionality. Typically, these are formatted as user/image-name.
detached mode mode détaché : à compléter le 6/07/2020, en gros c’est la même chose que & à la fin d’un commande Linux
Swarm mode