{"id":356,"date":"2021-04-04T13:23:36","date_gmt":"2021-04-04T11:23:36","guid":{"rendered":"https:\/\/nissel.it\/?p=356"},"modified":"2021-04-04T13:28:24","modified_gmt":"2021-04-04T11:28:24","slug":"gitlab-jenkins-buildpipeline-maven-java-docker-umgebung-fuer-entwickler","status":"publish","type":"post","link":"https:\/\/nissel.it\/index.php\/2021\/04\/04\/gitlab-jenkins-buildpipeline-maven-java-docker-umgebung-fuer-entwickler\/","title":{"rendered":"Gitlab + Jenkins + buildpipeline + Maven + Java Docker Umgebung f\u00fcr Entwickler"},"content":{"rendered":"\n<p>Ich m\u00f6chte lokal einen Buildserver einrichten um Features zu testen und einen Buildprozess zu entwickeln. Basieren soll dies alles auf docker bzw. docker-compose unter Linux und Windows. Nach der Installation sollen fertige Beispielprojekte eingerichtet sein. Das Versionsverwaltungssystem soll gitlab sein. Dies ist etwas aufwendig nur f\u00fcr einen git Server, aber ich wollte sowieso mit gitlab spielen. Der Buildserver wird Jenkins. Das erste Projekt soll ein buildpipeline Projekt sein, was per maven einen Java 16 Projekt mit einem Junit5 Testfall ausf\u00fchrt. Im Laufe der Zeit sollen weitere Beispiele dazu kommen.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Einrichtung Gitlab<\/h2>\n\n\n\n<p>Ziel ist es gitlab fertig eingerichtet mit einem Beispielprojekt zu starten. Unter Windows muss ber\u00fccksichtigt werden, dass Verzeichnisse mit voller Berechtigung in den docker container gemountet werden. Bei der Installation der ssh keys gibt es dann aber einen Fehler da die Berechtigungen zu gro\u00dfz\u00fcgig sind. Deswegen darf unter Windows \/var\/opt\/gitlab nicht direkt auf ein Verzeichnis gemountet werden. Unter Linux ist das nat\u00fcrlich m\u00f6glich.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    volumes:\n      - git-volume:\/var\/opt\/gitlab\n  ...\nvolumes:\n  git-volume:<\/code><\/pre>\n\n\n\n<p>Das initiale Passwort kann \u00fcber eine Umgebungsvariable gesetzt werden<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> environment:\n      GITLAB_OMNIBUS_CONFIG: |\n        gitlab_rails&#91;'initial_root_password'] = \"password\";<\/code><\/pre>\n\n\n\n<p>Zusammen ergibt das eine docker-compose.yml Datei mit folgenden Inhalt:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>version: \"3.3\"\n\nservices:\n   gitlab:\n    image: 'gitlab\/gitlab-ce:13.8.5-ce.0'\n    container_name: gitlab\n    environment:\n      GITLAB_OMNIBUS_CONFIG: |\n        external_url 'http:\/\/localhost';\n        gitlab_rails&#91;'initial_root_password'] = \"password\";\n    ports:\n      - '80:80'\n      - '443:443'\n      - '22:22'\n    volumes:\n      - .\/data\/gitlab\/config:\/etc\/gitlab\n      - .\/data\/gitlab\/logs:\/var\/log\/gitlab\n      - git-volume:\/var\/opt\/gitlab\nvolumes:\n  git-volume:<\/code><\/pre>\n\n\n\n<p>Damit wird ein gitlab gestartet und hat bereits ein initiales Passwort gesetzt. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Beispielprojekt in git anlegen<\/h2>\n\n\n\n<p>Nun ist aber noch kein Beispielprojekt erstellt. Dies habe ich in einem eigenen Docker Container umgesetzt. Dieser wird gestartet und wartet darauf, dass der git Container \u00fcber http erreichbar ist und erstellt falls noch nicht vorhanden ein git Projekt. Dazu wird ein dockerfile erstellt in dem der git client und wget installiert wird.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FROM ubuntu:20.04\n\nRUN apt update\nRUN apt install -y git wget<\/code><\/pre>\n\n\n\n<p>Da gitlab ohne ssh keys eingerichtet ist m\u00fcssen Benutzername und Passwort in eine credentials Datei gespeichert. Diese wird beim ausf\u00fchren des Containers gef\u00fcllt.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RUN git config --global credential.helper 'store --file \/work\/.git-credentials'<\/code><\/pre>\n\n\n\n<p>Im Container sind drei Skripte enthalten. start.sh, wait-for-git.sh und create-project.sh<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Skript start.sh<\/h3>\n\n\n\n<p>\u00dcberpr\u00fcft alle Umgebungsvariablen und erstellt f\u00fcr jeden Ordner in files\/projects\/ (im Container \/git\/) ein git Projekt. Dieser Ordner k\u00f6nnte auch als Volume eingebunden werden um beliebige Projekte zu erstellen. Hier werden aber die Projekte mit dem Image mitgeliefert.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for project in *; do\n  echo \"Create git project ${project} on ${HOSTNAME} if needed\"\n  PATH_TO_PROJECT=\"${GIT_PROJECT_DIR}\/${project}\"\n  \/usr\/bin\/wait-for-git.sh ${HOSTNAME} ${GIT_USER} ${project} &amp;&amp; echo \"Project ${project} already created\" || \/usr\/bin\/create-project.sh ${HOSTNAME} ${GIT_USER} ${project} ${PATH_TO_PROJECT}\ndone<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Skript wait-for-git.sh<\/h3>\n\n\n\n<p>Wartet bis der gitserver \u00fcber http erreichbar ist und keinen Fehler meldet. Danach wird gepr\u00fcft ob das Projekt bereits existiert. Wenn ja wird 0 zur\u00fcck gegeben. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>until wget --quiet http:\/\/${HOSTNAME} -O \/dev\/null\ndo\n  echo \"git server http:\/\/${HOSTNAME} is not online\"\n  sleep 5\ndone\n\ngit ls-remote http:\/\/${HOSTNAME}\/${GIT_PATH}\/${PROJECT}.git master > \/dev\/null 2>&amp;1<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Skript create-project.sh<\/h3>\n\n\n\n<p>Initialisiert ein git Projekt, erstellt eine Readme.md und commited und pushed ein Projekt zum git server.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git init\necho \"${PROJECT}\" > Readme.md\ngit add *\ngit commit -m \"initial commit\"\ngit push --set-upstream http:\/\/${HOSTNAME}\/${GIT_PATH}\/${PROJECT}.git master<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Aufruf in docker-compose.yml<\/h3>\n\n\n\n<p>Der Container kann einfach als Service mit aufgenommen werden:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>create-git-examples:\n    build: \n      context: .\/git-example-projects\n    container_name: git-example-projects\n    environment: \n      GIT_HOST: gitlab\n      GIT_USER: root\n      GIT_PASSWORD: password<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Jenkins einrichten<\/h2>\n\n\n\n<p>Aufgabe ist es automatisch die ben\u00f6tigten Plugins, Jenkins Konfiguration und Jobs zu erstellen. Dazu habe ich einen eigenes Docker image erstellt welches vom offiziellen jenkins image erbt. F\u00fcr die Installation von Plugins  kann das Kommandozeilen Programm jenkins-plugin-cli verwendet werden. Die Konfiguration von Jenkins \u00fcbernimmt das Plugin configuration-as-code welches dann \u00fcber eine .yml Datei gesteuert werden kann. Die Jobs sind einfach nur die config.xml Dateien die in der Ordner \/usr\/share\/jenkins\/ref\/jobs\/ kopiert werden und beim initialisieren automatisch erstellt werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FROM jenkins\/jenkins:lts\n\nRUN jenkins-plugin-cli --plugins configuration-as-code:1.47 role-strategy:3.1 workflow-aggregator:2.6 git:4.7.0 pipeline-maven docker-build-publish:1.3.3 adoptopenjdk:1.3\n\nCOPY .\/files\/jenkins.yml \/usr\/share\/jenkins\/ref\/config_as_code\/jenkins.yml\nENV CASC_JENKINS_CONFIG \/usr\/share\/jenkins\/ref\/config_as_code\/jenkins.yml\n\nCOPY .\/files\/jobs\/ \/usr\/share\/jenkins\/ref\/jobs\/<\/code><\/pre>\n\n\n\n<p>Die jenkins Konfiguration kann manuell \u00fcber die Oberfl\u00e4che durchgef\u00fchrt werden und danach kann man sich das Ergebnis als .yml Datei anschauen:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"725\" height=\"330\" src=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/manage-jenkins-configure-as-code.png\" alt=\"\" class=\"wp-image-360\" srcset=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/manage-jenkins-configure-as-code.png 725w, https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/manage-jenkins-configure-as-code-300x137.png 300w\" sizes=\"auto, (max-width: 725px) 100vw, 725px\" \/><figcaption>Configuration as Code Plugin aufrufen<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"510\" height=\"432\" src=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/configure-as-code-view-config.png\" alt=\"\" class=\"wp-image-361\" srcset=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/configure-as-code-view-config.png 510w, https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/configure-as-code-view-config-300x254.png 300w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><figcaption>Konfiguration anzeigen.<\/figcaption><\/figure>\n\n\n\n<p>Damit Jenkins den Installations-Assistenten starten muss noch eine Umgebungsvariabe gesetzt werden. Je nach Projekten sollte der Jenkins auch mit ausreichend Ram gestartet werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>environment:\n      JAVA_OPTS: -Djenkins.install.runSetupWizard=false -Xmx8192m<\/code><\/pre>\n\n\n\n<p>Die Vollst\u00e4ndige Service Definition sieht dann wie Folgend aus.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>jenkins:\n    container_name: jenkins\n    environment:\n      JAVA_OPTS: -Djenkins.install.runSetupWizard=false -Xmx8192m\n    ports:\n     - 8080:8080\n     - 50000:50000\n    volumes:\n     - .\/data\/jenkins:\/var\/jenkins_home\n    build:\n      context: .\/jenkins\n    depends_on:\n      - gitlab<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Starten der Umgebung<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code># Alles starten\ndocker-compose up\n# Alles im Hindergrund starten\ndocker-compose up -d\n# Dockerfiles neu bauen und starten\ndocker-compose up --build\n# Imges bauen und einzeln starten\ndocker-compose up --build gitlab\ndocker-compose up --build jenkins\ndocker-compose up --build create-git-examples<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Beispielprojekt mit Java16 und Build Pipeline<\/h2>\n\n\n\n<p>Das Beispielprojekt besteht aus einem einfachen Jenkinsfile und einer Klasse und die dazugeh\u00f6rige Testklasse.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pipeline {\n    agent any\n    tools {\n        maven 'maven-3.6.3'\n        jdk 'jdk16'\n    }\n    stages {\n        stage ('Build') {\n            steps {\n                sh 'mvn -Dmaven.test.failure.ignore=true install' \n            }\n            post {\n                success {\n                    junit 'target\/surefire-reports\/**\/*.xml' \n                }\n            }\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<p>Die &#8222;Tools&#8220; wurden vorher in der Jenkins Konfiguration erstellt:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tool:\n  git:\n    installations:\n    - home: \"git\"\n      name: \"Default\"\n  jdk:\n    installations:\n    - name: \"jdk16\"\n      properties:\n      - installSource:\n          installers:\n          - adoptOpenJdkInstaller:\n              id: \"jdk-16+36\"<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1014\" height=\"663\" src=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/pipeline.png\" alt=\"\" class=\"wp-image-364\" srcset=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/pipeline.png 1014w, https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/pipeline-300x196.png 300w, https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/pipeline-768x502.png 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption>Fertig ausgef\u00fchrter Job<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Gesamtes Projekt<\/h2>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/jenkins-env-1.zip\">jenkins-env-1<\/a><a href=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/jenkins-env-1.zip\" class=\"wp-block-file__button\" download>Herunterladen<\/a><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Links<\/h2>\n\n\n\n<p><a href=\"https:\/\/stackoverflow.com\/questions\/60229016\/one-line-console-command-to-set-first-root-password-in-gitlab\">https:\/\/stackoverflow.com\/questions\/60229016\/one-line-console-command-to-set-first-root-password-in-gitlab<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/docs.tibco.com\/pub\/mash-local\/4.1.1\/doc\/html\/docker\/GUID-BD850566-5B79-4915-987E-430FC38DAAE4.html\">https:\/\/docs.tibco.com\/pub\/mash-local\/4.1.1\/doc\/html\/docker\/GUID-BD850566-5B79-4915-987E-430FC38DAAE4.html<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/git-scm.com\/docs\/git-credential-store\">https:\/\/git-scm.com\/docs\/git-credential-store<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/ufoscout\/docker-compose-wait\">https:\/\/github.com\/ufoscout\/docker-compose-wait<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/www.praqma.com\/stories\/start-jenkins-config-as-code\/\">https:\/\/www.praqma.com\/stories\/start-jenkins-config-as-code\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/www.jenkins.io\/blog\/2017\/02\/07\/declarative-maven-project\/\">https:\/\/www.jenkins.io\/blog\/2017\/02\/07\/declarative-maven-project\/<\/a><\/p>\n\n\n\n<p><a href=\"http:\/\/www.thinkcode.se\/blog\/2019\/12\/23\/jenkins-configuration-as-code\">http:\/\/www.thinkcode.se\/blog\/2019\/12\/23\/jenkins-configuration-as-code<\/a><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ich m\u00f6chte lokal einen Buildserver einrichten um Features zu testen und einen Buildprozess zu entwickeln. Basieren soll dies alles auf docker bzw. docker-compose unter Linux und Windows. Nach der Installation sollen fertige Beispielprojekte eingerichtet sein. Das Versionsverwaltungssystem soll gitlab sein. Dies ist etwas aufwendig nur f\u00fcr einen git Server, aber ich wollte sowieso mit gitlab &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/nissel.it\/index.php\/2021\/04\/04\/gitlab-jenkins-buildpipeline-maven-java-docker-umgebung-fuer-entwickler\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eGitlab + Jenkins + buildpipeline + Maven + Java Docker Umgebung f\u00fcr Entwickler\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[13,18,16,17],"class_list":["post-356","post","type-post","status-publish","format-standard","hentry","category-softwareentwicklung","tag-docker","tag-git","tag-java","tag-jenkins"],"_links":{"self":[{"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/posts\/356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/comments?post=356"}],"version-history":[{"count":6,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/posts\/356\/revisions"}],"predecessor-version":[{"id":367,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/posts\/356\/revisions\/367"}],"wp:attachment":[{"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/media?parent=356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/categories?post=356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/tags?post=356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}