Docker rhel7
| Fiche express | |
|---|---|
| Contexte | Installation et usage de Docker sur RHEL 7 |
| Isolation noyau | Espaces de noms (namespaces) + cgroups + SELinux |
| Limites théoriques | ~6000 conteneurs et ~12000 points de montage par machine (ordre de grandeur, à vérifier selon version noyau) |
| Voir aussi | RHEL7 · SELinux · cgroups · Firewalld · Docker users |
RHEL 7 est une des plateformes historiques où Docker a été packagé et supporté par Red Hat, avec des dépôts et une intégration SELinux spécifiques. Cette page couvre l'installation et l'usage de Docker propres à RHEL 7, ainsi que les mécanismes noyau (espaces de noms, cgroups) sur lesquels reposent tous les conteneurs Linux, indépendamment de la distribution.
Mécanismes noyau sous-jacents
Docker ne virtualise rien : il isole des processus ordinaires du noyau hôte à l'aide de plusieurs mécanismes combinés.
Espaces de noms (namespaces)
Le noyau Linux fournit une séparation par espace de noms pour plusieurs ressources :
- mount — isole la vue du système de fichiers : le conteneur voit une racine (
/) qui lui est propre. - PID — chaque conteneur a son propre arbre de processus, numéroté indépendamment de l'hôte.
- network — chaque conteneur dispose de sa propre interface réseau et de ses propres tables de routage.
- IPC — les ressources de communication inter-processus (mémoire partagée, sémaphores) sont cloisonnées : deux conteneurs ne peuvent pas interagir par mémoire partagée sans configuration explicite.
- UTS — le conteneur peut porter un nom d'hôte différent de celui de la machine physique.
cgroups et SELinux
Les cgroups limitent et comptabilisent la consommation de ressources (CPU, mémoire, I/O) par conteneur, tandis que SELinux (activé par défaut sur RHEL) ajoute une couche de contrôle d'accès obligatoire qui limite ce qu'un processus conteneurisé peut faire même s'il parvient à s'échapper d'un des espaces de noms ci-dessus. Sur RHEL 7, ces deux briques sont actives par défaut avec Docker et ne doivent pas être désactivées à la légère pour « simplifier » un déploiement.
Conteneurs et machines virtuelles
| Critère | Conteneurs | Machines virtuelles |
|---|---|---|
| Poids / démarrage | Légers, démarrage quasi instantané | Plus lourdes, démarrage plus lent |
| Noyau | Partagé avec l'hôte | Noyau dédié par VM |
| Isolation | Espaces de noms + cgroups + LSM (SELinux/AppArmor) | Isolation matérielle via l'hyperviseur, plus forte |
| Portabilité entre machines | Très bonne (image versionnée) | Bonne mais images plus volumineuses |
| Migration à chaud | Non, nativement | Oui, sur la plupart des hyperviseurs |
| Hétérogénéité d'OS invité | Non (noyau hôte partagé) | Oui (chaque VM a son propre OS) |
Les conteneurs conviennent bien à la portabilité et à la densité ; les VM restent nécessaires quand une isolation forte au niveau noyau ou une hétérogénéité de systèmes d'exploitation est requise.
Installation sur RHEL 7
Sur les versions de RHEL où Docker est distribué via les dépôts extras/optional :
subscription-manager repos --enable=rhel-7-server-extras-rpms
subscription-manager repos --enable=rhel-7-server-optional-rpms
yum install docker
systemctl start docker.service
systemctl enable docker.service
docker version
L'unit systemd du service se trouve dans /lib/systemd/system/docker.service.
Gestion des images
# Recherche d'une image sur le registre configuré
docker search nom_image
docker search --stars=1 --trusted fedora
# Récupération d'une image
docker pull depot/nom_image
# Lister les images locales
docker images
# Supprimer une image
docker rmi nom_image
Sur un hôte RHEL, il est courant de partir des images officielles Red Hat plutôt que de Docker Hub :
docker pull registry.access.redhat.com/redhat/rhel7
# ou, en air-gap, à partir d'une archive fournie
docker load -i rhel-server-docker-7.tar.gz
docker images
Cycle de vie d'un conteneur
# Démarrer un conteneur
docker run --name=mon_conteneur nom_image commande
# Lister les conteneurs (actifs, puis tous)
docker ps
docker ps -a
# Arrêter / tuer
docker stop mon_conteneur
docker kill mon_conteneur
# Redémarrer
docker start mon_conteneur
docker restart mon_conteneur
# Supprimer
docker rm mon_conteneur
Exemple d'exécution interactive puis de reprise d'un conteneur existant :
docker run -i -t --rm rhel7 cat /etc/hosts
docker ps -a
docker start -ai <nom_du_conteneur_existant>
Créer une image à partir d'un conteneur (commit)
Approche manuelle, à réserver au dépannage ou à l'exploration : en usage courant, on préfère un Dockerfile versionné (voir plus bas).
docker run -i rhel7 bash -c "yum install -y httpd; yum clean all"
docker ps -l
docker commit -m "rhel7 + httpd" <nom_du_conteneur> rhel_httpd
docker images
docker run -p 8080:80 -d rhel_httpd /usr/sbin/httpd -DFOREGROUND
curl http://localhost:8080
Connexion et inspection d'un conteneur
# PID du processus principal du conteneur, côté hôte
docker inspect -f '{{.State.Pid}}' id_conteneur
# Entrer dans les espaces de noms du conteneur depuis l'hôte
nsenter -m -u -n -i -p -t <pid_hote_du_conteneur> /bin/sh
docker info
docker inspect mon_conteneur
docker inspect -f '{{.Section.Sous_section}}' mon_conteneur
Journaux et historique
# Différences de système de fichiers par rapport à l'image d'origine
docker diff mon_conteneur
# Journaux applicatifs du conteneur
docker logs mon_conteneur
# Historique des couches d'une image
docker history nom_image
# Consommation de ressources en direct
docker top mon_conteneur
Construire une image avec un Dockerfile
Instructions principales disponibles dans un Dockerfile :
FROM · MAINTAINER (obsolète, remplacé par un label) · RUN · CMD · EXPOSE · ENV · ADD · ENTRYPOINT · VOLUME · USER (voir Docker users) · WORKDIR · ONBUILD
Exemple, un conteneur Apache minimal :
FROM registry.access.redhat.com/redhat/rhel7beta
LABEL maintainer="<nom> <email>"
RUN yum -y update; yum clean all
RUN yum -y install httpd; yum clean all
RUN echo "Apache" >> /var/www/html/index.html
EXPOSE 80
# Script de démarrage pour éviter les soucis observés au redémarrage du conteneur
ADD run-apache.sh /run-apache.sh
RUN chmod -v +x /run-apache.sh
CMD ["/run-apache.sh"]
#!/bin/bash
rm -rf /run/httpd/*
exec /usr/sbin/apachectl -D FOREGROUND
Construction de l'image :
docker build --tag=nom:tag chemin_du_contexte
Réseau et événements
# Port publié d'un conteneur pour un port privé donné
docker port mon_conteneur port_prive
# Flux d'événements du démon
docker events
docker events --since '2024-01-01'
Sur un hôte RHEL avec firewalld actif, penser à ouvrir les ports publiés si le trafic doit venir d'une autre machine que l'hôte lui-même.
Copier des données entre hôte et conteneur
docker cp mon_conteneur:/chemin/dans/le/conteneur ./chemin_hote
docker cp mon_conteneur:/etc/hosts .
Volumes de données
docker run --name=mon_conteneur --volume=/chemin/hote nom_image commande
docker run --name=conteneur2 --volumes-from=conteneur1 nom_image commande
Partage de volumes entre conteneurs via un conteneur de données dédié :
docker run --name=data -v /var/volume1 -v /var/volume2 rhel7-data true
docker run --volumes-from=data --name=conteneur1 rhel7 bash
Archives : export, import, sauvegarde
# Export du système de fichiers d'un conteneur (perd l'historique des couches)
docker export mon_conteneur > conteneur.tar
docker import conteneur.tar
# Sauvegarde/restauration d'une image avec ses métadonnées de couches
docker save --output=nom_image.tar nom_image
docker load --input=nom_image.tar
export/import aplatit le système de fichiers en une seule couche (utile pour réduire la taille, mais perd l'historique) ; save/load conserve la structure en couches de l'image.
Publier des images vers un registre privé
Installation d'un registre historique via le paquet docker-registry (pour une approche plus moderne, voir Docker registry avec l'image officielle registry) :
yum install docker-registry
systemctl start docker-registry
systemctl enable docker-registry
firewall-cmd --add-port=5000/tcp
firewall-cmd --add-port=5000/tcp --permanent
docker tag rhel_httpd registry.example.com:5000/mon_utilisateur/httpd
docker images
docker push registry.example.com:5000/mon_utilisateur/httpd
Connexion à un registre nécessitant une authentification :
docker login --username="<utilisateur>" --password="<mot de passe>" registry.example.com:5000
Passer un mot de passe en clair sur la ligne de commande l'expose dans l'historique du shell et la liste des processus : préférer un login interactif ou un gestionnaire de secrets en production.
Nettoyage
docker stop mon_conteneur
docker rm mon_conteneur
docker rmi nom_image
docker info