Virt/Docker

De TartareFR
Aller à la navigation Aller à la recherche
Logo Docker

Théorie

Docker est donc une plateforme de virtualisation par conteneur qui, contrairement à la virtualisation sur hyperviseur où de nouvelles machines complètes doivent être créée, va permettre de créer des conteneurs qui vont uniquement contenir une ou plusieurs applications. Empaquetées sous forme de conteneurs, ces applications pourront ainsi être facilement déployées sur tout hôte exécutant Docker, chaque conteneur restant parfaitement indépendant !

Le nom et le vocabulaire de cette technologie n’ont pas été choisis au hasard : tout comme les conteneurs en métal, toujours fabriqués selon les mêmes standards, peuvent être pris en charge par n’importe quel transporteur (et peu importe ce qu’il y a dedans), une application « Dockerisée » doit pouvoir être exécutée sur n’importe quel hôte faisant tourner Docker, peu importe son contenu !

La virtualisation par hyperviseur

Virtualisation par hyperviseur

Avec la virtualisation par hyperviseur de type 2 (VMware Workstation, VirtualBox…), chaque hôte invité virtualise un environnement complet, ce qui permet notamment de pouvoir exécuter un système virtualisé différent du système hôte (typiquement du Windows sur un GNU/Linux par exemple).

La virtualisation par conteneur

Virtualisation par containeur

Dans ce cas, conteneur virtualisé et système hôte sont fortement liés et c’est pour cela que cette technologie, qui existe pourtant depuis longtemps (OpenVZ a déjà presque 10 ans !), était peu répandue jusqu’à maintenant. Certains appellent d’ailleurs ce type de virtualisation la paravirtualisation...

Principe d'utilisation

Docker simplifie l’utilisation d’outils existants, et c’est sa principale force. S’il est possible d’isoler des conteneurs : processus, interfaces réseau, points de montage, c’est grâce à l’utilisation des namespaces Linux. Un processus qui s’exécute dans un espace de nom correspondant à un conteneur ne sera visible que par ce conteneur et le système hôte exécutant ce conteneur. En comparant les deux précédents schémas, on remarque que la virtualisation par conteneur est plus rapide que la virtualisation par hyperviseur car les conteneurs ont directement accès aux ressources matérielles de l’hôte. La consommation de ces ressources pouvant être gérées par l’hôte en question grâce aux control groups (cgroups) du noyau Linux.

Tout ceci fait donc de Docker un chroot dopé aux stéroïdes.

À ses débuts Docker était une couche d’abstraction à LXC car il permettait de s’affranchir de la complexité de ce dernier en gérant pour nous un certain nombre d’opérations. Aujourd’hui Docker va beaucoup plus loin que LXC puisqu’il dispose de sa propre plate-forme : Libcontainer (bien que LXC soit toujours proposé sous forme de plugin).

Et ce qui démarque Docker des autres, c’est la rapidité de la mise en place des flux de travail : tout est fait pour réduire le temps entre le développement, les tests, le déploiement et l’utilisation de votre application en production. Et pour cela, on trouve les images.

Une image est le composant de base de Docker. C’est un instantané d’un système d’exploitation (par exemple Debian). Ces images sont disponibles sur un dépôt public, géré par Docker, appelé le registre.

Les images

Conteneur Docker

L’exemple ci-dessus se compose de deux conteneurs, parfaitement isolés (d’où les couleurs différentes). On trouve à la base les composants nécessaires à Docker, et qui sont fournis par le noyau Linux de l’hôte. On trouve ensuite deux images : Debian et BusyBox.

Une image ne peut être modifiée directement, elle reste toujours en lecture seule.

Remarquez qu’un environnement d’exécution peut nécessiter l’empilement de plusieurs images (ici mariadb, puis apache), rendu possible par les fonctionnalités de copy-on-write des modules de stockages utilisés par Docker (AuFS, Btrfs).

Enfin, on trouve la couche supérieure, accessible en écriture, qui contiendra toutes les modifications apportées à l’application.

Idea.png
Au lancement d'un conteneur exécutant une application à partir d’une image, Docker va monter le système de fichier de l’image souhaitée en lecture seule, et ajouter une couche accessible en écriture par dessus, via UnionFS.

