Docker comme solution de virtualisation : installation

Source : Wikimédia. Image sous licence Apache 2.

Source : Wikimédia. Image sous licence Apache 2.

On va même aller un peu plus loin parce que l’installation est un peu trop facile…

Bienvenue dans la deuxième partie de ma série d’articles sur Docker ! Rappelez-vous la dernière fois nous avions fait un peu de théorie. On va maintenant utiliser nos petites mimines et commencer à jouer avec les images Docker. Mas avant, installation.

Comme d’habitude, je travaille sur la dernière version stable de Debian (7.8 aujourd’hui), en machine virtuelle et fraîchement installée.

Installation de Docker

Ici pas de secret, il suffit de suivre les instructions proposées par le site officiel. On nous informe que Docker a besoin du noyau Linux 3.8 ou supérieur pour fonctionner, et que Debian Stable est toujours sur le noyau 3.2. On va donc devoir activer les dépôts backports afin d’aller y récupérer la dernière version du noyau Linux.

Pour cela il suffit d’éditer le fichier /etc/apt/sources.list, et d’y ajouter :

deb http://http.debian.net/debian wheezy-backports main

On enregistre, puis :

sudo apt-get update
sudo apt-get -t wheezy-backports install linux-image-amd64

Redémarrons pour que le nouveau noyau soit chargé. Nous pouvons enfin récupérer le script d’installation de Docker 🙂

$ curl -sSL https://get.docker.com/ | sh

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 à un 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.

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.

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

Alors, c’était dur ?

$ docker version
Client version: 1.4.1
Client API version: 1.16
Go version (client): go1.3.3
Git commit (client): 5bc2ff8
OS/Arch (client): linux/amd64
Server version: 1.4.1
Server API version: 1.16
Go version (server): go1.3.3
Git commit (server): 5bc2ff8

Commençons à jouer avec les images

Avant de pouvoir commencer à jouer avec les conteneurs, il va falloir récupérer une image. Souvenez-vous dans l’article précédent, je vous avais expliqué que les images Docker sont des instantanés de systèmes d’exploitation sur lesquels nous allons pouvoir travailler et manipuler des conteneurs. Je vous avais même fait un joli schéma :

Les images Docker

Les images Docker

Tout un tas d’images sont maintenues et disponibles sur le registre officiel : le Docker Hub.

Imaginons que je souhaite récupérer une image d’Ubuntu. Je vais alors utiliser la commande search pour retrouver toutes les images Ubuntu du registre :

