Docker rhel7

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
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