October 15, 2024

Biotechnologie News

Classe Mondiale Technologie

Désacralisation du système de fichiers superposé Linux dans Docker

Les systèmes de fichiers superposés (également appelés systèmes de fichiers d’union) sont une technologie fondamentale de Docker pour créer des images et des conteneurs. Ils permettent de créer une union de répertoires pour créer un système de fichiers. Plusieurs systèmes de fichiers, qui ne sont que des répertoires, sont superposés les uns sur les autres pour créer un nouveau système de fichiers. Ces répertoires sont appelés couches et le processus d’unification est appelé montage d’union. Si deux fichiers avec le même chemin existent dans deux couches, seul le dernier fichier apparaîtra dans le système de fichiers superposé.

Nous apprendrons comment créer nous-mêmes un système de fichiers superposé et comment Docker l’utilise pour créer des images et exécuter des conteneurs.

Créer un système de fichiers superposé est facile

Le système de fichiers superposé est constitué de deux types de système de fichiers. Un ou plus plus bas systèmes de fichiers immuables. Leur contenu est uniquement lu et aucune modification n’interviendra à l’intérieur. Une plus haut Le système de fichiers reçoit toutes les modifications du système de fichiers superposé, y compris les créations, modifications et suppressions de fichiers.

La création d’un système de fichiers superposé est facile une fois que vous avez mis la main dessus. Tout ce dont vous avez besoin pour une machine Linux avec un accès root ou sudoer. Une machine virtuelle fera l’affaire.

Nous initialisons la mise en page en créant plusieurs dossiers, chacun d’eux correspondant à un calque. Nous avons également besoin d’un mount dossier à l’endroit où nous voulons que le système de fichiers superposé soit créé et un workdir dossier à des fins internes.

mkdir overlay; cd overlay
mkdir \
  lower-layer-1 lower-layer-2 lower-layer-3 upper-layer \
  mount \
  workdir

Créons également des fichiers dans 3 dossiers. Nous laissons le dossier supérieur vide.

echo "Content layer 1" > ./lower-layer-1/file-in-layer-1
echo "Content layer 2" > ./lower-layer-2/file-in-layer-2
echo "Content layer 3" > ./lower-layer-3/file-in-layer-3

Deux répertoires ou plus sont requis. Ils font une liste de répertoires inférieurs et un répertoire supérieur. Les répertoires inférieurs du système de fichiers sont en lecture seule, tandis que le répertoire supérieur peut être utilisé à la fois pour les lectures et les écritures. La mount La commande crée le système de fichiers superposé avec le type externe -t mis à overlay. Il doit être exécuté comme root.

sudo mount -t overlay my-overlay \
  -o lowerdir=$HOME/overlay/lower-layer-1:$HOME/overlay/lower-layer-2:$HOME/overlay/lower-layer-3,upperdir=$HOME/overlay/upper-layer,workdir=$HOME/overlay/workdir \
  $HOME/overlay/mount

La df La commande répertorie tous les systèmes de fichiers ainsi que des informations utiles telles que la quantité d’espace libre et le type de système de fichiers lorsqu’il est exécuté avec la commande -T Drapeau. La -h flag n’est là que pour imprimer la taille du système de fichiers dans un format lisible par l’homme.

df -Th | grep overlay
my-overlay overlay    20G  5.5G   14G  29% /home/ubuntu/overlay/mount

Le système de fichiers superposé est créé et monté à l’intérieur du mount dossier. Il contient les fichiers de tous les systèmes de fichiers d’origine.

ls -l mount
total 12
-rw-rw-r-- 1 ubuntu ubuntu 13 Jun  2 22:38 file-in-layer-1
-rw-rw-r-- 1 ubuntu ubuntu 13 Jun  2 22:38 file-in-layer-2
-rw-rw-r-- 1 ubuntu ubuntu 13 Jun  2 22:38 file-in-layer-3

cat mount/file-in-layer-3 
Content layer 3

Essayons de créer un fichier dans le dossier de montage :

echo "new content" > mount/new-file

Il est écrit dans le répertoire supérieur, upper-layer:

tree
.
├── lower-layer-1
│   └── file-in-layer-1
├── lower-layer-2
│   └── file-in-layer-2
├── lower-layer-3
│   └── file-in-layer-3
├── mount
│   ├── new-file
│   ├── file-in-layer-1
│   ├── file-in-layer-2
│   └── file-in-layer-3
├── upper-layer
│   └── new-file
└── workdir
    └── work [error opening dir]

7 directories, 8 files

Maintenant, nous modifions un fichier, par exemple, file-in-layer-1.

echo 'Add a new line' >> mount/file-in-layer-1

