Sommaire
- Introduction
- Mettons en place notre dépôt
- Améliorons l'image de base
- Démarrons notre environnement de test de manière automatisée
- Utilisons notre dépôt
- Un petit bonus…
- Conclusion
Introduction
Il y a quelques jours, j'ai commencé à m'intéresser à Docker et à un possible mariage avec Yocto. Ref. Yocto+docker: Les containers personnalisés
Aujourd'hui, je continue l'expérience et continue à la partager (attention, le papier est un peu long…).
Les idées développées cette fois-ci sont les suivantes :
- Construire une image un peu plus complexe qui servira de base à nos futures applications incluant un accès
ssh
etsmart
(gestionnaire de paquet). - Mettre en place un dépôt (contenant les paquets crées par Yocto) et qui sera disponible pour nos applications.
- Utiliser ce dépôt pour installer des logiciels sur notre image.
Mettons en place notre dépôt
Le dépôt contenant les paquets créés par Yocto se trouve dans le répertoire ~/yocto/poky/build/tmp/deploy/rpm/
Nous allons donc lancer un conteneur nginx
avec la commande suivante :
sudo docker run --name docker-nginx -p 80:80 -ti --rm -v /home/developper/yocto/poky/build/tmp/deploy/rpm/:/usr/share/nginx/html nginx
Note : Sur FC23, j'ai désactivé selinux
pour faire marcher mon volume (dans /etc/selinux/config
).
Pour vérifier que notre dépôt fonctionne, on peut activer l'affichage des répertoires dans nginx
.
Connectons nous à notre conteneur :
docker exec -ti docker-nginx bash
Et modifions la configuration de notre site pou y ajouter autoindex on;
:
cat > /etc/nginx/conf.d/default.conf<<EOF
server {
listen 80;
server_name localhost;
location / {
autoindex on;
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
EOF
Rechargeons maintenant la configuration de nginx
:
/etc/init.d/nginx reload
Maintenant, si on navigue sur la page http://127.0.0.1/ on doit voir le contenu de notre dépôt (jusqu'au prochain démarrage…).
Améliorons l'image de base
Notre dépôt est prêt, il faut maintenant que notre image de base soit capable de l'utiliser. Nous allons donc mettre à jour la recette de notre image comme suit :
cat > ~/yocto/poky/meta-xb/recipes-core/images/docker-image-base.bb <<EOF
SUMMARY = "Base image for docker guest - Proof of Concept"
DISTRO = "poky-tiny"
IMAGE_FSTYPES = "tar.bz2 "
LICENSE = "MIT"
IMAGE_FEATURES += "package-management"
IMAGE_INSTALL += "busybox dropbear"
inherit core-image
EOF
On peut noter que j'ai ajouté le gestionnaire de paquet. C'est smart
qui est proposé par défaut par Yocto en association avec des paquets au format rpm
.
J'ai aussi ajouté dropbear
pour l'accès ssh
.
On reconstruit l'image :
cd ~/yocto/poky
source oe-init-build-env
bitbake docker-image-base
On copie maintenant l'image dans notre espace de travail docker pour pouvoir l'utiliser :
mkdir -p ~/yocto/docker
cd ~/yocto/docker
cp ../poky/build/tmp/deploy/images/genericx86-64/docker-image-base-genericx86-64.tar.bz2 .
On va avoir besoin d'un script de démarrage pour démarrer dropbear
. Ce script (écrit vite fait) démarrera ensuite une commande top
afin d'avoir une commande bloquante (pour avoir une image fonctionnelle avec docker-compose
qu'on utilisera plus tard) :
cat > init.sh <<EOF
#!/bin/sh
/etc/init.d/dropbear start
top
EOF
On créé le Dockerfile
décrivant notre application:
cat > Dockerfile <<EOF
FROM scratch
ADD docker-image-base-genericx86-64.tar.bz2 /
ENV PS1 '[`whoami`@`hostname | sed "s/\..*//"` ${PWD}]# '
RUN smart channel -y --add all type=rpm-md baseurl=http://repo/all/
RUN smart channel -y --add core2_64 type=rpm-md baseurl=http://repo/core2_64/
RUN smart channel -y --add genericx86_64 type=rpm-md baseurl=http://repo/genericx86_64/
EXPOSE 22
COPY init.sh /usr/bin/init.sh
RUN chmod +x /usr/bin/init.sh
CMD ["init.sh"]
EOF
Dans cette nouvelle version, j'ai ajouté un prompt un peu plus explicite et quelques commandes qui initialiseront les dépôts disponibles et notre script de démarrage.
Ensuite, on peut construire l'image et la tester.
docker build -t docker-base .
docker run -ti --rm -p22:22 docker-base
Pour vérifier, on peut se connecter en ssh
et vérifier la présence de la commande smart
ssh root@127.0.0.1
smart
Démarrons notre environnement de test de manière automatisée
Nous allons utiliser docker-compose
pour lancer nos deux conteneurs (dépôt et machine) en même temps et les mettre en relation.
Installons d'abord docker-compose
sudo dnf install docker-compose
Créons la description de notre environnement dans docker-compose.yml
:
cd ~/yocto/docker
cat > yocto-docker-test.yml <<EOF
repo:
image: nginx
ports:
- "80:80"
volumes:
/home/developper/yocto/poky/build/tmp/deploy/rpm/:/usr/share/nginx/html
machine:
image : docker-base
ports :
- "22:22"
link :
- repo:repo
EOF
On retrouve ici la description de nos deux conteneurs et un lien permettant à notre machine de test de se connecter à notre dépôt.
Utilisons notre dépôt
Pour continuer l'expérience et à titre d'exemple, nous allons installer vim
. vim
est disponible dans le layer meta-oe
d'openembedded. Installons ce layer à partir du dépôt git
d'openembedded :
cd ~/yocto/poky
git://git.openembedded.org/meta-openembedded -b jethro
Il faut ensuite mettre à jour le fichier ~/yocto/poky/build/conf/bblayer.conf
et rajouter la ligne qui donnera accès à ce nouveau layer :
BBLAYERS += "/home/developper/yocto/poky/meta-openembedded/meta-oe "
Pour créer le paquet et mettre à jour le dépôt, on exécute les lignes suivantes :
bitbake vim
bitbake package-index
Pour installer vim
, il suffit de taper les commandes suivantes sur la machine cible :
smart update
smart install vim
Un petit bonus…
Voici un exemple d'utilisation de notre dépôt pour une application qui n'est pas dans les dépôts officiels. (J'ai choisi cette application au hasard sur github
)
Commençons par créer la recette de cette nouvelle application :
mkdir -p ~/yocto/poky/meta-xb/recipes-game/tty-tetris
cat > ~/yocto/poky/meta-xb/recipes-game/tty-tetris/tty-tetris_git.bb <<EOF
SUMMARY = "Example of recipe"
DESCRIPTION = "Part of Yocto+Docker journal fro X@v"
SRC_URI = "git://github.com/xorg62/tty-tetris.git"
SRCREV = "616bec61c52f3f5370e36993d7ba18c9f24d669b"
PV = "0.1+git${SRCPV}"
PR = "r1"
LICENSE = "BSD"
LIC_FILES_CHKSUM = "file://tetris.c;beginline=1;endline=31;md5=6b9c612aa8a5fb85148b8975e8079af4"
S = "${WORKDIR}/git"
FILES_${PN} += "/usr/local/bin/tty-tetris"
FILES_${PN}_dbg += "/usr/local/bin/.debug/tty-tetris"
do_configure() {
echo "done"
}
do_install() {
install -d ${D}/usr/local/bin/
install -m 0755 ${S}/tty-tetris ${D}/usr/local/bin/
}
EOF
Construisons notre nouveau paquet :
bitbake tty-tetris
Mettons à jour notre dépôt :
bitbake package-index
Enfin, sur la machine cible, installons le nouveau paquet :
smart update
smart install tty-tetris
Ça y est c'est installer, vous pouvez maintenant jouer à Tetris sur votre conteneur docker à partir d'un connexion ssh
… rigoureusement indispensable ;-).
Conclusion
Comme le prouve mes petites expériences, il est possible d'associer Yocto et Docker pour créer des images personnalisées.
Ne reste plus qu'à trouver des cas d'usages… des idées?
# Mauvaise pratique : SSH dans un conten
Posté par Tangi Colin . Évalué à 6.
Avoir un SSH dans un conteneur docker est considéré comme une mauvaise pratique. Mieux vaut avoir un unique accès SSH sur le host et ensuite faire un docker exec pour entrer dans un conteneur.
Parce que sinon, avoir 150 docker déployés ça fait beaucoup de clé ssh à gérer.
[^] # Re: Mauvaise pratique : SSH dans un conten
Posté par X@v (site web personnel) . Évalué à 4.
C'est une très bonne remarque (+1).
Du coup, elle soulève une autre question: Quelles sont les bonnes pratiques à connaître pour utiliser docker d'une manière efficace?
Je pense notamment à la gestion et au découpage des volumes, à l'écriture de Dockerfile… mais cette liste n'est pas exhaustive.
Vos commentaires et autres liens sont les bienvenus.
[^] # Re: Mauvaise pratique : SSH dans un conten
Posté par Tangi Colin . Évalué à 1.
un bon point de départ ce trouve ici : https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/
Je rajouterai à ça de bien pensé à ses processus de mis à jour des images.
On peut utiliser Clair pour détecter des vulnérabilité dans ses images : https://github.com/coreos/clair ou simplement régénérer souvent ses images dans un processus de Continuous Delivery avec des test de non régression de bonne qualités ça se passe tranquillement.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.