Tuto: fix mistakes and oversights

This commit is contained in:
nemunaire 2014-11-30 22:48:17 +01:00
parent e1aa9bd4c9
commit ef6e81877e
2 changed files with 141 additions and 120 deletions

View File

@ -22,13 +22,16 @@ commencer. Vous n'êtes pas forcément tenu de réaliser les étapes dans l'ordr
* N'oubliez pas de consulter avant toutes choses les `man` très fournis des
commandes que vous utiliserez ; en particulier tous les `lxc-*`,
`capabilities(7)`, ...
* Vous pouvez utiliser ou vous inspirer des images présentes sur le Hub Docker.
* Ne passez pas trop de temps sur l'interface, l'architecture des containers
est bien plus intéressante.
## Modalités de rendu
L'heure du rendu est fixé au dimanche 30 novembre 2014 à 11h42 CET.
Il est attendu que vous rendiez à virli@nemunai.re une tarball contenant un ou
plusieurs `Dockerfile` permettant d'obtenir l'interface de contrôle des
Il est attendu que vous rendiez, à <virli@nemunai.re>, une tarball contenant un
ou plusieurs `Dockerfile` permettant d'obtenir l'interface de contrôle des
conteneurs, accompagnés d'un script automatisant le déploiement de la solution
sur une nouvelle machine (voir la section 2.2 pour les modalités de ce script).

View File