On fait donc de sacrées économies de consommation puisque plusieurs conteneurs utilisant la même image de base utiliseront le même système de fichiers !

Le Hub

Le Hub Docker est un GitHub pour les images Docker.

Pour conserver les modifications apportées à l'application, Il faut enregistrer celles-ci dans une nouvelle image qui sera uniquement composée des différences apportées. Cette image sera identifiée par Docker grâce à un numéro unique, et pourra être pousser (push) vers le dépôt public Docker.

Le Docker Hub est aux images ce que git est au code. Les commandes sont les mêmes.

Installation

Installation du paquet RPM

Docker est supporté sur CentOS 6 et 7, avec de légères différences durant l'installation. Il est vivement recommandé de partir d'un hôte ayant les dernières mises à jour: yum update

  • CentOS 6: paquet présent dans le dépôt EPEL
    yum install docker-io
  • CentOS 7: paquet présent dans le dépôt EPEL
    yum install docker
Warning.png
Version du noyau CentOS 6
Pour utiliser Docker sur CentOS6, il faut, au minimum, un noyau de version 2.6.32-431 car celui-ci contient des adaptations pour exécuter Docker.

Exécuter Docker sans les droits root

La documentation nous indique que le daemon Docker tourne toujours avec l’utilisateur root, et qu’il se connecte à une socket Unix en lieu et place d’un socket TCP. L’utilisateur root est par défaut propriétaire de ce socket Unix, et ne peut donc être accessible qu’avec la commande sudo.

Pour éviter d’utiliser sudo à tort et à travers, nous allons pouvoir créer un groupe Unix nommé docker pour nous y ajouter. Ainsi, les propriétés du daemon docker seront modifiées pour que celui-ci soit accessible en lecture / écriture pour les membres du groupe docker. Certes le daemon doit toujours fonctionner en tant que root, mais si nous utilisons le client docker en tant que membre du groupe docker, alors nous n’aurons plus besoin d’utiliser sudo.

# On ajoute le groupe docker s'il n'existe pas déjà.
groupadd docker
 
# On ajoute l'utilisateur courant (nous) "${USER}" au groupe.
# On peut y mettre n'importe quel utilisateur
# Il faudra se reconnecter pour que les modifications prennent effet.
gpasswd -a ${USER} docker
 
# On redémarre le daemon.
service docker restart

C’est du bonus hein… Cela permet aussi de gérer la surface d’attaque de Docker, mais vous pouvez très bien sauter cette étape et continuer à utiliser Docker avec sudo.

Tests

docker version
Client version: 1.7.1
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 786b29d/1.7.1
OS/Arch (client): linux/amd64
Server version: 1.7.1
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 786b29d/1.7.1
OS/Arch (server): linux/amd64
docker info
Images: 7
Storage Driver: devicemapper
 Pool Name: docker-253:0-1183660-pool
 Pool Blocksize: 65.54 kB
 Backing Filesystem: extfs
 Data file: /dev/loop0
 Metadata file: /dev/loop1
 Data Space Used: 957.5 MB
 Data Space Total: 107.4 GB
 Data Space Available: 24.65 GB
 Metadata Space Used: 1.507 MB
 Metadata Space Total: 2.147 GB
 Metadata Space Available: 2.146 GB
 Udev Sync Supported: true
 Deferred Removal Enabled: false
 Data loop file: /var/lib/docker/devicemapper/devicemapper/data
 Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata
 Library Version: 1.02.95-RHEL6 (2015-09-08)
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 2.6.32-573.22.1.el6.x86_64
Operating System: <unknown>
CPUs: 8
Total Memory: 7.685 GiB
Name: webdev-test.b2pweb.com
ID: TZXP:Z74H:7XCC:JMST:ZAKF:R5Y5:DSOR:JHGO:Z4GC:T3SZ:662F:3NR2

Les conteneurs

Pour récupérer une image, on va interroger le docker hub pour lister toutes les images du registre:

