Chapitre 4. Création d’images


Apprenez à créer vos propres images de conteneur, basées sur des images prédéfinies qui sont prêtes à vous aider. Le processus comprend l’apprentissage des meilleures pratiques pour l’écriture d’images, la définition des métadonnées pour les images, les tests d’images et l’utilisation d’un workflow de constructeur personnalisé pour créer des images à utiliser avec Red Hat OpenShift Service sur AWS.

4.1. Apprendre les meilleures pratiques des conteneurs

Lors de la création d’images conteneur pour fonctionner sur Red Hat OpenShift Service sur AWS, il existe un certain nombre de meilleures pratiques à considérer comme un auteur d’image pour assurer une bonne expérience pour les consommateurs de ces images. Étant donné que les images sont destinées à être immuables et utilisées telles quelles, les lignes directrices suivantes permettent de garantir que vos images sont très consommables et faciles à utiliser sur Red Hat OpenShift Service sur AWS.

Les directives suivantes s’appliquent lors de la création d’une image de conteneur en général et sont indépendantes de l’utilisation ou non des images sur Red Hat OpenShift Service sur AWS.

La réutilisation des images

Dans la mesure du possible, basez votre image sur une image en amont appropriée à l’aide de l’instruction FROM. Cela garantit que votre image peut facilement récupérer des correctifs de sécurité à partir d’une image en amont lorsqu’elle est mise à jour, plutôt que de devoir mettre à jour vos dépendances directement.

De plus, utilisez des balises dans l’instruction FROM, par exemple rhel:rhel7, pour indiquer clairement aux utilisateurs la version d’une image sur laquelle votre image est basée. En utilisant une balise autre que la dernière, vous assurez que votre image n’est pas soumise à des changements qui pourraient entrer dans la dernière version d’une image en amont.

Conserver la compatibilité dans les balises

Lors du marquage de vos propres images, essayez de maintenir la compatibilité rétrograde dans une balise. Ainsi, si vous fournissez une image nommée image et qu’elle inclut actuellement la version 1.0, vous pouvez fournir une balise d’image:v1. Lorsque vous mettez à jour l’image, tant qu’elle continue d’être compatible avec l’image originale, vous pouvez continuer à marquer la nouvelle image:v1, et les consommateurs en aval de cette balise sont en mesure d’obtenir des mises à jour sans être cassés.

Lorsque vous publiez ultérieurement une mise à jour incompatible, puis passez à une nouvelle balise, par exemple image:v2. Cela permet aux consommateurs en aval de passer à la nouvelle version à volonté, mais ne sont pas brisés par inadvertance par la nouvelle image incompatible. Le consommateur en aval utilisant image:la plus longue prend le risque d’introduire des modifications incompatibles.

Évitez les processus multiples

Il ne faut pas démarrer plusieurs services, tels qu’une base de données et un SSHD, à l’intérieur d’un seul conteneur. Ce n’est pas nécessaire car les conteneurs sont légers et peuvent être facilement liés entre eux pour l’orchestration de multiples processus. Le service OpenShift Red Hat sur AWS vous permet de colocaliser et de co-gérer facilement les images associées en les regroupant en un seul pod.

Cette colocation assure que les conteneurs partagent un espace de noms réseau et un stockage pour la communication. Les mises à jour sont également moins perturbatrices car chaque image peut être mise à jour moins fréquemment et indépendamment. Les flux de gestion du signal sont également plus clairs avec un seul processus car vous n’avez pas à gérer les signaux de routage vers les processus engendrés.

Exec dans les scripts d’emballage

De nombreuses images utilisent des scripts d’emballage pour faire une certaine configuration avant de commencer un processus pour le logiciel en cours d’exécution. Lorsque votre image utilise un tel script, ce script utilise exec afin que le processus du script soit remplacé par votre logiciel. Lorsque vous n’utilisez pas exec, les signaux envoyés par votre conteneur vont dans votre script d’emballage au lieu du processus de votre logiciel. Ce n’est pas ce que vous voulez.

Lorsque vous avez un script d’emballage qui démarre un processus pour un serveur. Démarrez votre conteneur, par exemple, en utilisant podman run -i, qui exécute le script d’emballage, qui démarre à son tour votre processus. Lorsque vous souhaitez fermer votre conteneur avec CTRL+C. Lorsque votre script d’emballage utilisé exec pour démarrer le processus serveur, podman envoie SIGINT au processus serveur, et tout fonctionne comme vous l’attendez. Lorsque vous n’avez pas utilisé Exec dans votre script d’emballage, podman envoie SIGINT au processus pour le script d’emballage et votre processus continue de fonctionner comme si rien ne s’était passé.

