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:
1
| sudo 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):
1
| sudo 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:
1
| curl -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:
1
| echo "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:
1
2
| sudo apt-get update
sudo 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
3
| {
"data-root": "/opt/docker_images"
}
|
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):
1
2
| sudo systemctl is-enabled docker
enabled
|
1
2
| sudo systemctl is-enabled containerd
enabled
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| systemctl status docker containerd
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2021-12-25 16:51:16 CET; 3min 48s ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 28277 (dockerd)
Tasks: 13
Memory: 36.0M
CPU: 275ms
CGroup: /system.slice/docker.service
└─28277 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Dec 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
Dec 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>
Dec 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
Dec 25 16:51:16 station.gtg dockerd[28277]: time="2021-12-25T16:51:16.016000291+01:00" level=info msg="Loading containers: start."
Dec 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 >
Dec 25 16:51:16 station.gtg dockerd[28277]: time="2021-12-25T16:51:16.279475675+01:00" level=info msg="Loading containers: done."
Dec 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
Dec 25 16:51:16 station.gtg dockerd[28277]: time="2021-12-25T16:51:16.301591296+01:00" level=info msg="Daemon has completed initialization"
Dec 25 16:51:16 station.gtg systemd[1]: Started Docker Application Container Engine.
Dec 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"
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| sudo systemctl status containerd
● containerd.service - containerd container runtime
Loaded: loaded (/lib/systemd/system/containerd.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2021-12-25 16:51:14 CET; 6min ago
Docs: https://containerd.io
Main PID: 28192 (containerd)
Tasks: 13
Memory: 21.8M
CPU: 252ms
CGroup: /system.slice/containerd.service
└─28192 /usr/bin/containerd
Dec 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
Dec 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
Dec 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
Dec 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
Dec 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
Dec 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
Dec 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
Dec 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
Dec 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"
Dec 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:
1
| sudo usermod -aG docker <login>
|
Ensuite, en voulant tester Docker avec la commande docker run hello-world
, j’ai reçu le message suivant:
1
| got 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:
1
| sudo 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| Using default tag: latest
latest: Pulling from library/postgres
a2abf6c4d29d: Pull complete
e1769f49f910: Pull complete
33a59cfee47c: Pull complete
461b2090c345: Pull complete
8ed8ab6290ac: Pull complete
495e42c822a0: Pull complete
18e858c71c58: Pull complete
594792c80d5f: Pull complete
794976979956: Pull complete
eb5e1a73c3ca: Pull complete
6d6360292cba: Pull complete
131e916e1a28: Pull complete
757a73507e2e: Pull complete
Digest: sha256:f329d076a8806c0ce014ce5e554ca70f4ae9407a16bb03baa7fef287ee6371f1
Status: Downloaded newer image for postgres:latest
docker.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:
1
| docker 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:
1
| docker volume inspect pgdata
|
On obtient une réponse au format JSON:
1
2
3
4
5
6
7
8
9
10
11
| [
{
"CreatedAt": "2022-01-22T16:58:42+01:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/opt/docker_images/volumes/pgdata/_data",
"Name": "pgdata",
"Options": {},
"Scope": "local"
}
]
|
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:
1
| docker 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
Pour vérifier que Docker ne perd pas les modifications, je vais ajouter une table à la base avec cette requête:
1
2
3
| CREATE TABLE public.test (
id varchar(36) NULL
);
|
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:
1
2
3
| docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a81ad52651f8 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:
1
| docker container stop a81ad52651f8 && docker container rm a81ad52651f8
|
Et maintenant on relance notre image avec la même commande qu’au lancement initial:
1
| docker 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
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.
C’est par ici