Le fichier original présent à l’intérieur lower-layer-1 n’est pas modifié. Au lieu de cela, un nouveau fichier dans upper-layer est créé:

cat lower-layer-1/file-in-layer-1 
Content layer 1

cat upper-layer/file-in-layer-1 
Content layer 1
Add a new line

cat mount/file-in-layer-1 
Content layer 1
Add a new line

Voyons le comportement lors de la suppression d’un fichier, par exemple, file-in-layer-2.

Le fichier original à l’intérieur lower-layer-2 est toujours là. Un nouveau dossier dans upper-layer est créé avec un type spécial, c’est un fichier de caractères. C’est ainsi que le système de fichiers superposé représente un fichier supprimé.

ls -l lower-layer-2/file-in-layer-2 
-rw-rw-r-- 1 ubuntu ubuntu 13 Jun  2 22:38 lower-layer-2/file-in-layer-2

ls -l upper-layer/file-in-layer-2 
c--------- 1 root root 0, 0 Jun  2 23:33 upper-layer/file-in-layer-2

Maintenant que le laboratoire est terminé, nous pouvons démonter le système de fichiers et purger nos fichiers.

sudo umount $HOME/overlay/mount

ls -l mount/
total 0

cd ..
rm -rf overlay

Superposition dans Docker

Docker prend en charge plusieurs pilotes de stockage pour écrire des données sur la couche inscriptible d’un conteneur, SuperpositionFS est le pilote de stockage recommandé. Si vous imprimez les informations à partir de votre installation Docker locale, il est probable qu’elle imprime le overlay2 pilote de stockage.

docker info | grep "Storage Driver"
 Storage Driver: overlay2

Docker utilise le système de fichiers de superposition pour créer des images ainsi que pour positionner la couche de conteneur au-dessus des couches d’image.

Lorsqu’une image est téléchargée, ses calques sont situés à l’intérieur du /var/lib/docker/overlay2 dossier. Par exemple, télécharger une image à 3 couches en utilisant docker pull ubuntu crée 3+1 répertoires. La l Le répertoire contient des identifiants de couche raccourcis sous forme de liens symboliques.

docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
345e3491a907: Pull complete 
57671312ef6f: Pull complete 
5e9250ddb7d0: Pull complete 
Digest: sha256:adf73ca014822ad8237623d388cedf4d5346aa72c270c5acc01431cc93e18e2d
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

Dans mon cas, 3 couches sont téléchargées :

ls -l /var/lib/docker/overlay2/
total 16
drwx------ 4 root root 4096 Jun  3 11:21 289a71f4e07caadc95892ac5b4027606bb93c69d1a23d0e866818cdb1179644b/
drwx------ 4 root root 4096 Jun  3 11:21 40766b9f546e9826ff353976c167f60cb615f57c01926a607ab48a2df64806ab/
drwx------ 3 root root 4096 Jun  3 11:21 88826e8f5f21df691dbd998df70d94e1b6b480e489c4dbb5999dcc8a7367159e/
drwx------ 2 root root 4096 Jun  3 11:21 l/

ls -l /var/lib/docker/overlay2/l/
total 12
lrwxrwxrwx 1 root root 72 Jun  3 11:21 NSEHV6LZKQIRKICXA2T7T5252D -> ../88826e8f5f21df691dbd998df70d94e1b6b480e489c4dbb5999dcc8a7367159e/diff/
lrwxrwxrwx 1 root root 72 Jun  3 11:21 QPAIOX2SCZPFZIIXB27PFVHUPH -> ../40766b9f546e9826ff353976c167f60cb615f57c01926a607ab48a2df64806ab/diff/
lrwxrwxrwx 1 root root 72 Jun  3 11:21 USIDUBYHQEGWIRN4JOSF74ZWIL -> ../289a71f4e07caadc95892ac5b4027606bb93c69d1a23d0e866818cdb1179644b/diff/

Ces couches sont également exposées en inspectant l’image Docker. La sortie de la commande Docker est au format JSON. Nous utilisons jq pour filtrer la partie qui nous intéresse le plus.

docker image inspect ubuntu | jq -r '.[0] | Data: .GraphDriver.Data'

  "Data": 
    "LowerDir":  "/var/lib/docker/overlay2/40766b9f546e9826ff353976c167f60cb615f57c01926a607ab48a2df64806ab/diff:/var/lib/docker/overlay2/88826e8f5f21df691dbd998df70d94e1b6b480e489c4dbb5999dcc8a7367159e/diff",
    "MergedDir": "/var/lib/docker/overlay2/289a71f4e07caadc95892ac5b4027606bb93c69d1a23d0e866818cdb1179644b/merged",
    "UpperDir":  "/var/lib/docker/overlay2/289a71f4e07caadc95892ac5b4027606bb93c69d1a23d0e866818cdb1179644b/diff",
    "WorkDir":   "/var/lib/docker/overlay2/289a71f4e07caadc95892ac5b4027606bb93c69d1a23d0e866818cdb1179644b/work"
  