Il est également à noter que votre processus s’exécute en tant que PID 1 lorsqu’il s’exécute dans un conteneur. Cela signifie que si votre processus principal se termine, l’ensemble du conteneur est arrêté, annulant tous les processus enfants que vous avez lancés à partir de votre processus PID 1.

Nettoyer les fichiers temporaires

Enlevez tous les fichiers temporaires que vous créez pendant le processus de construction. Cela inclut également tous les fichiers ajoutés avec la commande ADD. À titre d’exemple, exécutez la commande yum clean après avoir effectué des opérations d’installation yum.

Il est possible d’empêcher le cache yum de se retrouver dans une couche d’image en créant votre instruction RUN comme suit:

RUN yum -y install mypackage && yum -y install myotherpackage && yum clean all -y
Copy to Clipboard Toggle word wrap

A noter que si vous écrivez plutôt:

RUN yum -y install mypackage
RUN yum -y install myotherpackage && yum clean all -y
Copy to Clipboard Toggle word wrap

Ensuite, la première invocation yum laisse des fichiers supplémentaires dans cette couche, et ces fichiers ne peuvent pas être supprimés lorsque l’opération de nettoyage yum est exécutée plus tard. Les fichiers supplémentaires ne sont pas visibles dans l’image finale, mais ils sont présents dans les couches sous-jacentes.

Le processus de construction du conteneur actuel ne permet pas qu’une commande s’exécute dans une couche ultérieure pour réduire l’espace utilisé par l’image lorsque quelque chose a été supprimé dans une couche antérieure. Cependant, cela pourrait changer à l’avenir. Cela signifie que si vous exécutez une commande rm dans une couche ultérieure, bien que les fichiers soient cachés, cela ne réduit pas la taille globale de l’image à télécharger. Donc, comme avec l’exemple yum clean, il est préférable de supprimer des fichiers dans la même commande qui les a créés, lorsque cela est possible, afin qu’ils ne finissent pas par écrire sur un calque.

De plus, l’exécution de commandes multiples dans une seule instruction RUN réduit le nombre de couches de votre image, ce qui améliore le temps de téléchargement et d’extraction.

Placer les instructions dans l’ordre approprié

Le constructeur de conteneurs lit le Dockerfile et exécute les instructions de haut en bas. Chaque instruction exécutée avec succès crée un calque qui peut être réutilisé la prochaine fois que cette ou une autre image est construite. Il est très important de placer des instructions qui changent rarement en haut de votre Dockerfile. Cela garantit que les prochaines versions de la même image sont très rapides car le cache n’est pas invalidé par des changements de couche supérieure.

À titre d’exemple, si vous travaillez sur un Dockerfile contenant une commande ADD pour installer un fichier sur lequel vous itérez, et une commande RUN pour yum installer un paquet, il est préférable de mettre la commande ADD en dernier:

FROM foo
RUN yum -y install mypackage && yum clean all -y
ADD myfile /test/myfile
Copy to Clipboard Toggle word wrap

De cette façon, chaque fois que vous modifiez myfile et redémarrez podman build ou docker build, le système réutilise le calque mis en cache pour la commande yum et génère uniquement le nouveau calque pour l’opération ADD.

Au lieu de cela, vous avez écrit le Dockerfile comme suit:

FROM foo
ADD myfile /test/myfile
RUN yum -y install mypackage && yum clean all -y
Copy to Clipboard Toggle word wrap

Ensuite, chaque fois que vous avez changé myfile et reran podman build ou docker build, l’opération ADD invaliderait le cache de couche RUN, de sorte que l’opération yum doit également être redémarrée.

Marquer les ports importants

L’instruction EXPOSE met un port dans le conteneur à la disposition du système hôte et d’autres conteneurs. Bien qu’il soit possible de spécifier qu’un port doit être exposé avec une invocation podman run, l’utilisation de l’instruction EXPOSE dans un Dockerfile facilite l’utilisation de votre image pour les humains et les logiciels en déclarant explicitement les ports que votre logiciel doit exécuter:

  • Les ports exposés s’affichent sous podman ps associés aux conteneurs créés à partir de votre image.
  • Les ports exposés sont présents dans les métadonnées de votre image renvoyée par podman inspect.
  • Les ports exposés sont liés lorsque vous reliez un conteneur à un autre.
