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

Note Docker Pierre 1

Docker sur Openclassroom 2

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é.

Tiré de Images and layers dans la doc officielle 8

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

Docker file ref 16

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.

Différence entre ADD et COPY 18

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

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

    Doc sur les volumes drivers 26

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.

Page officielle de la documentation sur les service 31

Source ci-dessus sur devopssec.fr 32

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 inteeragit 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 !

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

Voir Docker à l’oeuvre

L”exemple de prakhar1989 catnip 35 dont le fichier dockerfile est accessible sous github.

Docker sample home 36

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 37

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 38

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