L’ordre de priorité commence par le répertoire supérieur, puis évalue les répertoires inférieurs de gauche à droite. Ainsi, les couches sont évaluées dans cet ordre :

1: 88826e8f5f21df691dbd998df70d94e1b6b480e489c4dbb5999dcc8a7367159e
2: 40766b9f546e9826ff353976c167f60cb615f57c01926a607ab48a2df64806ab
3: 289a71f4e07caadc95892ac5b4027606bb93c69d1a23d0e866818cdb1179644b

En commençant par la première couche à évaluer, son contenu est le système de fichiers Ubuntu :

ls /var/lib/docker/overlay2/88826e8f5f21df691dbd998df70d94e1b6b480e489c4dbb5999dcc8a7367159e/diff
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

À partir de là, les répertoires supplémentaires de la deuxième couche :

tree /var/lib/docker/overlay2/40766b9f546e9826ff353976c167f60cb615f57c01926a607ab48a2df64806ab/diff/
├── etc
│   ├── apt
│   │   └── apt.conf.d
│   │       ├── docker-autoremove-suggests
│   │       ├── docker-clean
│   │       ├── docker-gzip-indexes
│   │       └── docker-no-languages
│   └── dpkg
│       └── dpkg.cfg.d
│           └── docker-apt-speedup
├── usr
│   └── sbin
│       ├── initctl
│       └── policy-rc.d
└── var
    └── lib
        └── dpkg
            ├── diversions
            └── diversions-old

10 directories, 9 files

Et la troisième couche aussi :

tree /var/lib/docker/overlay2/289a71f4e07caadc95892ac5b4027606bb93c69d1a23d0e866818cdb1179644b/diff/
/var/lib/docker/overlay2/289a71f4e07caadc95892ac5b4027606bb93c69d1a23d0e866818cdb1179644b/diff/
└── run
    └── systemd
        └── container

2 directories, 1 file

Les instructions de création des couches sont définies dans le Dockerfile. La curl commande télécharger le fichier Dockerfile.

curl https://raw.githubusercontent.com/tianon/docker-brew-ubuntu-core/c5bc8f61f0e0a8aa3780a8dc3a09ae6558693117/focal/Dockerfile

Par défaut, il imprime le contenu sur la console.

FROM scratch
ADD ubuntu-focal-core-cloudimg-amd64-root.tar.gz /


RUN set -xe \	\	&& echo '#!/bin/sh' > /usr/sbin/policy-rc.d \	&& echo 'exit 101' >> /usr/sbin/policy-rc.d \	&& chmod +x /usr/sbin/policy-rc.d \	\	&& dpkg-divert --local --rename --add /sbin/initctl \	&& cp -a /usr/sbin/policy-rc.d /sbin/initctl \	&& sed -i 's/^exit.*/exit 0/' /sbin/initctl \	\	&& echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \	\	&& echo 'DPkg::Post-Invoke  true"; ;' > /etc/apt/apt.conf.d/docker-clean \	&& echo 'APT::Update::Post-Invoke ;' >> /etc/apt/apt.conf.d/docker-clean \	&& echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean \	\	&& echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages \	\	&& echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes \	\	&& echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests

RUN [ -z "$(apt-get indextargets)" ]



RUN mkdir -p /run/systemd && echo 'docker' > /run/systemd/container
CMD ["/bin/bash"]CMD hello

La ADD créé la première couche. La première RUN La commande a créé la deuxième couche. La deuxième RUN n’a créé aucun calque car aucun fichier n’a été créé. Le troisième RUN La commande a créé la troisième couche. La CMD La commande n’a créé aucune couche car elle est évaluée au moment de l’exécution lorsque le conteneur est créé à partir de l’image.

Conclusion

Une fois que nous avons compris le fonctionnement des systèmes de fichiers superposés, il est assez facile de voir comment Docker a utilisé le système de fichiers superposé dans son Dockerfile avec une mise en cache supplémentaire entre chaque couche. Il se combine facilement avec le chroot jail pour fournir un système de fichiers isolé au conteneur au-dessus des systèmes de fichiers immuables des couches d’image. La distribution d’images consiste simplement à combiner plusieurs images ensemble comme tar archive.