Définir les variables d’environnement

C’est une bonne pratique de définir des variables d’environnement avec l’instruction ENV. Il s’agit par exemple de définir la version de votre projet. Cela permet aux gens de trouver facilement la version sans regarder le Dockerfile. Autre exemple, la publicité d’un chemin sur le système qui pourrait être utilisé par un autre processus, tel que JAVA_HOME.

Évitez les mots de passe par défaut

Évitez de définir les mots de passe par défaut. Beaucoup de gens étendent l’image et oublient de supprimer ou de modifier le mot de passe par défaut. Cela peut entraîner des problèmes de sécurité si un utilisateur en production se voit attribuer un mot de passe bien connu. Les mots de passe sont paramétrables à l’aide d’une variable d’environnement à la place.

Lorsque vous choisissez de définir un mot de passe par défaut, assurez-vous qu’un message d’avertissement approprié est affiché lors du démarrage du conteneur. Le message doit informer l’utilisateur de la valeur du mot de passe par défaut et expliquer comment le modifier, comme quelle variable d’environnement à définir.

Évitez le sshd

Il est préférable d’éviter de courir sshd dans votre image. La commande podman exec ou docker exec permet d’accéder aux conteneurs qui s’exécutent sur l’hôte local. Alternativement, vous pouvez utiliser la commande oc exec ou la commande oc rsh pour accéder aux conteneurs qui s’exécutent sur le service OpenShift Red Hat sur le cluster AWS. L’installation et l’exécution de sshd dans votre image ouvrent des vecteurs supplémentaires pour les attaques et les exigences pour le correctif de sécurité.

Les volumes utilisés pour les données persistantes

Les images utilisent un volume pour les données persistantes. De cette façon, Red Hat OpenShift Service sur AWS monte le stockage réseau sur le nœud exécutant le conteneur, et si le conteneur se déplace vers un nouveau nœud, le stockage est réattaché à ce nœud. En utilisant le volume pour tous les besoins de stockage persistants, le contenu est conservé même si le conteneur est redémarré ou déplacé. Lorsque votre image écrit des données à des endroits arbitraires dans le conteneur, ce contenu n’a pas pu être préservé.

Les données qui doivent être conservées même après la destruction du conteneur doivent être écrites sur un volume. Les moteurs de conteneurs prennent en charge un drapeau en lecture seule pour les conteneurs, qui peut être utilisé pour appliquer strictement les bonnes pratiques en matière de ne pas écrire de données pour le stockage éphémère dans un conteneur. Concevoir votre image autour de cette capacité rend maintenant plus facile d’en profiter plus tard.

Définir explicitement les volumes dans votre Dockerfile permet aux consommateurs de l’image de comprendre facilement quels volumes ils doivent définir lors de l’exécution de votre image.

Consultez la documentation Kubernetes pour plus d’informations sur la façon dont les volumes sont utilisés dans Red Hat OpenShift Service sur AWS.

Note

En dépit des volumes persistants, chaque instance de votre image a son propre volume, et le système de fichiers n’est pas partagé entre instances. Cela signifie que le volume ne peut pas être utilisé pour partager l’état dans un cluster.

Les lignes directrices suivantes s’appliquent lors de la création d’images de conteneurs spécifiquement destinées à être utilisées sur Red Hat OpenShift Service sur AWS.

4.1.2.1. Activer les images pour la source à l’image (S2I)

Dans le cas des images destinées à exécuter le code d’application fourni par un tiers, comme une image Ruby conçue pour exécuter le code Ruby fourni par un développeur, vous pouvez activer votre image pour travailler avec l’outil de construction Source-à-Image (S2I). Le S2I est un framework qui facilite l’écriture d’images qui prennent le code source de l’application comme entrée et produisent une nouvelle image qui exécute l’application assemblée en sortie.

4.1.2.2. Assistance aux utilisateurs arbitraires

Par défaut, Red Hat OpenShift Service sur AWS exécute des conteneurs à l’aide d’un identifiant utilisateur attribué arbitrairement. Cela fournit une sécurité supplémentaire contre les processus qui s’échappent du conteneur en raison de la vulnérabilité d’un moteur de conteneur et par conséquent l’obtention d’autorisations supplémentaires sur le nœud hôte.

