Comme je m’intéresse à PostgreSql (“The World’s Most Advanced Open Source Relational Database”) et Docker, j’ai décidé d’installer Docker et l’image PostgreSql afin d’en cerner les avantages et inconvénients par rapport à la virtualisation classique.

Préparation

Comme d’habitude, il convient de mettre à jour Debian (ici en version 11) avant d’installer des paquets:

    
1sudo apt-get update && sudo apt-get upgrade

Ensuite, il faut installer les paquets suivants (j’ai juste eu besoin de apt-transport-https, le reste est déjà installé sur ma version):

    
1sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release

Installation de Docker

Ajout du repository

On commence par installer la clé PGP de Docker avec ces commandes:

    
1curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Puis on ajoute le repository Docker:

    
1echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Installation des paquets Docker

On fait une nouvelle mise à jour Debian afin de prendre en compte le repository puis on installe les paquets Docker:

    
1sudo apt-get update
2sudo apt-get install docker-ce docker-ce-cli containerd.io

Stockage des images et données

Avant d’aller plus loin, il faut savoir que les images Docker peuvent vite remplir le disque. Pour éviter que mon disque système déborde, j’ai choisi de déplacer les images dans ma partition /opt.

Pour cela, il faut d’ajouter ajouter le dossier /opt/docker_images puis il faut éditer le fichier /etc/docker/daemon.json et ajouter les lignes suivantes:

    
1{
2"data-root": "/opt/docker_images"
3}

Contrôle de l’installation

Une fois l’installation terminée, on peut vérifier que Docker est prêt grâce aux commandes suivantes (réponses en bleu):

    
1sudo systemctl is-enabled docker
2enabled
    
1sudo systemctl is-enabled containerd
2enabled
    
 1systemctl status docker containerd
 2 docker.service - Docker Application Container Engine
 3     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
 4     Active: active (running) since Sat 2021-12-25 16:51:16 CET; 3min 48s ago
 5TriggeredBy:  docker.socket
 6       Docs: https://docs.docker.com
 7   Main PID: 28277 (dockerd)
 8      Tasks: 13
 9     Memory: 36.0M
10        CPU: 275ms
11     CGroup: /system.slice/docker.service
12             └─28277 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
13
14Dec 25 16:51:15 station.gtg dockerd[28277]: time="2021-12-25T16:51:15.913595169+01:00" level=info msg="scheme \"unix\" not registered, fallback to default scheme" module=grpc
15Dec 25 16:51:15 station.gtg dockerd[28277]: time="2021-12-25T16:51:15.913612836+01:00" level=info msg="ccResolverWrapper: sending update to cc: {[{unix:///run/containerd/containerd.sock  <nil> 0 <nil>}] <ni>
16Dec 25 16:51:15 station.gtg dockerd[28277]: time="2021-12-25T16:51:15.913624402+01:00" level=info msg="ClientConn switching balancer to \"pick_first\"" module=grpc
17Dec 25 16:51:16 station.gtg dockerd[28277]: time="2021-12-25T16:51:16.016000291+01:00" level=info msg="Loading containers: start."
18Dec 25 16:51:16 station.gtg dockerd[28277]: time="2021-12-25T16:51:16.207380620+01:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used >
19Dec 25 16:51:16 station.gtg dockerd[28277]: time="2021-12-25T16:51:16.279475675+01:00" level=info msg="Loading containers: done."
20Dec 25 16:51:16 station.gtg dockerd[28277]: time="2021-12-25T16:51:16.301485806+01:00" level=info msg="Docker daemon" commit=459d0df graphdriver(s)=overlay2 version=20.10.12
21Dec 25 16:51:16 station.gtg dockerd[28277]: time="2021-12-25T16:51:16.301591296+01:00" level=info msg="Daemon has completed initialization"
22Dec 25 16:51:16 station.gtg systemd[1]: Started Docker Application Container Engine.
23Dec 25 16:51:16 station.gtg dockerd[28277]: time="2021-12-25T16:51:16.351774256+01:00" level=info msg="API listen on /run/docker.sock"
    
 1sudo systemctl status containerd
 2 containerd.service - containerd container runtime
 3     Loaded: loaded (/lib/systemd/system/containerd.service; enabled; vendor preset: enabled)
 4     Active: active (running) since Sat 2021-12-25 16:51:14 CET; 6min ago
 5       Docs: https://containerd.io
 6   Main PID: 28192 (containerd)
 7      Tasks: 13
 8     Memory: 21.8M
 9        CPU: 252ms
