Docker implémenté en environ 100 lignes de Bash : Bocker (2015)
(github.com/p8952)- Bocker est un projet qui implémente Docker en environ 100 lignes de Bash et propose un flux proche de Docker avec pull d’images, exécution de conteneurs, consultation des logs, commit et suppression
- Son exécution nécessite btrfs-progs, curl, iproute2, iptables, libcgroup-tools, util-linux 2.25.2 ou plus, coreutils 7.5 ou plus, ainsi qu’un système de fichiers btrfs sous
/var/bockeret une configuration réseaubridge0 - L’exemple du README montre un flux où l’on pull l’image
centos:7, on exécute une commande dans le conteneur, puis on commit le résultat deyum install -y wgetpour vérifier ensuite la présence de/usr/bin/wget - Bocker s’exécute en root et modifie les interfaces réseau, la table de routage et les règles du pare-feu ; il est donc recommandé de l’exécuter dans une machine virtuelle, sans garantie contre d’éventuels dommages sur le système
- À ce jour,
docker pull,images,ps,run,exec,logs,commit,rm/rmi, la mise en réseau et les quotas basés sur CGroups sont implémentés, mais les volumes de données, les conteneurs de volumes de données et la redirection de ports ne le sont pas encore
Objectif et périmètre de Bocker
- Bocker est un projet qui implémente Docker en environ 100 lignes de Bash
- Le README illustre un flux de commandes proche de Docker en Bash, avec gestion d’images, exécution de conteneurs, consultation des logs, commit des modifications et limitation des ressources
Exigences d’exécution
- Les paquets nécessaires à l’exécution sont les suivants
-
btrfs-progs
- curl
- iproute2
- iptables
- libcgroup-tools
- util-linux 2.25.2 ou plus
- coreutils 7.5 ou plus
- comme la plupart des distributions n’incluent pas une version suffisamment récente de util-linux, il peut être nécessaire de télécharger et compiler soi-même les sources de util-linux 2.25
- Le système doit disposer de la configuration suivante
- un système de fichiers btrfs monté sous
/var/bocker - un pont réseau nommé
bridge0avec l’adresse IP10.0.0.1/24 - l’activation de l’IP forwarding dans
/proc/sys/net/ipv4/ip_forward - des règles de pare-feu permettant d’acheminer le trafic de
bridge0vers l’interface physique - un Vagrantfile est fourni pour faciliter la création de l’environnement nécessaire
-
Précautions d’exécution
- Même si les prérequis sont remplis, il est recommandé d’exécuter Bocker dans une machine virtuelle
- Bocker s’exécute en root et doit modifier les éléments suivants
- les interfaces réseau
- la table de routage
- les règles du pare-feu
- Le README précise qu’il ne peut garantir que Bocker n’endommagera pas le système
Exemple de flux d’utilisation
bocker pull centos 7permet de récupérer l’imagecentos:7et génère un ID d’image commeimg_42150bocker imagesaffiche l’ID de l’image et sa source- Exemple de sortie :
img_42150,centos:7
- Exemple de sortie :
bocker run img_42150 cat /etc/centos-releaseaffiche les informations de version de CentOS depuis le conteneur- Exemple de sortie :
CentOS Linux release 7.1.1503 (Core)
- Exemple de sortie :
bocker psaffiche les ID des conteneurs lancés et la commandebocker logs ps_42045affiche les logs de sortie du conteneur concernébocker rm ps_42045supprime le conteneur- Lors de l’exécution de
bocker run img_42150 which wget, le résultat indique d’abord quewgetn’est pas présent - Après installation de
wgetavecbocker run img_42150 yum install -y wget,bocker commit ps_42018 img_42150permet de répercuter les modifications dans l’image - Ensuite,
bocker run img_42150 which wgetaffiche/usr/bin/wget
Limitation des ressources et CGroups
- L’exemple d’exécution de Bocker montre que le conteneur est placé sous CGroups
- dans
/proc/1/cgroup, on voit apparaître des entrées commememory:/ps_42152,cpuacct,cpu:/ps_42152
- dans
- Les exemples de part CPU par défaut et de limite mémoire sont les suivants
/sys/fs/cgroup/cpu/ps_42152/cpu.shares:512/sys/fs/cgroup/memory/ps_42152/memory.limit_in_bytes:512000000
- Il est possible de modifier les limites de ressources via des variables d’environnement
BOCKER_CPU_SHARE=1024BOCKER_MEM_LIMIT=1024
- Après modification, l’exemple montre les valeurs suivantes
- CPU shares :
1024 - limite mémoire :
1024000000
- CPU shares :
Fonctionnalités implémentées et non implémentées
- Les fonctionnalités actuellement implémentées sont les suivantes
docker build†docker pulldocker imagesdocker psdocker rundocker execdocker logsdocker commitdocker rm/docker rmi-
Mise en réseau
- Quota Support / CGroups
- †
bocker initfournit une implémentation très limitée dedocker build - Les fonctionnalités pas encore implémentées sont les suivantes
- Data Volume Containers
- Data Volumes
- Port Forwarding
Licence
- Bocker est un logiciel libre pouvant être redistribué et modifié selon les termes de la GNU General Public License
- La version de la licence peut être la GPL v3 publiée par la Free Software Foundation ou toute version ultérieure
- Le programme est distribué dans l’espoir qu’il soit utile, mais sans aucune garantie implicite de qualité marchande ni d’adéquation à un usage particulier
1 commentaires
Avis de Hacker News
J’avais déjà créé quelque chose de similaire avec proot, qui s’appelait Bag [1], et je ne pense pas l’avoir présenté comme une alternative à Docker.
Cela n’avait rien à voir avec les cgroups, et l’interface en ligne de commande était différente de celle de Docker. Le contexte, c’est que j’avais créé une chaîne de proxy qui ressemblait à du trafic HTML ordinaire pour contourner la censure sur Internet et l’inspection approfondie des paquets ; il fallait qu’elle puisse continuer à tourner partout, mais je ne voulais pas la porter en application native Android.
Je voulais la faire tourner dans Termux, mais à l’époque Termux n’avait pas de JDK/JRE, tandis qu’en lançant un environnement Arch Linux avec proot, on pouvait utiliser le JDK. L’environnement Arch dans Termux était globalement plus utile, et il était aussi facile d’automatiser par script la création puis la suppression d’environnements jetables avec des configurations différentes, puis d’y entrer avec proot pour n’exécuter qu’une seule commande. Je l’ai donc nommé bag.sh, au sens d’une forme bien plus petite qu’un conteneur maritime.
Fait amusant, bag.sh contient encore une roadmap/TODO que je n’ai pas touchée depuis cinq ans. Je l’avais rédigée sur un écran mobile, donc la plupart des lignes sont alignées sur 40 colonnes pour pouvoir les voir sans faire défiler.
[1]: https://github.com/hkoosha/bag
J’avais créé dans /opt un petit Debian contenant les logiciels nécessaires et des dépendances comme MySQL ; cela fonctionnait plutôt bien et a été utilisé jusqu’à l’acquisition, vers 2016, de l’entreprise pour laquelle je l’avais fait. Plus généralement, je pense qu’implémenter soi-même une version rudimentaire d’une grosse application est l’une des meilleures façons d’en apprendre le fonctionnement interne.
mkdir -p $(dirname "$2")Avec un clavier Bluetooth d’environ 10 pouces qui rentre facilement dans la poche intérieure d’une veste en cuir, on peut sortir de chez soi sans sac, s’asseoir dans un coin d’un beer garden à proximité et écrire du code. C’est étonnamment productif aussi : peut-être parce qu’il y a un peu plus de friction que sur un ordinateur portable pour basculer vers les distractions habituelles, on finit par continuer à fixer le code en sirotant sa bière.
J’aime ce genre de choses. J’ai toujours aimé les réalisations en Bash minimal.
Voici aussi une preuve de concept de répartiteur de charge interne à un cluster, en 40 lignes de Bash, réalisée lors d’un hackathon que nous avions organisé il y a environ 10 ans pour faire connaître des infrastructures distribuées comme Docker et Mesos : https://github.com/cell-os/metal-cell/blob/master/discovery/...
Il est probablement perdu, mais il y avait aussi un outil de transfert colo-to-cloud basé sur des tunnels SSH inversés, avec redondance et distribution. Shell Fu et d’autres sites recensent bien ce genre de choses : https://www.shell-fu.org/
Le fait qu’on puisse réimplémenter aussi simplement une grande partie de Docker est le plus gros problème auquel Docker, l’entreprise, a été confrontée et continue de l’être. Fondamentalement, c’est surtout du code de liaison qui assemble des fonctionnalités du noyau.
Là où Docker apporte vraiment de la valeur, ce n’est pas seulement Docker Hub, mais Docker for Windows et Mac. L’expérience intégrée est nettement meilleure que de devoir manipuler soi-même VirtualBox et Vagrant pour faire tourner Docker sur une machine de développement.
Personnellement, je pense que la vraie magie de Docker était le format d’image Docker/OCI. C’est une excellente façon de gérer le cache et la distribution d’images de conteneurs, et cela reste l’élément clé qui distingue encore ce workflow d’une VM « complète ».
Sous Windows, on peut utiliser Docker dans WSL et cela fonctionne très bien. J’ai du mal à comprendre pourquoi on utiliserait Docker Desktop.
À la place, ils ont créé ce Docker Swarm bancal qui ne fonctionnait pas correctement de manière fiable, et Kubernetes les a rapidement dépassés.
Pour ma part, je ne m’en suis servi que pour récupérer l’environnement de build virtuel de quelqu’un afin de compiler un logiciel, il y a quelques années.
Il y a dans le dépôt des mentions comme « pas encore implémenté », « TODO », « en cours », et voir que le dernier commit date d’il y a plusieurs années, ça fait du bien.
Ça me rassure un peu sur le fait de ne pas retourner voir les TODO que j’ai disséminés dans mon code. Ce n’est pas pour rabaisser l’auteur, c’est juste réconfortant.
Dans du code non rémunéré, bénévole ou de hobby, si l’on ressent l’obligation de faire simplement parce qu’il est public, le codage devient moins agréable, et on peut finir par ne plus publier du code qu’on aurait autrement rendu public.
S’il y a toujours une idée suivante, alors par définition il restera toujours des TODO inachevés. En fait, cela devrait être l’état normal de tous les projets.
Définir clairement les limites du périmètre est tout à fait acceptable et souvent utile. Cela évite de poursuivre des pistes secondaires et d’avoir éternellement l’impression que le projet n’est jamais « terminé ».
Je suis surpris que lazydocker n’ait pas encore été mentionné comme excellente alternative à Docker Desktop. Il fonctionne sous Linux/macOS/Windows [1].
C’est une interface terminal assez riche en fonctionnalités, avec aussi l’avantage de pouvoir être exécutée via SSH.
[1] https://github.com/jesseduffield/lazydocker
En tout cas, c’est la première fois que je vois ça. Je me demande aussi si ce genre de publicité est autorisé par les conditions d’utilisation ou la politique d’usage acceptable de GitHub.
Je me demande pourquoi Bocker revient si souvent en une. En 2024, Docker est-il encore à ce point controversé ?
Je ne comprends pas pourquoi on ne reconnaît pas que Docker a apporté quelque chose de réellement utile, principalement pour la distribution de logiciels et le « ça tourne facilement partout ».
Docker est une combinaison de technologies du noyau qui existaient déjà : namespaces, cgroups, systèmes de fichiers union, et probablement quelques autres.
C’est donc intéressant, et c’est pratiquement l’histoire HN parfaite.
Ce n’est qu’après l’avoir montré à quelques personnes que j’ai réalisé qu’elles auraient pu simplement utiliser
/, ou bien que j’aurais pu leur apporter Docker.Dans le genre frère d’une autre mère, il y a https://bastillebsd.org/.
Bastille utilise en shell beaucoup de structures qu’on s’attendrait à voir dans Docker pour gérer les jails FreeBSD. Il a très peu de dépendances, ce qui me le fait préférer à d’autres logiciels de gestion de jails sous BSD.
Cela dit, même si c’est un outil CLI/TUI, c’est une solution proche du « maximum d’excès ». Ces temps-ci, je passe par les étapes de création et de gestion des jails uniquement avec la configuration de base de FreeBSD, mais ce n’est qu’une phase temporaire.
Je continuerai seulement jusqu’à avoir suffisamment gravé dans ma tête la façon dont tout s’imbrique pour être à l’aise en debug ; ensuite, comme une personne raisonnable, j’arrêterai de taper des cailloux les uns contre les autres et je reviendrai à des outils de plus haut niveau.
En revanche, il m’a fallu un moment pour comprendre pourquoi il s’appelait Bastille. La Bastille était une forteresse construite pendant la guerre de Cent Ans pour défendre Paris contre les attaques anglaises, puis elle a été transformée en prison.
Il faut faire attention à la partie disant que « la plupart des distributions ne fournissent pas une version suffisamment récente de util-linux, donc il faudra récupérer les sources ici et compiler soi-même ».
Le préfixe d’installation par défaut étant
/usr/bin, l’installation peut écraser la commande mount existante par une version qui exige des bibliothèques inexistantes. Au démarrage suivant, le noyau montera alors le système de fichiers en lecture seule./usr/local/bin.Ce n’est pas idéal pour un usage quotidien, mais ça donne une idée de ce qu’est Docker et de son fonctionnement.
Sous Linux, Docker est fondamentalement un chroot sophistiqué.
Fait amusant : Docker a commencé en Bash, puis a été porté en Python avant de finalement se fixer sur Go.
Et lors d’un meetup Docker en 2013, quelqu’un avait écrit un clone de Docker en Bash. Les gens veulent apprendre, et j’espère que ce genre de choses les aide.