Afin qu’une image soit prise en charge en tant qu’utilisateur arbitraire, les répertoires et les fichiers qui sont écrits par des processus de l’image doivent être détenus par le groupe racine et être lus/en écriture par ce groupe. Les fichiers à exécuter doivent également avoir des autorisations d’exécution de groupe.

L’ajout de ce qui suit à votre Dockerfile définit le répertoire et les autorisations de fichiers pour permettre aux utilisateurs du groupe racine d’y accéder dans l’image construite:

RUN chgrp -R 0 /some/directory && \
    chmod -R g=u /some/directory
Copy to Clipboard Toggle word wrap

Étant donné que l’utilisateur du conteneur est toujours membre du groupe racine, l’utilisateur du conteneur peut lire et écrire ces fichiers.

Avertissement

Des précautions doivent être prises lors de la modification des répertoires et des autorisations de fichiers des zones sensibles d’un conteneur. En cas d’application sur des zones sensibles, telles que le fichier /etc/passwd, ces modifications peuvent permettre la modification de ces fichiers par des utilisateurs involontaires, exposant potentiellement le conteneur ou l’hôte. CRI-O prend en charge l’insertion d’identifiants d’utilisateur arbitraires dans le fichier /etc/passwd d’un conteneur. En tant que tel, changer les autorisations n’est jamais nécessaire.

De plus, le fichier /etc/passwd ne devrait pas exister dans aucune image de conteneur. Dans le cas contraire, l’exécution du conteneur CRI-O ne permettra pas d’injecter un UID aléatoire dans le fichier /etc/passwd. Dans de tels cas, le conteneur pourrait faire face à des difficultés pour résoudre l’UID actif. Le non-respect de cette exigence pourrait avoir une incidence sur la fonctionnalité de certaines applications conteneurisées.

En outre, les processus exécutés dans le conteneur ne doivent pas écouter sur des ports privilégiés, ports inférieurs à 1024, car ils ne fonctionnent pas en tant qu’utilisateur privilégié.

Dans les cas où votre image doit communiquer avec un service fourni par une autre image, comme une image frontale Web qui doit accéder à une image de base de données pour stocker et récupérer des données, votre image consomme un service Red Hat OpenShift sur AWS. Les services fournissent un point de terminaison statique pour l’accès qui ne change pas lorsque les conteneurs sont arrêtés, démarrés ou déplacés. En outre, les services fournissent un équilibrage de charge pour les demandes.

4.1.2.4. Fournir des bibliothèques communes

Dans le cas des images destinées à exécuter le code d’application fourni par un tiers, assurez-vous que votre image contient des bibliothèques couramment utilisées pour votre plate-forme. En particulier, fournissez des pilotes de base de données pour les bases de données communes utilisées avec votre plate-forme. À titre d’exemple, fournissez des pilotes JDBC pour MySQL et PostgreSQL si vous créez une image de framework Java. Cela empêche le téléchargement de dépendances courantes pendant le temps d’assemblage de l’application, accélérant la création d’images d’application. Il simplifie également le travail requis par les développeurs d’applications pour s’assurer que toutes leurs dépendances sont respectées.

4.1.2.5. Les variables d’environnement pour la configuration

Les utilisateurs de votre image sont en mesure de la configurer sans avoir à créer une image en aval en fonction de votre image. Cela signifie que la configuration d’exécution est gérée à l’aide de variables d’environnement. Dans une configuration simple, le processus d’exécution peut consommer les variables d’environnement directement. Dans le cas d’une configuration plus compliquée ou d’exécutions qui ne supportent pas cela, configurez l’exécution en définissant un fichier de configuration de modèle qui est traité au démarrage. Au cours de ce traitement, les valeurs fournies à l’aide de variables d’environnement peuvent être substituées dans le fichier de configuration ou utilisées pour prendre des décisions sur les options à définir dans le fichier de configuration.

Il est également possible et recommandé de transmettre des secrets tels que des certificats et des clés dans le conteneur en utilisant des variables d’environnement. Cela garantit que les valeurs secrètes ne finissent pas par être commises dans une image et divulguées dans un registre d’images conteneur.

Fournir des variables d’environnement permet aux consommateurs de votre image de personnaliser le comportement, tels que les paramètres de base de données, les mots de passe et le réglage des performances, sans avoir à introduire un nouveau calque au-dessus de votre image. Au lieu de cela, ils peuvent simplement définir des valeurs variables d’environnement lors de la définition d’un pod et modifier ces paramètres sans reconstruire l’image.