@ -54,23 +54,54 @@ la configuration de votre noyau en utilisant la commande `lxc-checkconfig`.
### Par le gestionnaire de paquets
Sous Debian et ses dérivés (Ubuntu, Mint, ...) le paquet et la commande ont été
nommés `docker.io`.
nommés `docker.io`. Vous pouvez vous créer un alias `alias docker=docker.io`.
Sous les autres distribution, `docker` correspond a priori bien à la solution
de virtualisation légère que l'on va utiliser.
### Manuellement
L'équipe en charge de Docker met à disposition un script pour
installer Docker sur n'importe quel système :
L'équipe en charge de Docker met à disposition un script pour installer Docker
sur n'importe quel système :
```sh
curl -sSL https://get.docker.com/ | sh
```
### Vérifier la bonne marche de l'installation
Vous devriez maintenant être capable de lancer la commande suivante :
```
docker version
```
Une sortie similaire au bloc suivant devrait apparaître sur votre écran :
```
Client version: 1.3.2
Client API version: 1.15
Go version (client): go1.3.3
Git commit (client): 39fa2fa
OS/Arch (client): linux/amd64
Server version: 1.3.2
Server API version: 1.15
Go version (server): go1.3.3
Git commit (server): 39fa2fa
```
Si vous avez cette erreur : `dial unix /var/run/docker.sock: permission
denied.`, ajoutez votre utilisateur au groupe `docker` et **relancer votre
session** :
```
sudo gpasswd -a $USER docker
```
## LXC
Votre distribution fourni sans doute un paquet `lxc`.
Votre distribution fournit sans doute un paquet `lxc`.
# Docker
@ -260,7 +291,7 @@ dossier ne contenant que votre fichier `Dockerfile`, placez-vous
dedans, puis utilisez la commande `build` :
```
docker build -name=my_editor .
docker build --tag=my_editor .
```
Une fois la construction de l'image terminée, vous pouvez la lancer et
@ -270,7 +301,7 @@ constater l'existence de notre éditeur favori :
docker run -it my_editor /bin/bash
```
Consultez https://docs.docker.com/reference/builder/ pour la liste
Consultez <https://docs.docker.com/reference/builder/> pour la liste
complète des instructions reconnues.
@ -296,7 +327,7 @@ redirection de port aléatoire sur la machine hôte vers votre
conteneur :
```
docker build -name=my_webserver .
docker build --tag=my_webserver .
docker run -it -P my_webserver /bin/bash
service nginx start
```
@ -305,7 +336,7 @@ Dans un autre terminal, lancer un `docker ps` et consulter la colonne
*PORTS* pour connaître le port choisit par Docker pour effectuer la
redirection.
Rendez-vous ensuite dans votre navigateur sur http://localhost:49153/.
Rendez-vous ensuite dans votre navigateur sur <http://localhost:49153/>.
À vous de jouer : utilisez l'instruction `COPY` pour afficher votre
propre `index.html` remplaçant celui installé de base par nginx.
@ -321,7 +352,7 @@ CMD nginx -g "daemon off;"
```
```
docker build -name=my_nginx .
docker build --tag=my_nginx .
docker run -d -P my_nginx
```
@ -359,36 +390,34 @@ Vous constaterez que le répertoire `/var/log/nginx` est partagé entre
`romantic_archimedes` et le dernier conteneur lancé.
\newline
Le concept principal de Docker est de concevoir des conteneurs
applicatifs : on va préférer assigner un unique rôle à un conteneur
(donc géralement on ne va lancer qu'une seule application par
conteneur) et concevoir un service complet en créant un groupe de
conteneur, partageant des données entre-eux par des volumes.
Le concept principal de Docker est de concevoir des conteneurs applicatifs : on
va préférer assigner un unique rôle à un conteneur (donc géralement on ne va
lancer qu'une seule application par conteneur) et concevoir un service complet
en créant un groupe de conteneur, partageant des données entre-eux par des
volumes.
Une lecture intéressante sur ce sujet est sans doute cet article de
Michael Crosby: http://crosbymichael.com/advanced-docker-volumes.html
Une lecture intéressante sur ce sujet est sans doute [cet article de Michael
Crosby](http://crosbymichael.com/advanced-docker-volumes.html).
### Data Volume Container
Dans de nombreuses situation, il est intéressant de séparer les
données de l'application, et donc d'avoir un conteneur exécutant
l'application et un second stockant les données.
Dans de nombreuses situation, il est intéressant de séparer les données de
l'application, et donc d'avoir un conteneur exécutant l'application et un
second stockant les données.
Cela est particulièrement utile dans le cas d'une base de données : on
veut pouvoir mettre à jour le conteneur exécutant le serveur, sans
pour autant perdre les données.
Cela est particulièrement utile dans le cas d'une base de données : on veut
pouvoir mettre à jour le conteneur exécutant le serveur, sans pour autant
perdre les données.
L'idée derrière le concept de `Data Volume Container` est de partager
un volume avec un conteneur dont le seul rôle est de stocker les
données.
L'idée derrière le concept de `Data Volume Container` est de partager un volume
avec un conteneur dont le seul rôle est de stocker les données.
Il est parfaitement possible de partager un volume avec un conteneur
qui n'est plus lancé. En effet, tant que vous n'avez pas demandé
explicitement à un conteneur d'être supprimé, il est préservé dans un
coin en attendant des jours meilleurs.
Il est parfaitement possible de partager un volume avec un conteneur qui n'est
plus lancé. En effet, tant que vous n'avez pas demandé explicitement à un
conteneur d'être supprimé, il est préservé dans un coin en attendant des jours
meilleurs.
Voici comment on pourrait lancer un conteneur exécutant une base de
données :
Voici comment on pourrait lancer un conteneur exécutant une base de données :
```
docker run -v /var/lib/mysql --name dbdata busybox
@ -396,39 +425,36 @@ docker run --volume-from dbdata -e MYSQL_ROOT_PASSWORD=mysecretpassword -d mysql
```
Le premier conteneur, sans commande passée, va s'arrêter dès son
lancement. Busybox est l'une des plus petites images possédant tous
les outils de base (il est possible d'obtenir un shell en cas de
besoin). Il expose un volume qui sera utiliser comme stockage
persistant.
lancement. Busybox est l'une des plus petites images possédant tous les outils
de base (il est possible d'obtenir un shell en cas de besoin). Il expose un
volume qui sera utiliser comme stockage persistant.
Le second conteneur va lancer le serveur MySQL et utiliser le
répertoire partagé pour stocker les données.
Le second conteneur va lancer le serveur MySQL et utiliser le répertoire
partagé pour stocker les données.
Lorsqu'il y aura besoin de mettre à jour le conteneur MySQL, les
données ne seront pas perdues (et s'il y avait besoin de migrer les
données entre les deux versions des conteneurs, un conteneur
intermédiaire pourrait parfaitement s'en charger).
Lorsqu'il y aura besoin de mettre à jour le conteneur MySQL, les données ne
seront pas perdues (et s'il y avait besoin de migrer les données entre les deux
versions des conteneurs, un conteneur intermédiaire pourrait parfaitement s'en
charger).
Cela facile également les sauvegardes, qui peuvent s'exécuter dans un
conteneur distinct, dédié à la tâche de sauvegarde.
Cela facile également les sauvegardes, qui peuvent s'exécuter dans un conteneur
distinct, dédié à la tâche de sauvegarde.
## Lier les conteneurs
En plus de vouloir partager des répertoires entre deux conteneurs, il
est souvent nécessaire de partager des ports.
En plus de vouloir partager des répertoires entre deux conteneurs, il est
souvent nécessaire de partager des ports.
Pour automatiser le partage d'informations sur les IP et ports
exposés, la commande `run` possède l'option `--link` qui permet de
définir dans les variables d'environnement du conteneur que l'on va
lancer.
Pour automatiser le partage d'informations sur les IP et ports exposés, la
commande `run` possède l'option `--link` qui permet de définir dans les
variables d'environnement du conteneur que l'on va lancer.
Le détail des variables ajoutées dans cette situation est disponible
ici : https://docs.docker.com/userguide/dockerlinks/#environment-variables
[ici](https://docs.docker.com/userguide/dockerlinks/#environment-variables).
On utiliser généralement cette liaison pour fournir au conteneur
hébergeant un site web dynamique l'IP et le port où trouver la base de
données :
On utiliser généralement cette liaison pour fournir au conteneur hébergeant un
site web dynamique l'IP et le port où trouver la base de données :
```
docker run -e MYSQL_ROOT_PASSWORD=mysecretpassword -d --name db1 mysql
@ -437,45 +463,43 @@ docker run --link db1 my_nginx
### Ambasador
Afin d'abstraire le plus possible l'infrastructure sous-jacente et
d'autoriser les migrations de conteneurs, on utilise le modèle
*ambassador*.
Afin d'abstraire le plus possible l'infrastructure sous-jacente et d'autoriser
les migrations de conteneurs, on utilise le modèle *ambassador*.
On lancera systématiquement un conteneur entre deux conteneurs que
l'on veut lier : l'ambassadeur. Celui-ci s'occupera de router
correctement le trafic. En cas de changement de route (si l'un des
conteneurs change de machine hôte par exemple), on a simplement à
redémarrer l'ambassadeur plutôt que le conteneur principal.
On lancera systématiquement un conteneur entre deux conteneurs que l'on veut
lier : l'ambassadeur. Celui-ci s'occupera de router correctement le trafic. En
cas de changement de route (si l'un des conteneurs change de machine hôte par
exemple), on a simplement à redémarrer l'ambassadeur plutôt que le conteneur
principal.
La documentation officielle pour ce modèle est disponible à
https://docs.docker.com/articles/ambassador_pattern_linking/
La documentation officielle pour ce modèle est disponible
(ici)[https://docs.docker.com/articles/ambassador_pattern_linking/].
# LXC
Contrairement à Docker, l'utilisation de LXC est beaucoup plus proche
de l'administration système classique, car l'approche est beaucoup
plus bas niveau.
Contrairement à Docker, l'utilisation de LXC est beaucoup plus proche de
l'administration système classique, car l'approche est beaucoup plus bas
niveau.
## Lancer un conteneur
Avec le paquet LXC que vous avez installé, vous avez également
récupéré un certain nombre de modèles de système (souvent installés
dans le dossier `/usr/share/lxc/templates/`).
Avec le paquet LXC que vous avez installé, vous avez également récupéré un
certain nombre de modèles de système (souvent installés dans le dossier
`/usr/share/lxc/templates/`).
La méthode la plus simple pour lancer un conteneur LXC est d'utiliser
l'un de ces modèles qui va installer tout un environnement pour
vous. On utilise pour cela la commande `lxc-create` :
La méthode la plus simple pour lancer un conteneur LXC est d'utiliser l'un de
ces modèles qui va installer tout un environnement pour vous. On utilise pour
cela la commande `lxc-create` :
```
lxc-create --name toto_first --template ubuntu
```
Ce modèle va créer un dossier dans `/var/lib/lxc/` portant le nom que
vous avez précisé. Ce dossier va contenir la configuration LXC du
conteneur, la table des partitions s'il y a besoin de faire des
montages particuliers et enfin le dossier `rootfs` contenant le
système en lui-même.
Ce modèle va créer un dossier dans `/var/lib/lxc/` portant le nom que vous avez
précisé. Ce dossier va contenir la configuration LXC du conteneur, la table des
partitions s'il y a besoin de faire des montages particuliers et enfin le
dossier `rootfs` contenant le système en lui-même.
On peut maintenant démarrer le conteneur :
@ -484,54 +508,48 @@ lxc-start --name toto_first
```
À la différence de Docker qui va ne lancer que l'application (ou les
applications listées dans la ligne de commande) dans son
environnement, LXC va appeler `/sbin/init` et démarrer tous les
services que l'on peut s'attendre à trouver dans n'importe quelle
machine virtuelle plus classique (la seule différence réside donc dans
le fait que le noyau est partagé avec l'hôte).
applications listées dans la ligne de commande) dans son environnement, LXC va
appeler `/sbin/init` et démarrer tous les services que l'on peut s'attendre à
trouver dans n'importe quelle machine virtuelle plus classique (la seule
différence réside donc dans le fait que le noyau est partagé avec l'hôte).
Généralement on lance `lxc-start` avec l'option `--daemon`, puis on
utilise `lxc-console` qui permet de se détacher de la console via le
binding `^A+q`.
Généralement on lance `lxc-start` avec l'option `--daemon`, puis on utilise
`lxc-console` qui permet de se détacher de la console via le binding `^A+q`.
Connectez-vous, lancez quelques commandes puis éteignez la machine
avec `sudo poweroff` ou dans un autre terminal via `lxc-stop --name
toto_first`.
Connectez-vous, lancez quelques commandes puis éteignez la machine avec `sudo
poweroff` ou dans un autre terminal via `lxc-stop --name toto_first`.
## Persistance des données
Contrairement à Docker, lorsque vous arrêtez un conteneur, les
modifications apportées sont conservées. Si vous appelez à nouveau
`lxc-start --name toto_first`, vous constaterez que votre historique
contient les dernières commandes que vous avez tapé et si vous avez
apporté d'autres modifications sur le système, celles-ci sont toujours
visibles.
Contrairement à Docker, lorsque vous arrêtez un conteneur, les modifications
apportées sont conservées. Si vous appelez à nouveau `lxc-start --name
toto_first`, vous constaterez que votre historique contient les dernières
commandes que vous avez tapé et si vous avez apporté d'autres modifications sur
le système, celles-ci sont toujours visibles.
## Le réseau
Le modèle ubuntu que vous avez utilisé initialise un fichier de
configuration sans paramètres pour le réseau. Vous n'avez donc pas
d'interface dans le conteneur pour le connecter au réseau.
Le modèle ubuntu que vous avez utilisé initialise un fichier de configuration
sans paramètres pour le réseau. Vous n'avez donc pas d'interface dans le
conteneur pour le connecter au réseau.
Un excellent article détaillant les différents types de réseau est
accessible à :
https://blog.flameeyes.eu/2010/09/linux-containers-and-networking
Un excellent article détaillant les différents types de réseau est accessible
(ici)[https://blog.flameeyes.eu/2010/09/linux-containers-and-networking].
N'ayant qu'une seule interface physique sur la machine et n'ayant pas
accès à la configuration des VLAN de la pièce, il ne nous reste que
deux méthodes pour obtenir du réseau dans nos conteneurs : Virtual
Ethernet ou MACVLAN.
N'ayant qu'une seule interface physique sur la machine et n'ayant pas accès à
la configuration des VLAN de la pièce, il ne nous reste que deux méthodes pour
obtenir du réseau dans nos conteneurs : Virtual Ethernet ou MACVLAN.
### Virtual Ethernet
Virtual Ethernet est la configuration la plus simple. On met en place un pont
sur la machine hôte, puis on crée une interface `veth` par conteneur
que l'on veut lancer. On n'oubliera pas d'ajouter ces interfaces au pont.
sur la machine hôte, puis on crée une interface `veth` par conteneur que l'on
veut lancer. On n'oubliera pas d'ajouter ces interfaces au pont.
Voici un extrait de configuration correspondant au paramétrage d'une
interface `eth0` pour un conteneur donné :
Voici un extrait de configuration correspondant au paramétrage d'une interface
`eth0` pour un conteneur donné :
```
lxc.network.type = veth
@ -539,15 +557,15 @@ lxc.network.flags = up
lxc.network.link = br0
```
Cette technique a pour inconvénient de laisser au noyau le soin de
router les paquets selon leur adresse IP, ce qui peut être lent et
coûteux étant donné que la carte est placé en mode de promiscuité.
Cette technique a pour inconvénient de laisser au noyau le soin de router les
paquets selon leur adresse IP, ce qui peut être lent et coûteux étant donné que
la carte est placé en mode de promiscuité.
### MACVLAN
Ici, le noyau va orienter les paquets en fonction de leur adresse MAC
de destination.
Ici, le noyau va orienter les paquets en fonction de leur adresse MAC de
destination.
```
lxc.network.type = macvlan
@ -559,9 +577,9 @@ lxc.network.link = br0
## Stockage
Par défaut, le stockage se fait dans l'arborescence du système hôte,
mais il est possible d'utiliser d'autres backends tels que Btrfs, LVM,
overlayfs, AUFS ou ZFS.
Par défaut, le stockage se fait dans l'arborescence du système hôte, mais il
est possible d'utiliser d'autres backends tels que Btrfs, LVM, overlayfs, AUFS
ou ZFS.
Pour utiliser un type de stockage particulier, préciser lors de la
création de l'environnement du conteneur `-B [btrfs|zfs|lvm|...]`.
Pour utiliser un type de stockage particulier, préciser lors de la création de
l'environnement du conteneur `-B [btrfs|zfs|lvm|...]`.