web-dev-qa-db-fra.com

Construire des applications C ++ avec Docker: comment gérer la liaison dynamique?

J'ai un projet C++, cloné à partir de GitHub, que je voudrais construire avec une image Docker (une écurie Debian personnalisée). L'image contient les outils habituels de compilation des applications C++ ainsi que toutes les dépendances requises par le projet.

Mon flux de travail idéal serait:

  1. cd dans le répertoire du projet;
  2. invoquez Docker et laissez le conteneur configurer + créer l'application;
  3. exécutez l'exécutable dans le système hôte (c'est-à-dire pas dans le conteneur Docker).

Malheureusement, les liens exécutables contre certaines bibliothèques partagées, disponibles dans l'image Docker mais pas installés dans l'hôte. Je vois deux options ici:

  1. forcer une construction statique - délicat mais devrait faire le travail;
  2. installer les dépendances manquantes dans l'hôte - facile mais cela irait à l'encontre de l'objectif: garder le système propre de tout élément supplémentaire.

Quelle est une façon intelligente de surmonter cet obstacle? Existe-t-il des meilleures pratiques connues sur le sujet?

8
Ignorant

La gestion des dépendances et des bibliothèques dynamiques n'est pas un nouveau problème. Dans votre scénario, l'utilisation de Docker n'est pas liée à ce problème car vous utilisez uniquement Docker pour regrouper votre chaîne d'outils de génération (c'est-à-dire les compilateurs).

L'environnement dans lequel votre application est exécutée aura besoin de toutes les dépendances. Cependant, cela ne signifie pas que vous devez polluer le système hôte.

Par exemple, il peut être possible d'exécuter l'application dans un conteneur Docker qui fournit les dépendances. Cependant, cela ne convient souvent pas, car Docker préfère fortement les images immuables et peut imposer une isolation inappropriée.

Bien sûr, d'autres technologies de conteneurisation existent également. Cela peut être approprié si votre logiciel nécessite des services/démons spécialement configurés. Mais vous ne voudrez peut-être pas déployer via des conteneurs, par exemple car les utilisateurs devraient installer un logiciel de gestion de conteneurs, parce que les images peuvent nécessiter un stockage excessif, ou parce que le déploiement d'images de conteneurs rend difficile l'application des mises à jour de sécurité aux dépendances indépendamment de votre logiciel.

L'utilisation de liens statiques peut être une approche très pratique, lorsque cela est possible. Notez que cela peut ne pas fonctionner si les dépendances englobent non seulement les bibliothèques mais également d'autres ressources (polices, images, bases de données, services externes). Cela peut également affecter les licences logicielles, en particulier si vous avez des dépendances LGPL.

Il peut être pratique de déclarer toutes les dépendances et d'utiliser un système de gestion des dépendances externe tel que APT pour les résoudre. Cela peut être très convivial, mais peut également impliquer des dépendances que vous ne pouvez pas contrôler. Si une dépendance n'est pas fournie, vous pouvez l'empaqueter d'une manière qui installe sous /opt .

Il n'est pas nécessaire d'installer les dépendances globalement. Si vous configurez vos dépendances pour qu'elles s'installent sous un préfixe local (et définissez LD_LIBRARY_PATH convenablement), vous pouvez alors installer des dépendances dans votre répertoire de projet. Vous pouvez ensuite les déployer avec votre application. Surtout, cela vous permet de facilement plusieurs versions de vos dépendances côte à côte. La (ré) installation des dépendances devrait alors faire partie de votre processus de construction normal.

Ces stratégies ne sont pas exclusives mais peuvent être mélangées et assorties si nécessaire. Par exemple, exiger que libstdc ++ dans une version appropriée soit installée sur le système hôte peut être OK, mais vous voudrez peut-être lier d'autres dépendances statiquement. Ou si vous disposez d'un script de déploiement qui peut installer des dépendances localement, ce script peut également être utilisé dans le Dockerfile du conteneur de génération.

Au final, laquelle de ces variantes est préférable dépend de la façon dont votre logiciel sera installé et utilisé. Tout est potentiellement bien, tant que tout peut être scripté.

4
amon