Dans le cas de scénarios extrêmement complexes, la configuration peut également être fournie en utilisant des volumes qui seraient montés dans le conteneur au moment de l’exécution. Cependant, si vous choisissez de le faire de cette façon, vous devez vous assurer que votre image fournit des messages d’erreur clairs au démarrage lorsque le volume ou la configuration nécessaire n’est pas présent.

Ce sujet est lié au sujet Utiliser les services pour la communication inter-images dans la mesure où la configuration comme les sources de données sont définies en termes de variables d’environnement qui fournissent des informations sur le point de terminaison du service. Cela permet à une application de consommer dynamiquement un service de datasource qui est défini dans le service Red Hat OpenShift sur l’environnement AWS sans modifier l’image de l’application.

En outre, le réglage se fait en inspectant les paramètres des groupes pour le conteneur. Cela permet à l’image de s’adapter à la mémoire, au CPU et à d’autres ressources disponibles. À titre d’exemple, les images basées sur Java règlent leur tas en fonction du paramètre de mémoire maximum de cgroup pour s’assurer qu’elles ne dépassent pas les limites et obtiennent une erreur hors mémoire.

4.1.2.6. Définir les métadonnées d’image

Définir les métadonnées d’image aide Red Hat OpenShift Service sur AWS à mieux consommer vos images conteneur, permettant à Red Hat OpenShift Service sur AWS de créer une meilleure expérience pour les développeurs utilisant votre image. À titre d’exemple, vous pouvez ajouter des métadonnées pour fournir des descriptions utiles de votre image ou proposer des suggestions sur d’autres images nécessaires.

4.1.2.7. Clustering

Il faut bien comprendre ce que signifie exécuter plusieurs instances de votre image. Dans le cas le plus simple, la fonction d’équilibrage de charge d’un service gère le routage du trafic vers toutes les instances de votre image. Cependant, de nombreux cadres doivent partager des informations pour effectuer l’élection des dirigeants ou l’état de basculement; par exemple, dans la réplication de session.

Considérez comment vos instances accomplissent cette communication lors de l’exécution dans Red Hat OpenShift Service sur AWS. Bien que les pods puissent communiquer directement les uns avec les autres, leurs adresses IP changent chaque fois que la gousse démarre, s’arrête ou est déplacée. Il est donc important que votre système de clustering soit dynamique.

4.1.2.8. L’exploitation forestière

Il est préférable d’envoyer toute la journalisation à la norme. Le service OpenShift Red Hat sur AWS recueille la norme à partir des conteneurs et l’envoie au service de journalisation centralisé où il peut être visualisé. Lorsque vous devez séparer le contenu du journal, préfixer la sortie avec un mot clé approprié, ce qui permet de filtrer les messages.

Lorsque votre image enregistre un fichier, les utilisateurs doivent utiliser des opérations manuelles pour entrer dans le conteneur en cours d’exécution et récupérer ou afficher le fichier journal.

4.1.2.9. Les sondes de vivacité et de préparation

Documentez des sondes de vivacité et de préparation qui peuvent être utilisées avec votre image. Ces sondes permettent aux utilisateurs de déployer votre image en toute confiance que le trafic n’est pas acheminé vers le conteneur jusqu’à ce qu’il soit prêt à la manipuler, et que le conteneur soit redémarré si le processus entre dans un état malsain.

4.1.2.10. Les modèles

Envisagez de fournir un modèle d’exemple avec votre image. Le modèle offre aux utilisateurs un moyen facile de déployer rapidement votre image avec une configuration de travail. Le modèle doit inclure les sondes de vivacité et de préparation que vous avez documentées avec l’image, pour l’exhaustivité.

Retour au début
Red Hat logoGithubredditYoutubeTwitter

Apprendre

Essayez, achetez et vendez

Communautés

À propos de la documentation Red Hat

Nous aidons les utilisateurs de Red Hat à innover et à atteindre leurs objectifs grâce à nos produits et services avec un contenu auquel ils peuvent faire confiance. Découvrez nos récentes mises à jour.

Rendre l’open source plus inclusif

Red Hat s'engage à remplacer le langage problématique dans notre code, notre documentation et nos propriétés Web. Pour plus de détails, consultez le Blog Red Hat.

À propos de Red Hat

Nous proposons des solutions renforcées qui facilitent le travail des entreprises sur plusieurs plates-formes et environnements, du centre de données central à la périphérie du réseau.

Theme

© 2025 Red Hat