$ docker search ubuntu
NAME                                DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
ubuntu                              Official Ubuntu base image                      1159      [OK]       
dockerfile/ubuntu                   Trusted automated Ubuntu (http://www.ubunt...   39                   [OK]
ansible/ubuntu14.04-ansible         Ubuntu 14.04 LTS with ansible                   30                   [OK]
dockerfile/ubuntu-desktop           Trusted automated Ubuntu Desktop (LXDE) (h...   20                   [OK]
ubuntu-upstart                      Upstart is an event-based replacement for ...   17        [OK]       
[...]

Vous verrez qu’un grand nombre de résultats sont proposés, c’est pourquoi j’ai volontairement tronqué la sortie. On observe que le premier résultat indique une image d’Ubuntu 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.

Je décide de récupérer l’image Ubuntu officielle :

$ docker pull ubuntu:14.04

Vous noterez l’ajout du :14.04 au nom de l’image. Ceci afin d’éviter de récupérer toutes les version d’Ubuntu présentes dans le dépôt Ubuntu. Après quelques secondes de téléchargement (l’image fait 200Mo), la nouvelle image est prête !

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              14.04               b39b81afc8ca        13 hours ago        188.3 MB
Heu on pourrait avoir des infos sur ce qu’est un Tag ou un ID ?

La sortie de la commande précédente indique que nous avons récupéré l’image portant l’ID b39b81afc8ca dans le dépôt intitulé « ubuntu ». Un ID permet d’identifier de manière unique la version d’une image. Et oui, un dépôt contient plusieurs versions d’une image, sous forme de couches de systèmes de fichiers. Je vous en avais parlé précédemment.

Ensuite, comme un ID n’est pas forcément explicite pour désigner une version, on lui affecte un ou plusieurs tags, ici « 14.04 ». Plusieurs tags peuvent effectivement désigner la même image, mais chaque version d’image ne possède qu’un ID.

Cet empilement de version et de systèmes de fichier peut être affiché avec l’option --all

$ docker images --all
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              14.04               b39b81afc8ca        13 hours ago        188.3 MB
<none>              <none>              615c102e2290        13 hours ago        188.3 MB
<none>              <none>              837339b91538        13 hours ago        188.3 MB
<none>              <none>              53f858aaaf03        13 hours ago        188.1 MB
<none>              <none>              511136ea3c5a        19 months ago       0 B
Ok, mais à quoi correspondent toutes ces images intermédiaire ?

Je ne voudrais pas vous embrouiller tout de suite… Elles correspondent en fait 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 ubuntu:14.04
IMAGE               CREATED             CREATED BY                                      SIZE
b39b81afc8ca        13 hours ago        /bin/sh -c #(nop) CMD [/bin/bash]               0 B
615c102e2290        13 hours ago        /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/   1.895 kB
837339b91538        13 hours ago        /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic   194.5 kB
53f858aaaf03        13 hours ago        /bin/sh -c #(nop) ADD file:ca5b63647c6b7a419e   188.1 MB
511136ea3c5a        19 months ago                                                       0 B

Nous y reviendrons quand nous créerons nos propres images, pas de panique 🙂

Et tout ce bazar, il est stocké où ?
$ docker info
docker info
Containers: 0
Images: 5
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Dirs: 5
Execution Driver: native-0.2
Kernel Version: 3.16.0-0.bpo.4-amd64
Operating System: Debian GNU/Linux 7 (wheezy)
CPUs: 2
Total Memory: 3.86 GiB
Name: dev
ID: E7WT:PPQD:Z6IE:ZGW2:42EC:T5IE:KXLQ:CIRB:WI54:KJG7:KUYM:SYFB
WARNING: No memory limit support
WARNING: No swap limit support

Voilà toutes les informations relatives notre installation de Docker. Pour répondre à la question, la ligne qui nous intéresse est donc le Root Dir, soit /var/lib/docker/aufs :

$ sudo ls -l /var/lib/docker/aufs/*
/var/lib/docker/aufs/diff:
total 20
drwxr-xr-x  2 root root 4096 Jan 17 11:42 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158
drwxr-xr-x 21 root root 4096 Jan 17 11:44 53f858aaaf03033e088d357df23e311d71aa93ac578ef39aa8230580ea95076f
drwxr-xr-x  3 root root 4096 Jan 17 11:44 615c102e2290b70d38d89c03a1ad263da8bd8b05fb7fc8479174e5fd2215520e
drwxr-xr-x  6 root root 4096 Jan 17 11:44 837339b915388417a842c87a681a5448df2509068c8d3efd1638f1fad2eacea2
drwxr-xr-x  2 root root 4096 Jan 17 11:44 b39b81afc8cae27d6fc7ea89584bad5e0ba792127597d02425eaee9f3aaaa462
 
/var/lib/docker/aufs/layers:
total 16
-rw-r--r-- 1 root root   0 Jan 17 11:42 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158
-rw-r--r-- 1 root root  65 Jan 17 11:44 53f858aaaf03033e088d357df23e311d71aa93ac578ef39aa8230580ea95076f
-rw-r--r-- 1 root root 195 Jan 17 11:44 615c102e2290b70d38d89c03a1ad263da8bd8b05fb7fc8479174e5fd2215520e
-rw-r--r-- 1 root root 130 Jan 17 11:44 837339b915388417a842c87a681a5448df2509068c8d3efd1638f1fad2eacea2
-rw-r--r-- 1 root root 260 Jan 17 11:44 b39b81afc8cae27d6fc7ea89584bad5e0ba792127597d02425eaee9f3aaaa462
 
/var/lib/docker/aufs/mnt:
total 20
drwxr-xr-x 2 root root 4096 Jan 17 11:42 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158
drwxr-xr-x 2 root root 4096 Jan 17 11:44 53f858aaaf03033e088d357df23e311d71aa93ac578ef39aa8230580ea95076f
drwxr-xr-x 2 root root 4096 Jan 17 11:44 615c102e2290b70d38d89c03a1ad263da8bd8b05fb7fc8479174e5fd2215520e
drwxr-xr-x 2 root root 4096 Jan 17 11:44 837339b915388417a842c87a681a5448df2509068c8d3efd1638f1fad2eacea2
drwxr-xr-x 2 root root 4096 Jan 17 11:44 b39b81afc8cae27d6fc7ea89584bad5e0ba792127597d02425eaee9f3aaaa462

Ce retour n’est pas sans rappeler le contenu de .git/objects pour les utilisateurs de Git, nous verrons plus tard que ce n’est absolument pas un hasard si nous retrouvons une syntaxe et une philosophie de versionning très proches de Git.

Enfin, pour connaître tous les détails d’une image :

docker inspect ubuntu:14.04
[{
    "Architecture": "amd64",
    "Author": "",
    "Checksum": "tarsum.dev+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "Comment": "",
    "Config": {
        "AttachStderr": false,
        "AttachStdin": false,
        "AttachStdout": false,
        "Cmd": [
            "/bin/bash"
        ],
        "CpuShares": 0,
        "Cpuset": "",
        "Domainname": "",
        "Entrypoint": null,
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "ExposedPorts": null,
        "Hostname": "2338b11efbe1",
        "Image": "615c102e2290b70d38d89c03a1ad263da8bd8b05fb7fc8479174e5fd2215520e",
        "MacAddress": "",
        "Memory": 0,
        "MemorySwap": 0,
        "NetworkDisabled": false,
        "OnBuild": [],
        "OpenStdin": false,
        "PortSpecs": null,
        "StdinOnce": false,
        "Tty": false,
        "User": "",
        "Volumes": null,
        "WorkingDir": ""
    },
    "Container": "485a6058231fa39ea20d4c7a526ff5916aee18284fd1fa7d78e1e5bea7ff662b",
    "ContainerConfig": {
        "AttachStderr": false,
        "AttachStdin": false,
        "AttachStdout": false,
        "Cmd": [
            "/bin/sh",
            "-c",
            "#(nop) CMD [/bin/bash]"
        ],
        "CpuShares": 0,
        "Cpuset": "",
        "Domainname": "",
        "Entrypoint": null,
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "ExposedPorts": null,
        "Hostname": "2338b11efbe1",
        "Image": "615c102e2290b70d38d89c03a1ad263da8bd8b05fb7fc8479174e5fd2215520e",
        "MacAddress": "",
        "Memory": 0,
        "MemorySwap": 0,
        "NetworkDisabled": false,
        "OnBuild": [],
        "OpenStdin": false,
        "PortSpecs": null,
        "StdinOnce": false,
        "Tty": false,
        "User": "",
        "Volumes": null,
        "WorkingDir": ""
    },
    "Created": "2015-01-16T21:25:30.510167396Z",
    "DockerVersion": "1.4.1",
    "Id": "b39b81afc8cae27d6fc7ea89584bad5e0ba792127597d02425eaee9f3aaaa462",
    "Os": "linux",
    "Parent": "615c102e2290b70d38d89c03a1ad263da8bd8b05fb7fc8479174e5fd2215520e",
    "Size": 0,
    "VirtualSize": 188305056
}
]

Le mot de la fin

Voilà j’espère que cette première approche vous a plu. Notre environnement de travail est maintenant prêt et nous allons pouvoir commencer à rentrer dans le vif du sujet, à savoir manipuler les conteneurs. L’objectif final étant d’avoir un conteneur Docker embarquant Sonerezh 🙂

Cet article fait partie d’une suite :

  1. Docker comme solution de virtualisation : théorie
  2. Docker comme solution de virtualisation : installation
  3. Docker comme solution de virtualisation : les conteneurs
  4. Docker comme solution de virtualisation : les commits
  5. Docker comme solution de virtualisation : les liaisons
  6. Docker comme solution de virtualisation : les volumes

Cet article vous a plu ? Partagez-le sur les réseaux sociaux !

Twitter Facebook Google Plus email