10     CGroup: /system.slice/containerd.service
11             └─28192 /usr/bin/containerd
12
13Dec 25 16:51:14 station.gtg containerd[28192]: time="2021-12-25T16:51:14.783865144+01:00" level=info msg="loading plugin \"io.containerd.grpc.v1.namespaces\"..." type=io.containerd.grpc.v1
14Dec 25 16:51:14 station.gtg containerd[28192]: time="2021-12-25T16:51:14.783876315+01:00" level=info msg="loading plugin \"io.containerd.internal.v1.opt\"..." type=io.containerd.internal.v1
15Dec 25 16:51:14 station.gtg containerd[28192]: time="2021-12-25T16:51:14.784109298+01:00" level=info msg="loading plugin \"io.containerd.grpc.v1.snapshots\"..." type=io.containerd.grpc.v1
16Dec 25 16:51:14 station.gtg containerd[28192]: time="2021-12-25T16:51:14.784128313+01:00" level=info msg="loading plugin \"io.containerd.grpc.v1.tasks\"..." type=io.containerd.grpc.v1
17Dec 25 16:51:14 station.gtg containerd[28192]: time="2021-12-25T16:51:14.784142614+01:00" level=info msg="loading plugin \"io.containerd.grpc.v1.version\"..." type=io.containerd.grpc.v1
18Dec 25 16:51:14 station.gtg containerd[28192]: time="2021-12-25T16:51:14.784155687+01:00" level=info msg="loading plugin \"io.containerd.grpc.v1.introspection\"..." type=io.containerd.grpc.v1
19Dec 25 16:51:14 station.gtg containerd[28192]: time="2021-12-25T16:51:14.784347206+01:00" level=info msg=serving... address=/run/containerd/containerd.sock.ttrpc
20Dec 25 16:51:14 station.gtg containerd[28192]: time="2021-12-25T16:51:14.784384609+01:00" level=info msg=serving... address=/run/containerd/containerd.sock
21Dec 25 16:51:14 station.gtg containerd[28192]: time="2021-12-25T16:51:14.784422458+01:00" level=info msg="containerd successfully booted in 0.047712s"
22Dec 25 16:51:14 station.gtg systemd[1]: Started containerd container runtime.

Ajout des droits utilisateurs

Par défaut, seul le root peut lancer Docker. Pour une question de facilité (démarrage à la demande) et de sécurité (on travaille le moins possible avec le compte root), il vaut mieux autoriser son compte (ou un autre) à lancer Docker. Cela se fait simplement avec la commande:

    
1sudo usermod -aG docker <login>

Ensuite, en voulant tester Docker avec la commande docker run hello-world, j’ai reçu le message suivant:

    
1got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create?name=redis: dial unix /var/run/docker.sock: connect: permission denied

Pour corriger cela, il faut autoriser son compte (ou le même qu’à l’étape précédente) à écrire le fichier de lock avec la commande:

    
1sudo setfacl --modify user:<login>:rw /var/run/docker.sock

A ce stade, Docker est prêt!

Création de l’image PostgreSql

Récupération de l’image

Il existe une image PostgreSql officielle pour Docker et il faut lancer la préparation avec la commande docker pull postgres.La réponse est la suivante:

    
 1Using default tag: latest
 2latest: Pulling from library/postgres
 3a2abf6c4d29d: Pull complete 
 4e1769f49f910: Pull complete 
 533a59cfee47c: Pull complete 
 6461b2090c345: Pull complete 
 78ed8ab6290ac: Pull complete 
 8495e42c822a0: Pull complete 
 918e858c71c58: Pull complete 
