Sommaire
- Installons de Yocto
- Générons notre image
- Installons docker
- Créons notre container.
- Démarrons notre image
- Poussons l'exercice encore un peu plus loin…
Bonjour 'nal… c'est comme ça qu'on dit n'est pas?
Vous connaissez certainement Docker, la solution permettant de d'automatiser le déploiement d'application sous forme de containers LXC.
Docker fournit un grand nombre d'images prédéfinies par d'autre mais, question: Comment peut-on faire pour créer notre propre image et la déployer?
Je travail avec Yocto qui est conçu pour créer des images aux petits oignions pour des systèmes embarqués. Pourquoi donc ne pas utiliser cet outil pour fabriquer une image qui sera ensuite utilisée dans un container Docker?
Ce journal est écrit pour faire partager mes expériences prend la forme d'un tutoriel expliquant étape par étape et comment créer et exécuter cette image.
Installons de Yocto
Pour débuter avec Yocto, il suffit de se référer au tutoriel Yocto Project Quick Start mais ne vous inquiétez pas je détail toutes les commandes ci-dessous.
Note: Dans mon exemple, je vais utiliser Fedora Core 23 (qui n'ai pas supporté par Yocto-project mais qui fonctionne).
Pourquoi cette distrib? Tout simplement parce que j'avais envie de tester l'interface Gnome3 et que je l'avais sous la main.
Tout commence donc l'installation des outils nécessaires:
sudo dnf install gawk make wget tar bzip2 gzip python unzip perl patch diffutils diffstat \
git cpp gcc gcc-c++ glibc-devel texinfo chrpath ccache perl-Data-Dumper perl-Text-ParseWords \
perl-Thread-Queue socat findutils which SDL-devel xterm
J'ai dû rajouter un paquet manquant (et oui, on m'avait bien prévenu, FC23 n'est pas supporté…)
sudo dnf install perl-bignum
Ensuite, nous devons récupérer Yocto en lui même, et nous allons l'installer dans ~/yocto
:
mkdir ~/yocto
cd ~/yocto
git clone git://git.yoctoproject.org/poky -b jethro
Générons notre image
Avant de créer notre image, nous devons d'abord créer notre environnement.
Les commandes suivantes font le travail:
cd ~/yocto/poky
source oe-init-build-env
Maintenant, nous devons définir notre machine cible. Par défaut Yocto propose d'utiliser qemu, dans notre cas nous allons utiliser une cible identique au futur hôte: genericx86-64
Pour cela éditons le fichier ~/yocto/poky/build/conf/local.conf
et dé-commentons la ligne suivante:
MACHINE ?= "genericx86-64"
Nous allons aussi vouloir que notre système de fichier soit produit sous forme d'une archive tar.bz2
Ajoutons à la fin de ce même fichier la ligne suivante:
IMAGE_FSTYPES += "tar.bz2 "
Voilà, notre environnement est prêt, nous pouvons lancer la compilation et partir faire quelque chose d'intéressant pendant que le PC travail (en fonction de la puissance de votre machine, ça peut prendre pas mal de temps):
cd ~/yocto/poky/build
bitbake core-image-minimal
L'image résultant de cette compilation se trouve dans ~/yocto/poky/build/tmp/deploy/genericx86-64/
Installons docker
L'installation et le démarrage de docker se fait en deux lignes:
sudo dnf install docker
sudo service docker start
Créons notre container.
Nous allons maintenant créer l'environnement permettant le déploiement de notre image:
mkdir ~/docker
cd ~/docker
Copions l'image créée précédemment dans notre environnement de déploiement Docker:
cp ~/yocto/poky/build/tmp/deploy/genericx86-64/core-image-minimal-genericx86-64-*.rootfs.tar.bz2 docker-image-minimal-genericx86-64.tar.bz2
Nous devons d'abord créer une description de ce dernier grâce à un fichier Dockerfile
Ce fichier contient les instructions permettant la création de notre container. Voici son contenu:
FROM scratch
ADD docker-image-minimal-genericx86-64.tar.bz2 /
CMD ["sh"]
Petite explication: On part "FROM scratch", on ajoute notre système de fichier docker-image-minimal-genericx86-64.tar.bz2
à la racine \
. Notre container démarre avec la commande sh
.
Il faut maintenant construire et installer notre container.
sudo docker build -t mycontainer .
Cette commande va lire le fichier Dockerfile
que nous venons de créer et va créer un container puis décompresser l'image créée avec Yocto.
Il nous reste plus qu'a vérifier si notre image apparaît dans la liste:
sudo docker images
Démarrons notre image
Notre image est installer, démarrons là:
docker run -it --rm mycontainer
Bingo nous sommes dans notre nouvel environnement.
Poussons l'exercice encore un peu plus loin…
En explorant un peu ce que l'on vient de créer, nous constatons tout de même que nous avons une image un peu grosse (8MB) et surtout que nous avons perdu quand même pas mal de temps à compiler le noyau Linux alors qu'avec Docker, il ne nous sert à rien.
Si nous voulons encore réduire notre image et n'inclure dedans que la minimum (busybox
), nous allons devoir créer notre propre image.
Pour cela, nous allons créer notre propre layer et l'ajouter aux layers utilisés dans notre environnement Yocto.
mkdir -p ~/yocto/poky/meta-xb/conf
cp ~/yocto/poky/meta-yocto/conf/layer.conf ~/yocto/poky/meta-xb/conf/
Puis nous allons créer notre image qui ne contiendra que busybox
:
mkdir -p ~/yocto/poky/meta-xb/recipes-core/images/
cat > ~/yocto/poky/meta-xb/recipes-core/images/docker-image-minimal.bb << EOF
SUMMARY = "Minimal image for docker guest - Proof of Concept"
IMAGE_FSTYPES += "tar.bz2 "
LICENSE = "CLOSED"
IMAGE_INSTALL = "busybox"
inherit image
EOF
Note: J'ai mis LICENSE = "CLOSED"
pour me simplifier la vie et ne pas gérer cet aspect pendant mes expériences mais bien entendu, rien n'est fermé ici
Notre layer est prêt. Pour l'ajouter aux layers utilisés dans notre environement, il faut ajouter la ligne suivante à lafin du fichier ~/yocto/poky/build/conf/bblayer.conf
BBLAYERS += "/home/developper/yocto/poky/meta-xb "
Note: /home/developper
correspond à ~
Construisons notre nouvelle image:
cd ~/yocto/poky
source oe-init-build-env
bitbake docker-image-minimal
L'image produite ne fait plus que 2MB (soit 4 fois moins que la précédente … et je pense qu'on peut encore faire mieux)
Il est alors possible de la démarrer dans docker en suivant les instructions décrites un peu plus haut.
A partir de maintenant il possible possible de rajouter des recettes Yocto pour avoir un containers "aux petits oignons"…
# Bien vu !
Posté par a-wai (site web personnel) . Évalué à 7.
C'est une utilisation très intéressante de Yocto que tu fais là, merci pour ton retour !
# Des icônes ?
Posté par ǝpɐןƃu∀ nǝıɥʇʇɐW-ǝɹɹǝıԀ (site web personnel) . Évalué à -3.
Encore un journal sur le fait religieux ! Donc il existe maintenant des outils pour consacrer des images à destination des systèmes embarqués ? Le sens de la phrase est un peu obscur. À moins d'une coquille qui aurait remplacé le nom d'une plante potagère par l'imparfait du verbe oindre ?
« IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace
[^] # Re: Des icônes ?
Posté par ǝpɐןƃu∀ nǝıɥʇʇɐW-ǝɹɹǝıԀ (site web personnel) . Évalué à 0.
PS : le nom de la plante s'écrit soit oignon, soit ognon. Mais sans jamais prendre de i après le gn.
« IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace
# sur debian...
Posté par Psychofox (Mastodon) . Évalué à 2.
Sous debian et dérivées c'est relativement facile. Debootstrap, tar puis docker import. J'crois que c'est même dans la doc de docker.
# Ahhh je vois que je ne suis pas le seul à y avoir pensé :-)
Posté par ghusson (site web personnel) . Évalué à 3.
Ça me fait plaisir de voir ça. J'y avais pensé mais je n'ai pas pris le temps de tester :-)
Merci pour le partage !
Après pour optimiser l'empreinte, il est possible de ne prendre que les binaires et les librairies nécessaires (via un script d'automatisation qui cible des binaires définis). J'avais déjà fait ça pour un système de backup à chaud qui créait un ré-installeur sur USB dans un job précédent. Les scripts de bases sont présents sur le net.
# Docker, LXC
Posté par elf32 . Évalué à 4.
Attention, Docker n'est plus basé sur LXC depuis un bout de temps ;)
[^] # Re: Docker, LXC
Posté par X@v (site web personnel) . Évalué à 3.
Effectivement. C'est ma première expérience avec Docker et je découvre donc. En relisant plus attentivement les docs de docker je constate qu'il utilise maintenant libcontainer et plus LXC.
Merci pour la correction.
# Pas convaincu
Posté par Tangi Colin . Évalué à 3.
Si on veux vraiment joué à qui à la plus courte faut aller plus loin, configuré yocto pour utiliser µlibc ou même musl, strippé le tout etc…
Mais honnêtement un debian (depuis un deboostrap où on vire les man, les timezones, les langues) ça tient en 40 mo seulement tout en ayant "apt-get". Je préfère largement ça et niveau politique de sécurité je rebuild et redéploie mes images toutes les semaines (donc j'ai un apt update qui s'exécute une fois par semaine).
[^] # Re: Pas convaincu
Posté par Marotte ⛧ . Évalué à 2.
Dans le cas où doit vraiment isoler chaque service, donc lancer de nombreux « petits » conteneurs, la mémoire occupée par le système (avant lancement du service principal de ce conteneur) est importante. Le temps de démarrage nécessaire à chaque conteneur (entre une Debian minimal et un TinyCore Linux, ou le genre de système « au petits oignons » dont on parle ici, ça fait une nette différence…) ça rentre en ligne de compte.
[^] # Re: Pas convaincu
Posté par Sufflope (site web personnel) . Évalué à 2.
La taille de l'image système c'est pas forcément celle prise en mémoire. Je dois avoir 4Go rien que dans /usr mais fort heureusement mon OS ne prend pas 4Go rien que pour démarrer.
[^] # Re: Pas convaincu
Posté par Marotte ⛧ . Évalué à 1.
C’est quand même souvent corrélé. Une Debian (ou autre ditrib’ généraliste) occupe plus de place ET en terme de stockage dans /usr ET en terme d’utilisation de la RAM qu’un Busybox…
Par ailleurs, je ne connais pas bien Docker, je ne serais pas surpris que Docker charge tout l’userland (ie : le contenu du /usr du conteneur) quand il démarre le conteneur…
[^] # Re: Pas convaincu
Posté par Sufflope (site web personnel) . Évalué à 6. Dernière modification le 07 avril 2016 à 11:20.
C'est fou de faire autant de suppositions sur quelque chose qu'on avoue ne pas connaître.
[^] # Re: Pas convaincu
Posté par X@v (site web personnel) . Évalué à 2.
Avec Yocto, on peut aussi utiliser
apt-get
. Yocto pourra même créer des paquets.deb
pour des programmes qui ne sont pas dans les dépôts officiels.Le but de cette expérience était un petit challenge que je me suis lancé dans le but de tester Docker. Pour l'instant, je n'ai pas trop réfléchi aux cas d'usages possibles. J'ai tout de même le sentiment que le fait de marier les capacités de Yocto à créer des systèmes de fichiers, des dépôts et des paquets à partir de codes sources avec la puissance de docker laisse un champs de possibilités assez vaste…
# Excellent journal
Posté par Marotte ⛧ . Évalué à 3.
Ça donne envie de tester tout ça !
Au passage juste une faute dont ce journal mériterait qu’on la corrige :
n’est pas
C’est la seule que j’ai vu (mais elle pique)…
En tous cas encore une fois bravo, tes explications sont limpides…
[^] # Re: Excellent journal
Posté par X@v (site web personnel) . Évalué à 2.
Effectivement, il y a quelques coquilles qui se sont glissées dans ma prose:
Et peut-être encore d'autres… c'est ça de rédiger un journal à plus de 23:00 ;-)
# Alpine
Posté par nomorsad . Évalué à 4.
Je vois passer pas mal de Dockerfile basé sur du Alpine Linux http://alpinelinux.org/
Je ne connais ni Yocto ni Alpine mais ça me semble le même esprit.
Finalement le problème de Docker c'est qu'il ne reutilise pas les librairies dynamiques deja chargées c'est ca ? Et c'est donc pour ça que l'utilisation de mini libc contourne le problème ?
Si c'est le cas on peut aussi se demander pourquoi ne pas faire des binaires statiques du coup…
[^] # Re: Alpine
Posté par Marotte ⛧ . Évalué à 4.
Ce n’est pas un problème… le principe d’un conteneur c’est de segmenter… c’est normal que des bibliothèques ne soient pas partagées entre les conteneurs…
Bien sûr le gestionnaire de conteneurs peut dédoubler certains espaces mémoire mais j’imagine que ça a ses limites si on veut conserver une séparation stricte des environnements d’exécution…
D’où effectivement la nécessitée de mettre au point un « bare system » des plus léger…
[^] # Re: Alpine
Posté par Ph Husson (site web personnel) . Évalué à 3.
Hors conteneur, tous les process se partagent la même zone mémoire pour les zones statiques de la libc, quelque soit leur origine ou UI, et c'est garanti sécurisé par le kernel.
Après, c'est le boulot du KSM de tout merger, mais ça reste une surcharge. De cpu si c'est les même libs, de RAM si les libs sont toutes différentes
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.