docker search centos
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                          The official build of CentOS.                   2147      [OK]       
jdeathe/centos-ssh              CentOS-6 6.7 x86_64 / CentOS-7 7.2.1511 x8...   20                   [OK]
jdeathe/centos-ssh-apache-php   CentOS-6 6.7 x86_64 / Apache / PHP / PHP M...   16                   [OK]
nimmis/java-centos              This is docker images of CentOS 7 with dif...   8                    [OK]
torusware/speedus-centos        Always updated official CentOS docker imag...   7                    [OK]
nickistre/centos-lamp           LAMP on centos setup                            3                    [OK]
centos/mariadb55-centos7                                                        3                    [OK]
[...]

Un grand nombre de résultats sont proposés. On observe que le premier résultat indique une image CentOS officielle, ce qui nous assure qu’elle a été validée par l’équipe de Docker. Les images gérées par l’équipe de Docker se remarquent par le format de leur nom, qui est de la forme nom-image alors que les non-officielles sont plutôt de la forme utilisateur/nom-image.

On récupère l'image officielle CentOS 7 (latest)

docker pull centos
latest: Pulling from centos
47d44cb6f252: Pull complete 
8aa7f4a1dd13: Pull complete 
e0f5867add13: Pull complete 
eeb3a076a0be: Pull complete 
Digest: sha256:1b9adf413b3ab95ce430c2039954bb0db0c8e2672c48182f2c5b3d30373d5b71
Status: Downloaded newer image for centos:latest

ainsi quer la version 6

docker pull centos:6
6: Pulling from centos
9868edceea88: Pull complete 
e0eab6e60b7e: Pull complete 
61bf77ab8841: Pull complete 
47d44cb6f252: Already exists 
Digest: sha256:57f0027b92985edbd0eb87818b73d5dd771dd5955e6b794d624c8a79a4bd4795
Status: Downloaded newer image for centos:6

On liste les images déjà téléchargées. La sortie de la commande suivante indique que nous avons récupéré les image portant l’ID 61bf77ab8841 et eeb3a076a0be dans le dépôt intitulé « centos ». Un ID permet d’identifier de manière unique la version d’une image. Ensuite, comme un ID n’est pas forcément explicite pour désigner une version, on lui affecte un ou plusieurs tags, ici « latest » et « 6 ». Plusieurs tags peuvent effectivement désigner la même image, mais chaque version d’image ne possède qu’un ID.

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              6                   61bf77ab8841        2 weeks ago         228.9 MB
centos              latest              eeb3a076a0be        2 weeks ago         196.7 MB

L'empilement peut être affiché avec l'option --all

docker images --all
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              6                   61bf77ab8841        2 weeks ago         228.9 MB
<none>              <none>              e0eab6e60b7e        2 weeks ago         228.9 MB
<none>              <none>              9868edceea88        2 weeks ago         228.9 MB
centos              latest              eeb3a076a0be        2 weeks ago         196.7 MB
<none>              <none>              e0f5867add13        2 weeks ago         196.7 MB
<none>              <none>              8aa7f4a1dd13        2 weeks ago         196.7 MB
<none>              <none>              47d44cb6f252        7 months ago        0 B

Les images intermédiaires correspondent aux différentes commandes qui ont été utilisées pour générer l’image finale. Ces commandes peuvent être affichées avec la commande history.

docker history centos:6
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
61bf77ab8841        2 weeks ago         /bin/sh -c #(nop) CMD ["/bin/bash"]             0 B                 
e0eab6e60b7e        2 weeks ago         /bin/sh -c #(nop) LABEL name=CentOS Base Imag   0 B                 
9868edceea88        2 weeks ago         /bin/sh -c #(nop) ADD file:ae8f506cbd1f016c67   228.9 MB            
47d44cb6f252        7 months ago        /bin/sh -c #(nop) MAINTAINER The CentOS Proje   0 B

Premiers lancements

On lance notre premier conteneur. Évidemment l'intérêt est purement éducatif, car celui-ci ne fera qu'afficher Hello World! et se terminera.

Important.png
Durée de vie des conteneurs
La durée de vie d’un conteneur dépend directement du temps de vie des processus qui y sont exécutés.
docker run centos:latest /bin/echo 'Hello World!'
Hello World!

On lance maintenant l'interpréteur Bash à l'intérieur de notre conteneur. L'option i laisse l'entrée standard ouverte et l'option t alloue un pseudo-terminal à la commande.