10594792c80d5f: Pull complete 
11794976979956: Pull complete 
12eb5e1a73c3ca: Pull complete 
136d6360292cba: Pull complete 
14131e916e1a28: Pull complete 
15757a73507e2e: Pull complete 
16Digest: sha256:f329d076a8806c0ce014ce5e554ca70f4ae9407a16bb03baa7fef287ee6371f1
17Status: Downloaded newer image for postgres:latest
18docker.io/library/postgres:latest

Création d’un volume de stockage

Par défaut, Docker ne persiste pas le contenu des images et c’est un peu gênant pour une base de données de voir son contenu réinitialisé à chaque démarrage. Pour activer le stockage, il faut d’abord créer un volume dédié avec la commande suivante:

    
1docker volume create pgdata

On peut vérifier que le volume est créé et quel dossier contient les fichiers qui vont être sauvés grâce à la commande:

    
1docker volume inspect pgdata

On obtient une réponse au format JSON:

    
 1[
 2    {
 3        "CreatedAt": "2022-01-22T16:58:42+01:00",
 4        "Driver": "local",
 5        "Labels": {},
 6        "Mountpoint": "/opt/docker_images/volumes/pgdata/_data",
 7        "Name": "pgdata",
 8        "Options": {},
 9        "Scope": "local"
10    }
11]

En rouge, il s’agit du dossier qu’on a définit dans le fichier /etc/docker/daemon.json. En bleu, il s’agit du nom du volume.

Démarrage de l’image

Pour démarrer notre image PostgreSql, il suffit simplement d’exécuter la commande:

    
1docker run -d --name=pgsql -p 5432:5432 --mount source=pgdata,target=/var/lib/postgresql/data -e POSTGRES_PASSWORD=<mot de passe> postgres

On trouve beaucoup (tous en fait) de tutoriels qui indiquent d’utiliser le paramètre “-v” pour désigner le volume à prendre en compte. Cela fonctionne uniquement si le container est en mode interactif. Dans mon cas, le container est lancé en daemon (paramètre “-d”) et il faut alors utiliser le paramètre “--mount” pour lier le volume au container.

Connexion au serveur PostgreSql

J’ai ajouté une connexion dans dBeaver (un des meilleurs clients SQL Open source) comme ceci:

PostgreSql: connexion avec dBeaver

PostgreSql: connexion avec dBeaver

Pour vérifier que Docker ne perd pas les modifications, je vais ajouter une table à la base avec cette requête:

    
1CREATE TABLE public.test (
2	id varchar(36) NULL
3);

Contrôler la persistance du volume

Pour vérifier que le volume a bien enregistré les fichiers de PostgreSql, on va arrêter le container puis le relancer. Normalement on doit retrouver la table de test créée à l’étape précédente. On commence par trouver l’identifiant du container:

    
1docker ps
2CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                                       NAMES
3a81ad52651f8   postgres   "docker-entrypoint.s…"   17 minutes ago   Up 17 minutes   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   pgsql

Puis on arrête le container avec la commande suivante:

    
1docker container stop a81ad52651f8 && docker container rm a81ad52651f8

Et maintenant on relance notre image avec la même commande qu’au lancement initial:

    
1docker run -d --name=pgsql -p 5432:5432 --mount source=pgdata,target=/var/lib/postgresql/data -e POSTGRES_PASSWORD=<mot de passe> postgres

Puis on se connecte au serveur PostgreSql avec dBeaver et magie! La table de test est présente.

Docker: la table est toujours présente

Docker: la table est toujours présente

Conclusion

L’installation de Docker ne pose aucune difficulté, l’ajout d’image est très simple. La gestion des images et containers est plutôt aisée. Le point fort de ce type de virtualisation est de ne pas avoir à installer un OS à chaque fois.