{"id":12998,"date":"2017-05-03T08:19:49","date_gmt":"2017-05-03T15:19:49","guid":{"rendered":"\/blog\/?p=12998"},"modified":"2017-05-03T08:19:49","modified_gmt":"2017-05-03T15:19:49","slug":"comment-nous-avons-migre-plus-de-350-jobs-maven-en-pipeline-as-code-avec-jenkins-2-et-docker-part1-creer-ses-propres-images-docker-pour-jenkins","status":"publish","type":"post","link":"https:\/\/www.exoplatform.com\/blog\/fr\/comment-nous-avons-migre-plus-de-350-jobs-maven-en-pipeline-as-code-avec-jenkins-2-et-docker-part1-creer-ses-propres-images-docker-pour-jenkins\/","title":{"rendered":"Comment nous avons migr\u00e9 plus de 350 jobs Maven en Pipeline as code avec Jenkins 2 et Docker !"},"content":{"rendered":"<h2>Part1: Cr\u00e9er ses propres images Docker pour Jenkins<\/h2>\n<p>&nbsp;<\/p>\n<p>Il y a un an, chez eXo, nous avons pris la d\u00e9cision de construire tous nos projets dans des conteneurs Docker.<\/p>\n<p><!--more--><\/p>\n<p>Dans cette s\u00e9rie d&#8217;articles, nous vous expliquerons pourquoi et comment nous avons migr\u00e9 plus de 350 jobs Maven &#8220;standards&#8221; de Jenkins vers du <strong><a href=\"https:\/\/jenkins.io\/doc\/book\/pipeline-as-code\/\" target=\"_blank\" rel=\"noopener\">Pipeline as code<\/a> <\/strong>sur nos serveurs d&#8217;Int\u00e9gration Continue avec Jenkins 2 et Docker.<\/p>\n<p>C&#8217;est l\u2019occasion de revenir sur les probl\u00e8mes que nous avons rencontr\u00e9s ainsi que les solutions apport\u00e9es, et sur certaines bonnes pratiques autour des builds Maven \/ Gradle \/ Android dans des conteneurs Docker, le tout g\u00e9r\u00e9 par du Pipeline as Code de Jenkins.<\/p>\n<p>Comme toute migration technique importante, nous l&#8217;avons r\u00e9alis\u00e9e \u00e9tape par \u00e9tape. Les 3 grandes \u00e9tapes ont \u00e9t\u00e9 les suivantes:<\/p>\n<ul>\n<li style=\"font-weight: 400;\">Cr\u00e9er nos propres images CI Docker<\/li>\n<li style=\"font-weight: 400;\">Utiliser les plugins Jenkins Pipeline &amp; Pipeline Docker<\/li>\n<li style=\"font-weight: 400;\">G\u00e9n\u00e9rer tous les jobs Pipeline avec le Job DSL plugin<\/li>\n<\/ul>\n<p>Le diagramme suivant repr\u00e9sente le flux de travail lorsque toutes ces \u00e9tapes sont effectu\u00e9es:<\/p>\n<p><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins.png\"><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-13000 aligncenter\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins.png\" alt=\"Diagramme flux de travail avec \u00e9tapes effectu\u00e9es\" width=\"616\" height=\"340\" srcset=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins.png 853w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins-300x166.png 300w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins-768x424.png 768w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins-720x398.png 720w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins-500x276.png 500w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins-360x199.png 360w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins-200x110.png 200w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins-100x55.png 100w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Jenkins-54x30.png 54w\" sizes=\"(max-width: 616px) 100vw, 616px\" \/><\/a>Dans cet article, nous d\u00e9taillerons le contexte (pourquoi nous l&#8217;avons fait) et la premi\u00e8re \u00e9tape de cette migration sur la cr\u00e9ation de vos propres images CI Docker.<\/p>\n<h3>Qu\u2019avions-nous \u00e0 construire ?<\/h3>\n<p>eXo Platform est b\u00e2tie sur <strong>l\u2019<a href=\"https:\/\/www.exoplatform.com\/fr\/technologie\/?utm_source=BlogFr&amp;utm_medium=Blog&amp;utm_campaign=link\">open-source et les standards ouverts<\/a><\/strong>. La plateforme est compatible avec la pile Java EE et s\u2019appuie sur de nombreuses biblioth\u00e8ques et composants open-source.<\/p>\n<p><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-13001\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1.jpg\" alt=\"Mobile 1\" width=\"141\" height=\"268\" srcset=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1.jpg 500w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1-158x300.jpg 158w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1-249x473.jpg 249w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1-172x328.jpg 172w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1-124x236.jpg 124w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1-69x131.jpg 69w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1-47x90.jpg 47w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-1-16x30.jpg 16w\" sizes=\"(max-width: 141px) 100vw, 141px\" \/><\/a><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-13002\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2.png\" alt=\"Mobile 2\" width=\"133\" height=\"261\" srcset=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2.png 815w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-153x300.png 153w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-522x1024.png 522w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-768x1508.png 768w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-782x1536.png 782w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-241x473.png 241w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-167x328.png 167w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-120x236.png 120w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-67x131.png 67w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-46x90.png 46w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Mobile-2-15x30.png 15w\" sizes=\"(max-width: 133px) 100vw, 133px\" \/><\/a><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Desktop.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-13003\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Desktop.png\" alt=\"Desktop\" width=\"294\" height=\"179\" srcset=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Desktop.png 625w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Desktop-300x182.png 300w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Desktop-500x304.png 500w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Desktop-360x219.png 360w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Desktop-200x122.png 200w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Desktop-100x61.png 100w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Desktop-49x30.png 49w\" sizes=\"(max-width: 294px) 100vw, 294px\" \/><\/a><\/p>\n<p>Pour diff\u00e9rentes raisons que nous allons vous expliquer, nous avons \u00e0 g\u00e9rer un grand nombre de builds sur nos serveurs d\u2019Int\u00e9gration Continue .<\/p>\n<h4>Composants d\u2019eXo Platform et Add-ons<\/h4>\n<p>La premi\u00e8re raison est que nous avons des d\u00e9p\u00f4ts git pour chacun des composants requis dans les livrables des distributions d\u2019eXo Platform:<\/p>\n<ul>\n<li style=\"font-weight: 400;\">25+ composants \u00e0 construire\n<ul>\n<li style=\"font-weight: 400;\">projets pour la plateforme (cf. diagramme ci-dessous)<\/li>\n<li style=\"font-weight: 400;\">projets Juzu&#8230;<\/li>\n<\/ul>\n<\/li>\n<li style=\"font-weight: 400;\">De nombreux Add-ons\n<ul>\n<li style=\"font-weight: 400;\">15+ Add-ons support\u00e9s<\/li>\n<li style=\"font-weight: 400;\">100+ Add-ons communautaires<\/li>\n<\/ul>\n<\/li>\n<li style=\"font-weight: 400;\">Projets natifs pour le mobile\n<ul>\n<li style=\"font-weight: 400;\">application Android<\/li>\n<li style=\"font-weight: 400;\">application iOS<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Composants-d\u2019eXo-Platform-et-Add-ons.png\" class=\"broken_link\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-13004 aligncenter\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Composants-d\u2019eXo-Platform-et-Add-ons.png\" alt=\"Composants d\u2019eXo Platform et Add-ons\" width=\"558\" height=\"518\"><\/a>Git Workflow<\/h4>\n<p>Nous utilisons un <strong><a href=\"http:\/\/developer.exoplatform.org\/#id-git-workflow\" target=\"_blank\" rel=\"noopener\">workflow git <\/a><\/strong>bas\u00e9 sur un <strong>mod\u00e8le de branches que tous les projets eXo doivent suivre<\/strong>:<\/p>\n<ul>\n<li style=\"font-weight: 400;\"><strong>develop<\/strong> : branche qui contient les derniers d\u00e9veloppements valid\u00e9s<\/li>\n<li style=\"font-weight: 400;\"><strong>feature\/xxx<\/strong> : branches d\u00e9di\u00e9es aux nouvelles fonctionnalit\u00e9s majeures (de nombreux commits), &#8220;xxx&#8221; correspond au nom de la fonctionnalit\u00e9.<\/li>\n<li style=\"font-weight: 400;\"><strong>stable\/xxx<\/strong> : branches utilis\u00e9es pour faire des releases et pour corriger des probl\u00e8mes sur des versions stables. &#8220;xxx&#8221; correspond au num\u00e9ro de version stabilis\u00e9e (e.g 1.0.x).<\/li>\n<li style=\"font-weight: 400;\"><strong>fix\/xxx<\/strong> : branches d\u00e9di\u00e9es aux correctifs qui doivent \u00eatre ensuite int\u00e9gr\u00e9s dans la branche <strong>develop<\/strong>. Dans certains cas, ces corrections peuvent \u00eatre aussi appliqu\u00e9es sur la branche <strong>stable<\/strong>.<\/li>\n<li style=\"font-weight: 400;\"><strong>integration\/xxx<\/strong> : branches d\u00e9di\u00e9es aux processus automatiques (exemple: processus de traductions\u2026).<\/li>\n<li style=\"font-weight: 400;\"><strong>poc\/xxx<\/strong> : branches d\u00e9di\u00e9es \u00e0 la r\u00e9alisation de Proof of Concept (PoC)<\/li>\n<\/ul>\n<h4><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Workflow-git-mod\u00e8le-de-branches-pour-suivre-les-projets-eXo.png\" class=\"broken_link\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-13005 aligncenter\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Workflow-git-mod\u00e8le-de-branches-pour-suivre-les-projets-eXo.png\" alt=\"Workflow git, mod\u00e8le de branches pour suivre les projets eXo\" width=\"603\" height=\"615\"><\/a>Clients et versions d\u2019eXo Platform<\/h4>\n<p>Depuis pr\u00e8s de 15 ans maintenant, eXo a publi\u00e9 de nombreuses versions d\u2019eXo Platform. Avec eXo Platform 5 en cours de d\u00e9veloppement et les versions que nous devons maintenir pour nos clients (eXo Platform 4.x: 4.0, 4.1, 4.2, 4.3, 4.4), nous avons ainsi plusieurs versions de nos environnements de build \u00e0 g\u00e9rer.<br \/>\nActuellement, nous devons \u00eatre en mesure de construire des projets avec les versions JDK6, JDK7 ou JDK8 et Maven 3.0, Maven 3.2 ou Maven 3.3. L&#8217;application Android native est construite par Gradle.<\/p>\n<h4>Vous vous souvenez comment cr\u00e9er un job Maven dans l\u2019interface Jenkins ?<\/h4>\n<p>M\u00eame si Jenkins 2 a fait de nombreux efforts pour l&#8217;am\u00e9liorer, il est toujours contraignant de cr\u00e9er de nouveaux jobs Maven via l&#8217;interface utilisateur, comme vous pouvez le voir ci-dessous:<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/comment-cr\u00e9er-un-job-Maven-dans-l\u2019interface-Jenkins.png\" class=\"broken_link\"><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-13006 aligncenter\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/comment-cr\u00e9er-un-job-Maven-dans-l\u2019interface-Jenkins.png\" alt=\"comment cr\u00e9er un job Maven dans l\u2019interface Jenkins\" width=\"726\" height=\"414\"><\/a><\/p>\n<p style=\"text-align: center;\"><strong>\u201cJenkins DSL et jobs Pipeline dans Docker \u00e0 la rescousse !\u201d<\/strong><\/p>\n<p>Pour ces diff\u00e9rentes raisons, nous devions <strong>g\u00e9rer beaucoup de jobs Maven \u00e0 partir de l&#8217;interface utilisateur<\/strong> de Jenkins et <strong>maintenir nombre d\u2019outils dans plusieurs versions<\/strong> (Maven, JDK &#8230;) sur les agents Jenkins ainsi que sur les postes de d\u00e9veloppeurs. Ce travail n\u2019\u00e9tant ni int\u00e9ressant ni efficace, nous avons d\u00e9cid\u00e9 de trouver une solution pour l&#8217;automatiser et le g\u00e9rer diff\u00e9remment.<\/p>\n<p>La technologie bas\u00e9e <strong><a href=\"https:\/\/www.docker.com\/what-container\" target=\"_blank\" rel=\"noopener\">sur les conteneurs (Docker)<\/a><\/strong>, combin\u00e9e &nbsp;\u00e0 l&#8217;\u00e9mergence d&#8217;outils d&#8217;automatisation dans<strong><a href=\"https:\/\/jenkins.io\/doc\/book\/pipeline\/#why\" target=\"_blank\" rel=\"noopener\"> Jenkins avec Pipeline<\/a><\/strong> et l&#8217;efficacit\u00e9 du<strong><a href=\"https:\/\/jenkinsci.github.io\/job-dsl-plugin\/\" target=\"_blank\" rel=\"noopener\"> DSL Job plugin<\/a><\/strong>, nous a alors sembl\u00e9 \u00eatre la meilleure solution dans le contexte eXo.<\/p>\n<h3>1ere \u00e9tape: Cr\u00e9er ses propres images Docker<\/h3>\n<p>Il est important de respecter les bonnes pratiques g\u00e9n\u00e9rales lorsque l\u2019on cr\u00e9\u00e9 nos propres images Docker, mais \u00e9galement quelques sp\u00e9cificit\u00e9s propres aux environnements de build.<\/p>\n<h4><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Cr\u00e9ation-de-nos-propres-images-Docker.png\" class=\"broken_link\"><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-13007 aligncenter\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Cr\u00e9ation-de-nos-propres-images-Docker.png\" alt=\"Cr\u00e9ation de nos propres images Docker\" width=\"636\" height=\"571\"><\/a>Choisir une image de base pour la distribution<\/h4>\n<p>Tous nos serveurs qui font office d\u2019agents Jenkins sont g\u00e9r\u00e9s \u00e0 partir de Puppet et sont bas\u00e9s sur la distribution Ubuntu. Nous avons donc d\u00e9cid\u00e9 d&#8217;utiliser une image Docker plus l\u00e9g\u00e8re bas\u00e9e sur cette distribution nomm\u00e9e <strong><a href=\"http:\/\/phusion.github.io\/baseimage-docker\/\" target=\"_blank\" rel=\"noopener\">baseimage-docker<\/a><\/strong>.<\/p>\n<p>C&#8217;\u00e9tait un bon compromis entre une image tr\u00e8s l\u00e9g\u00e8re comme Alpine qui avait des probl\u00e8mes li\u00e9s \u00e0 l&#8217;installation de JDK et l&#8217;image Docker officielle d\u2019Ubuntu trop volumineuse.<\/p>\n<p>FROM &nbsp;phusion\/baseimage:0.9.21<br \/>\nLABEL MAINTAINER &#8220;eXo Platform &lt;docker@exoplatform.com&gt;&#8221;<\/p>\n<h4>D\u00e9finir la locale<\/h4>\n<p>Qui n&#8217;a jamais eu de tests en \u00e9chec en raison de probl\u00e8mes d&#8217;encodage ? <i>Les tests passent &nbsp;sur mon poste Linux, mais ils \u00e9chouent sur le portable de mon coll\u00e8gue sous Windows !<\/i><\/p>\n<p>Il est tr\u00e8s fortement recommand\u00e9 de d\u00e9finir une locale pour s&#8217;assurer que tous les d\u00e9veloppeurs auront le m\u00eame comportement quel que soit leur environnement et que ce comportement sera conforme \u00e0 la configuration du serveur d\u2019Int\u00e9gration Continue.<\/p>\n<pre class=\"lang:default decode:true\"># Set the locale\nRUN locale-gen en_US.UTF-8\nENV LANG en_US.UTF-8\nENV LANGUAGE en_US:en\nENV LC_ALL en_US.UTF-8\n<\/pre>\n<h4>Cr\u00e9er un utilisateur CI d\u00e9di\u00e9<\/h4>\n<p>\u201c&#8230;<i>take care of running your processes inside the containers as non-privileged users (i.e., non-root).<\/i>\u201d est l&#8217;une des recommandations les plus importantes<strong> <a href=\"https:\/\/docs.docker.com\/engine\/security\/security\/\" target=\"_blank\" rel=\"noopener\">du guide de s\u00e9curit\u00e9 Docker<\/a>.<\/strong><\/p>\n<p>Dans le contexte de Jenkins, il est important de cr\u00e9er un <strong>utilisateur de CI d\u00e9di\u00e9 qui correspond \u00e0 l&#8217;<\/strong><strong><i>uid:gid<\/i><\/strong><strong> de l&#8217;utilisateur utilis\u00e9 par Jenkins sur vos agents<\/strong>.<\/p>\n<pre class=\"lang:default decode:true\"># eXo CI User\nARG EXO_CI_USER_UID=13000\nENV EXO_CI_USER ciagent\nENV EXO_GROUP ciagent\n...\n# Create user and group with specific ids\nRUN useradd --create-home --user-group -u ${EXO_CI_USER_UID} --shell \/bin\/bash ${EXO_CI_USER}<\/pre>\n<p>En effet, lorsque Jenkins ex\u00e9cute un job Pipeline avec Docker, il partage l&#8217;espace de travail du job ainsi que d&#8217;autres dossiers requis dans le conteneur Docker.<\/p>\n<p>Par exemple, Jenkins ex\u00e9cute la commande suivante sur l&#8217;agent:<\/p>\n<pre class=\"lang:default decode:true\">$ docker run -t -d -u 13000:13000\n-v m2-cache-ecms-develop-ci:\/home\/ciagent\/.m2\/repository\n-v \/srv\/ciagent\/workspace\/ecms-develop-ci:\/srv\/ciagent\/workspace\/ecms-develop-ci:rw\n-v \/srv\/ciagent\/workspace\/ecms-develop-ci@tmp:\/srv\/ciagent\/workspace\/ecms-develop-ci@tmp:rw\n... &nbsp;-e ******** --entrypoint cat exoplatform\/ci:jdk8-maven33\n<\/pre>\n<p>La cr\u00e9ation d\u2019un utilisateur CI d\u00e9di\u00e9 vous<strong> \u00e9vite ainsi les probl\u00e8mes d&#8217;autorisations avec les volumes Docker<\/strong>.<\/p>\n<p>Vous pouvez constater que nous d\u00e9finissons la variable <strong><i>EXO_CI_USER_UID<\/i><\/strong> avec l&#8217;instruction Docker <strong><i>ARG<\/i><\/strong>, elle aura son importance pour aider le d\u00e9veloppeur dans son environnement de de d\u00e9veloppement local et nous expliquerons pourquoi plus loin dans cette s\u00e9rie d&#8217;articles.<\/p>\n<h4>ENTRYPOINT et CMD<\/h4>\n<p>Dans un Dockerfile, l&#8217;instruction ENTRYPOINT est une d\u00e9finition facultative pour la premi\u00e8re partie de la commande \u00e0 ex\u00e9cuter. Ainsi, les instructions <strong><a href=\"https:\/\/www.ctl.io\/developers\/blog\/post\/dockerfile-entrypoint-vs-cmd\/\" class=\"broken_link\" target=\"_blank\" rel=\"noopener\">ENTRYPOINT ou CMD<\/a><\/strong>, sp\u00e9cifi\u00e9es dans votre Dockerfile, identifient l&#8217;ex\u00e9cutable par d\u00e9faut pour l&#8217;image Docker. Mais la meilleure solution est de combiner ces deux instructions en utilisant CMD pour fournir des arguments par d\u00e9faut pour le ENTRYPOINT.<\/p>\n<p>Dans les versions ant\u00e9rieures du plugin Jenkins Docker Pipeline, Jenkins n\u2019utilisait pas l&#8217;option <strong><i>&#8211;entrypoint<\/i><\/strong> lors du d\u00e9marrage des conteneurs, la commande ex\u00e9cut\u00e9e \u00e9tait alors:<\/p>\n<pre class=\"lang:default decode:true\">$ docker run ... -e ******** exoplatform\/ci:jdk8-maven33 cat<\/pre>\n<p>&nbsp;<\/p>\n<p>Dans ce cas, si votre image Docker utilisait l\u2019instruction ENTRYPOINT pour d\u00e9clarer une commande \u00e0 ex\u00e9cuter, Jenkins ne pouvait pas utiliser votre image.<\/p>\n<p>C&#8217;est pourquoi nous avons ajout\u00e9 un script personnalis\u00e9 dans nos images Docker, comme solution de contournement, afin de pouvoir ex\u00e9cuter Maven comme commande au d\u00e9marrage du conteneur, mais \u00e9galement la commande <i>cat<\/i> et d&#8217;autres commandes \u00e0 partir du moment o\u00f9 elles sont appel\u00e9es via un chemin absolu:<\/p>\n<p><i>Dockerfile<\/i><\/p>\n<pre class=\"lang:default decode:true \">COPY docker-entrypoint.sh \/usr\/bin\/docker-entrypoint\n# Workaround to be able to execute others command than \"mvn\" as entrypoint\nENTRYPOINT [\"\/usr\/bin\/docker-entrypoint\"]\n\nCMD [\"mvn\", \"--help\"]<\/pre>\n<p><i>docker-entrypoint.sh<\/i><\/p>\n<pre class=\"lang:default decode:true \"># Hack for Jenkins Pipeline: authorize cat without absolute path\nif [[ \"$1\" == \"\/\"* ]] || [[ \"$1\" == \"cat\" ]]; then\nexec \"$@\"\nfi\n\nexec mvn \"$@\"<\/pre>\n<p>Depuis plusieurs versions du plugin <strong><a href=\"https:\/\/jenkins.io\/doc\/pipeline\/steps\/docker-workflow\/\" target=\"_blank\" rel=\"noopener\">Jenkins Docker Pipeline<\/a><\/strong>, ce probl\u00e8me a \u00e9t\u00e9 corrig\u00e9 pour utiliser l&#8217;option <i>&#8211;entrypoint<\/i> afin que l&#8217;instruction ENTRYPOINT soit toujours surcharg\u00e9e:<\/p>\n<pre class=\"lang:default decode:true\">$ docker run ... -e ******** --entrypoint cat exoplatform\/ci:jdk8-maven33<\/pre>\n<h4>Utiliser l\u2019h\u00e9ritage pour \u00e9viter la duplication de code<\/h4>\n<p>Nous avons cr\u00e9\u00e9 et continuons \u00e0 cr\u00e9er des images Docker pour couvrir toutes nos environnements de build, aujourd\u2019hui cette liste contient notamment :<\/p>\n<ul>\n<li style=\"font-weight: 400;\">exoplatform\/ci:jdk6-maven30<\/li>\n<li style=\"font-weight: 400;\">exoplatform\/ci:jdk7-maven30<\/li>\n<li style=\"font-weight: 400;\">exoplatform\/ci:jdk7-maven32<\/li>\n<li style=\"font-weight: 400;\">exoplatform\/ci:jdk8-maven32<\/li>\n<li style=\"font-weight: 400;\">exoplatform\/ci:jdk8-maven33<\/li>\n<li style=\"font-weight: 400;\">exoplatform\/ci:jdk8-gradle2<\/li>\n<li style=\"font-weight: 400;\">\u2026<\/li>\n<\/ul>\n<p>Comme vous pouvez l&#8217;imaginer, il n&#8217;y a pas beaucoup de diff\u00e9rences entre toutes ces images. Nous avons donc cr\u00e9\u00e9 des images de base CI \u00e0 plusieurs niveaux afin d&#8217;\u00e9viter autant que possible la duplication du code.<\/p>\n<p>Le sch\u00e9ma ci-dessous montre comment ces images sont organis\u00e9es :<\/p>\n<p><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Image-de-base-CI-sur-docker-avec-h\u00e9ritage-pour-\u00e9viter-la-duplication-de-code.png\" class=\"broken_link\"><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-13008 aligncenter\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Image-de-base-CI-sur-docker-avec-h\u00e9ritage-pour-\u00e9viter-la-duplication-de-code.png\" alt=\"Image de base CI sur docker avec h\u00e9ritage pour \u00e9viter la duplication de code\" width=\"631\" height=\"474\"><\/a>Ci-dessous, il s&#8217;agit d&#8217;un extrait du Dockerfile pour l&#8217;image <strong><i>exoplatform\/ci:jdk8-maven33<\/i><\/strong> et vous pouvez voir qu&#8217;il n&#8217;y a que des instructions Docker li\u00e9es \u00e0 l&#8217;installation Maven car toutes les autres configurations ont \u00e9t\u00e9 effectu\u00e9es dans les images h\u00e9rit\u00e9es (d\u00e9finir les param\u00e8tres r\u00e9gionaux, cr\u00e9er un utilisateur CI &#8230;).<\/p>\n<pre class=\"lang:default decode:true\">FROM exoplatform\/ci:jdk8\n\n# CI Tools version\nENV MAVEN_VERSION 3.3.9\n# Install Maven\nRUN mkdir -p \/usr\/share\/maven \\\n&amp;&amp; curl -fsSL http:\/\/archive.apache.org\/dist\/maven\/maven-3\/$MAVEN_VERSION\/binaries\/apache-maven-$MAVEN_VERSION-bin.tar.gz \\\n| tar xzf - -C \/usr\/share\/maven --strip-components=1 &nbsp;\\\n&amp;&amp; ln -s \/usr\/share\/maven\/bin\/mvn \/usr\/bin\/mvn\n\n\u2026\n\n# Custom configuration for Maven\nENV M2_HOME=\/usr\/share\/maven\nENV MAVEN_OPTS=\"-Dmaven.repo.local=${HOME}\/.m2\/repository -XX:+UseConcMarkSweepGC -Xms1G -Xmx2G -XX:MaxMetaspaceSize=1G -Dcom.sun.media.jai.disableMediaLib=true -Djava.io.tmpdir=${EXO_CI_TMP_DIR} -Dmaven.artifact.threads=10 -Djava.awt.headless=true\"\nENV PATH=$JAVA_HOME\/bin:$M2_HOME\/bin:$PATH\n\n...\n\n# Workaround to be able to execute others command than \"mvn\" as entrypoint\nENTRYPOINT [\"\/usr\/bin\/docker-entrypoint\"]\n\nCMD [\"mvn\", \"--help\"]<\/pre>\n<p>Comme expliqu\u00e9 pr\u00e9c\u00e9demment dans cet article, nous avons combin\u00e9 les instructions Docker ENTRYPOINT et CMD pour pouvoir ex\u00e9cuter toutes les commandes Maven dans ce conteneur facilement:<\/p>\n<pre class=\"lang:default decode:true\">docker run ... -e ******** exoplatform\/ci:jdk8-maven33 clean package<\/pre>\n<p>Et nous ajoutons \u00e9galement un script personnalis\u00e9, pour pouvoir ex\u00e9cuter la commande cat et d&#8217;autres commandes que Maven en donnant le chemin d\u2019acc\u00e8s absolu \u00e0 la commande:<\/p>\n<pre class=\"lang:default decode:true\">docker run exoplatform\/ci:jdk8-maven33 \/bin\/echo hello<\/pre>\n<p>Enfin, vous avez peut-\u00eatre remarqu\u00e9 que nous avons d\u00e9clar\u00e9 les variables d&#8217;environnement <strong>M2_REPO<\/strong> et <strong>MAVEN_OPTS<\/strong> sous forme d\u2019instructions Docker<strong> ENV<\/strong> avec des valeurs par d\u00e9faut pour tous les param\u00e8tres importants. Elles peuvent \u00eatre surcharg\u00e9es via l&#8217;option <i>-e<\/i> dans la commande de d\u00e9marrage de docker.<\/p>\n<h4>Tester ses Images Docker<\/h4>\n<p>Comme pour tout autre type de code source, il est possible de cr\u00e9er des suites de tests pour ses images Docker et Dockerfiles. Pour les images Docker eXo CI, nous utilisons <strong><a href=\"https:\/\/github.com\/aelsabbahy\/goss\" target=\"_blank\" rel=\"noopener\">Goss<\/a><\/strong> \u00e0 travers son wrapper <strong><a href=\"https:\/\/github.com\/aelsabbahy\/goss\/tree\/master\/extras\/dgoss\" target=\"_blank\" rel=\"noopener\">dgoss<\/a><\/strong>.<\/p>\n<ul>\n<li style=\"font-weight: 400;\"><strong>Goss<\/strong> est un outil, bas\u00e9 sur YAML, pour valider la configuration d&#8217;un serveur<\/li>\n<li style=\"font-weight: 400;\"><strong>dgoss<\/strong> est une enveloppe autour de Goss qui vise \u00e0 apporter la simplicit\u00e9 de Goss aux conteneurs Docker.<\/li>\n<\/ul>\n<p>La premi\u00e8re \u00e9tape consiste \u00e0 cr\u00e9er un fichier YAML pour d\u00e9crire ce que vous souhaitez tester dans votre conteneur Docker. Il existe <strong><a href=\"https:\/\/github.com\/aelsabbahy\/dgoss-examples\" target=\"_blank\" rel=\"noopener\">des exemples en ligne<\/a> <\/strong>qui peuvent aider \u00e0 cr\u00e9er ce fichier de configuration, mais cela peut \u00e9galement \u00eatre g\u00e9n\u00e9r\u00e9 par la ligne de commande de goss.<\/p>\n<p>Par exemple, nous voulons v\u00e9rifier que certains fichiers de configuration Maven existent dans le conteneur. Nous voulons \u00e9galement \u00eatre s\u00fbr que la commande <strong><i>mvn &#8211;version<\/i><\/strong> est conforme aux versions Maven et JDK install\u00e9es dans le container.<\/p>\n<p><i>goss.yaml<\/i><\/p>\n<pre class=\"lang:default decode:true\">file:\n\/home\/ciagent\/.m2\/repository:\ntitle: Validating the presence Maven repository folder\nexists: true\n\/home\/ciagent\/.m2\/settings.xml:\ntitle: Validating the absence of eXo USER settings file\nexists: false\n\/usr\/share\/maven\/conf\/settings.xml:\ntitle: Validating the presence of eXo GLOBAL settings file\nexists: true\npackage:\ngit:\ninstalled: true\ntitle: Check that git is installed\ncommand:\nmvn --version:\nexit-status: 0\nstdout:\n- 3.3.9\n- 1.8.0\n- \"Default locale: en_US, platform encoding: UTF-8\"\nstderr: []\ntimeout: 0<\/pre>\n<p>Ensuite, pour ex\u00e9cuter ces tests, il suffit simplement d&#8217;ex\u00e9cuter une ligne de commande via &nbsp;<strong>dgoss<\/strong>:<\/p>\n<pre class=\"lang:default decode:true \">dgoss run -it exoplatform\/ci:jdk8-maven33 cat<\/pre>\n<p>&nbsp;<\/p>\n<h3><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code.png\"><img decoding=\"async\" loading=\"lazy\" class=\" wp-image-13009 aligncenter\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code.png\" alt=\"Code\" width=\"717\" height=\"549\" srcset=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code.png 871w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code-300x230.png 300w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code-768x588.png 768w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code-618x473.png 618w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code-428x328.png 428w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code-308x236.png 308w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code-171x131.png 171w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code-100x77.png 100w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2017\/05\/Code-39x30.png 39w\" sizes=\"(max-width: 717px) 100vw, 717px\" \/><\/a>Conclusion<\/h3>\n<p>Si vous \u00eates int\u00e9ress\u00e9s pour tester ou utiliser ces images Docker:<\/p>\n<ul>\n<li style=\"font-weight: 400;\">tous les <strong>Dockerfiles<\/strong> sont disponibles dans le projet GitHub d\u00e9di\u00e9 <strong><a href=\"https:\/\/github.com\/exo-docker\/exo-ci\/\" target=\"_blank\" rel=\"noopener\">exo-docker\/exo-ci<\/a><\/strong><\/li>\n<li style=\"font-weight: 400;\">les<strong> images Docker<\/strong> peuvent \u00eatre t\u00e9l\u00e9charg\u00e9es \u00e0 partir de<strong> <a href=\"https:\/\/hub.docker.com\/r\/exoplatform\/ci\/\" target=\"_blank\" rel=\"noopener\">l\u2019organisation eXo sur le DockerHub<\/a><\/strong><\/li>\n<\/ul>\n<p>N&#8217;h\u00e9sitez pas \u00e0 nous faire part de vos commentaires ou \u00e0 proposer vos id\u00e9es.<\/p>\n<h3>Prochaine \u00e9tape<\/h3>\n<p>Maintenant que nous avons cr\u00e9\u00e9 nos propres Images Docker pour toutes nos environnements de build de l&#8217;int\u00e9gration continue, nous vous expliquerons dans le prochain article (Partie 2), comment utiliser ces images dans un environnement de d\u00e9veloppement local quel que soit votre syst\u00e8me d&#8217;exploitation.<br \/>\n<strong><a href=\"https:\/\/www.exoplatform.com\/fr\/?utm_source=BlogFr&amp;utm_medium=Blog&amp;utm_campaign=link\" target=\"_blank\" rel=\"noopener\">D\u00e9couvrez comment eXo Platform peut vous aider \u00e0 transformer votre entreprise!<\/a><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"Part1: Cr\u00e9er ses propres images Docker pour Jenkins &nbsp; Il y a un an, chez eXo, nous avons pris la d\u00e9cision de construire tous nos projets dans des conteneurs Docker.","protected":false},"author":69,"featured_media":13012,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"image","meta":[],"categories":[],"tags":[606,850],"lang":"fr","translations":{"fr":12998},"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/posts\/12998"}],"collection":[{"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/users\/69"}],"replies":[{"embeddable":true,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/comments?post=12998"}],"version-history":[{"count":0,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/posts\/12998\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/media\/13012"}],"wp:attachment":[{"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/media?parent=12998"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/categories?post=12998"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/tags?post=12998"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}