docker run -t -i centos:6 /bin/bash
[root@a3bcca2ae195 /]# hostname
a3bcca2ae195
[root@a3bcca2ae195 /]# exit
exit

On liste nos conteneurs (l'option -a permet d'afficher tous les conteneurs car seul les actifs sont affiché par défaut).

docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED              STATUS                          PORTS               NAMES
a3bcca2ae195        centos:6            "/bin/bash"            35 seconds ago       Exited (0) 12 seconds ago                           angry_goodall       
f947fb083eaa        centos:6            "/bin/echo 'Hello Wo   About a minute ago   Exited (0) About a minute ago                       ecstatic_kirch      
b6710cdfbcb1        centos:latest       "/bin/echo 'Hello Wo   About a minute ago   Exited (0) About a minute ago                       lonely_feynman

On peut visualiser tous les détails d'une image

docker inspect centos:6
[
{
    "Id": "61bf77ab884102c059826f37af32b766aec3a0145af35dbc296bc33754e74757",
    "Parent": "e0eab6e60b7ea4336660dfcbc7ce837621f191d7d6ea587cdf225eecd2001dc6",
    "Comment": "",
    "Created": "2016-04-01T21:29:01.147650406Z",
    "Container": "01a4934c6001e17bfa875876616d915ee5c7a2fdd094f63c4ff84c70a9da3c43",
    "ContainerConfig": {
        "Hostname": "4d7e41fcce2c",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "PortSpecs": null,
        "ExposedPorts": null,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": null,
        "Cmd": [
            "/bin/sh",
            "-c",
            "#(nop) CMD [\"/bin/bash\"]"
        ],
        "Image": "e0eab6e60b7ea4336660dfcbc7ce837621f191d7d6ea587cdf225eecd2001dc6",
        "Volumes": null,
        "VolumeDriver": "",
        "WorkingDir": "",
        "Entrypoint": null,
        "NetworkDisabled": false,
        "MacAddress": "",
        "OnBuild": null,
        "Labels": {
            "build-date": "2016-03-31",
            "license": "GPLv2",
            "name": "CentOS Base Image",
            "vendor": "CentOS"
        }
    },
    "DockerVersion": "1.9.1",
    "Author": "The CentOS Project \u003ccloud-ops@centos.org\u003e",
    "Config": {
        "Hostname": "4d7e41fcce2c",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "PortSpecs": null,
        "ExposedPorts": null,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": null,
        "Cmd": [
            "/bin/bash"
        ],
        "Image": "e0eab6e60b7ea4336660dfcbc7ce837621f191d7d6ea587cdf225eecd2001dc6",
        "Volumes": null,
        "VolumeDriver": "",
        "WorkingDir": "",
        "Entrypoint": null,
        "NetworkDisabled": false,
        "MacAddress": "",
        "OnBuild": null,
        "Labels": {
            "build-date": "2016-03-31",
            "license": "GPLv2",
            "name": "CentOS Base Image",
            "vendor": "CentOS"
        }
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Size": 0,
    "VirtualSize": 228912764
}
]

Démonisation

On va daemoniser notre conteneur avec l'option d. Cette fois la sortie est l'ID du conteneur.

docker run -t -i -d centos:6 /bin/bash
713ed98359e25eebd6316831d192c9094d5ec7b5bb8f1907ad444db8eabbb298

Afin de se simplifier la vie, on va obtenir son petit nom

docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
713ed98359e2        centos:6            "/bin/bash"         2 minutes ago       Up 2 minutes                            gloomy_jones
  • Pour visualiser la sortie standard de notre conteneur daemonisé, on lance la commande
    • avec l'ID
      docker logs 713ed98359e25eebd6316831d192c9094d5ec7b5bb8f1907ad444db8eabbb298
    • avec son nom
      docker logs gloomy_jones
  • On peut s'attacher à ce conteneur
    docker attach gloomy_jones
  • Le mettre en pause
    docker pause gloomy_jones
  • Le sortir de sa léthargie imposée
    docker unpause gloomy_jones
  • L'arrêter
    docker stop gloomy_jones
  • Le renommer
    docker rename gloomy_jones centos6
  • Le supprimer
    docker rm centos6

Les commits

Les liaisons

Les volumes