{"id":368,"date":"2021-04-05T07:49:23","date_gmt":"2021-04-05T05:49:23","guid":{"rendered":"https:\/\/nissel.it\/?p=368"},"modified":"2021-04-05T15:32:57","modified_gmt":"2021-04-05T13:32:57","slug":"docker-in-docker-ueber-jenkins-pipeline","status":"publish","type":"post","link":"https:\/\/nissel.it\/index.php\/2021\/04\/05\/docker-in-docker-ueber-jenkins-pipeline\/","title":{"rendered":"Docker in Docker \u00fcber Jenkins pipeline"},"content":{"rendered":"\n<p>In dem Artikel <a href=\"https:\/\/nissel.it\/index.php\/2021\/04\/04\/gitlab-jenkins-buildpipeline-maven-java-docker-umgebung-fuer-entwickler\/\" data-type=\"post\" data-id=\"356\">Gitlab + Jenkins + buildpipeline + Maven + Java Docker Umgebung f\u00fcr Entwickler<\/a> habe ich beschrieben wie ein Jenkins \u00fcber Docker aufgesetzt werden kann. Ziel ist es jetzt \u00fcber den Jenkins \u00fcber die Buildpipeline ein Dockerfile zu starten und dort einen Befehl auszuf\u00fchren.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"651\" height=\"411\" src=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/docker-pipeline.jpg\" alt=\"\" class=\"wp-image-371\" srcset=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/docker-pipeline.jpg 651w, https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/docker-pipeline-300x189.jpg 300w\" sizes=\"auto, (max-width: 651px) 100vw, 651px\" \/><figcaption>Jenkins Pipeline mit Docker Container<\/figcaption><\/figure>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Docker in Docker Zugriff \u00fcber tcp<\/h2>\n\n\n\n<p>Der Zugriff docker \u00fcber tcp ist am flexibelsten. Der Docker Host\/Server kann \u00fcberall betrieben werden.  Grunds\u00e4tzlich muss daf\u00fcr nur ein Umgebungsvariable im container gesetzt werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DOCKER_HOST: tcp:\/\/host.docker.internal:2375<\/code><\/pre>\n\n\n\n<p>Unter Windows muss in den Docker Einstellungen der Port freigegeben werden. Unter Ubuntu 20.04 m\u00fcssen eine Reihe von Konfigurationen vorgenommen werden. Zuerst muss die Datei \/etc\/systemd\/system\/docker.service.d\/override.conf erstellt werden<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p \/etc\/systemd\/system\/docker.service.d\nnano \/etc\/systemd\/system\/docker.service.d\/override.conf\n\n&#91;Service]\nExecStart=\nExecStart=\/usr\/bin\/dockerd<\/code><\/pre>\n\n\n\n<p>Danach muss in der \/etc\/docker\/daemon.json der port und socket frei gegeben werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo '{\"hosts\": &#91;\"tcp:\/\/0.0.0.0:2375\", \"unix:\/\/\/var\/run\/docker.sock\"]}' &gt; \/etc\/docker\/daemon.json<\/code><\/pre>\n\n\n\n<p>Nun kann docker neu gestartet werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl daemon-reload &amp;&amp; systemctl restart docker.service<\/code><\/pre>\n\n\n\n<p>Damit der Dockerhost nicht als IP angegeben werden muss, sollte eine Docker Version gr\u00f6\u00dfer gleich 20.10 verwendet werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ docker --version\nDocker version 20.10.5, build 55c4c88<\/code><\/pre>\n\n\n\n<p>Diese habe ich auch im Jenkins Docker image verwendet. Da dies auf debian 10 basiert, wird es wie folgt installiert:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RUN apt install -y apt-transport-https ca-certificates curl gnupg lsb-release\nRUN curl -fsSL https:\/\/download.docker.com\/linux\/debian\/gpg | gpg --dearmor -o \/usr\/share\/keyrings\/docker-archive-keyring.gpg\nRUN echo \"deb &#91;arch=amd64 signed-by=\/usr\/share\/keyrings\/docker-archive-keyring.gpg] https:\/\/download.docker.com\/linux\/debian \\\n  $(lsb_release -cs) stable\" | tee \/etc\/apt\/sources.list.d\/docker.list &gt; \/dev\/null\nRUN apt update\nRUN apt install -y docker-ce docker-ce-cli containerd.io<\/code><\/pre>\n\n\n\n<p>Unter Windows ist automatisch der Host unter den DNS Namen host.docker.internal erreichbar. Unter Windows muss dies im extra_host Bereich angegeben werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>version: \"3.3\"\n\nservices:\n  jenkins:\n    container_name: jenkins\n    environment:\n      JAVA_OPTS: -Djenkins.install.runSetupWizard=false -Xmx8192m\n      DOCKER_HOST: tcp:\/\/host.docker.internal:2375\n    ports:\n     - 8080:8080\n     - 50000:50000\n    volumes:\n     - .\/data\/jenkins:\/var\/jenkins_home\n docker container over socket\n    build:\n      context: .\/jenkins\n    extra_hosts:\n      - host.docker.internal:host-gateway<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Docker in Docker Zugriff \u00fcber Socket (Alternative)<\/h2>\n\n\n\n<p>Als alternative zu der tcp Verbindung kann man docker auch \u00fcber socket verbinden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>volumes:\n     - \/var\/run\/docker.sock:\/var\/run\/docker.sock<\/code><\/pre>\n\n\n\n<p>In Wirklichkeit l\u00e4uft docker auf dem Host System und wird \u00fcber einen Unix socket bereitgestellt. Dies funktioniert auch unter Windows mit WSL2. Dieser Socket ist mit bestimmten Rechten angelegt. Da der Jenkins im container nicht mit root Rechten l\u00e4uft kann dieser Standardm\u00e4\u00dfig nicht zugreifen. Hier sind die Rechte an die groupid 998 gebunden:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ docker exec -it jenkins ls -ls \/var\/run\/docker.sock\n0 srw-rw---- 1 root 998 0 Apr  5 04:49 \/var\/run\/docker.sock<\/code><\/pre>\n\n\n\n<p>Es gibt grunds\u00e4tzlich zwei M\u00f6glichkeiten das Problem zu l\u00f6sen. Entweder im docker container die Rechte des socket anpassen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker exec --user root -it jenkins chmod 666 \/var\/run\/docker.sock<\/code><\/pre>\n\n\n\n<p>Oder die UserId (id -u) und die group des Hostsystem verwenden. Weiterer Vorteil ist, dass die Dateien mit den Rechten des Benutzers des Hostsystems erstellt werden und so volumes gemeinsam genutzt werden k\u00f6nnen. Dazu muss nur in der dokcer-compose.yml &#8222;user: 1000:998&#8220; f\u00fcr UserId 1000 und GroupId 998 hinzugef\u00fcgt werden:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>version: \"3.3\"\n\nservices:\n  jenkins:\n    container_name: jenkins\n    environment:\n      JAVA_OPTS: -Djenkins.install.runSetupWizard=false -Xmx8192m\n    ports:\n     - 8080:8080\n     - 50000:50000\n    user: 1000:998 # Local user and groupid to run docker in docker\n    volumes:\n     - .\/data\/jenkins:\/var\/jenkins_home\n     - \/var\/run\/docker.sock:\/var\/run\/docker.sock # To run docker in docker container\n    build:\n      context: .\/jenkins<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Jenkins docker pipeline<\/h2>\n\n\n\n<p>Damit Docker im Jenkins benutzt werden kann, muss im Jenkins image auch docker installiert werden:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RUN apt install -y docker.io<\/code><\/pre>\n\n\n\n<p>Und den Docker Support f\u00fcr jenkins und der pipeline.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RUN jenkins-plugin-cli --plugins docker-workflow:1.26 docker-plugin:1.2.2<\/code><\/pre>\n\n\n\n<p>Als Beispiel verwende ich eine Dockerfile in der ein wget installiert wird.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FROM ubuntu:20.04\nRUN apt update &amp;&amp; apt upgrade\nRUN apt install -y wget<\/code><\/pre>\n\n\n\n<p>Dazu lege ich ein Jenkinsfile in der das Dockerfile verwendet wird und ein wget auf eine URL aufgerufen wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pipeline {\n    agent { dockerfile true }\n    stages {\n        stage('Run wget') {\n            steps {\n                sh 'wget https:\/\/nissel.it'\n            }\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"651\" height=\"524\" src=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/docker-pipeline-output.png\" alt=\"\" class=\"wp-image-370\" srcset=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/docker-pipeline-output.png 651w, https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/docker-pipeline-output-300x241.png 300w\" sizes=\"auto, (max-width: 651px) 100vw, 651px\" \/><figcaption>Docker pipleine Konsolen Ausgabe<\/figcaption><\/figure>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/jenkins-env-2.zip\">jenkins-env-2<\/a><a href=\"https:\/\/nissel.it\/wp-content\/uploads\/2021\/04\/jenkins-env-2.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:\/\/dev.to\/acro5piano\/specifying-user-and-group-in-docker-i2e\">https:\/\/dev.to\/acro5piano\/specifying-user-and-group-in-docker-i2e<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/faun.pub\/set-current-host-user-for-docker-container-4e521cef9ffc\">https:\/\/faun.pub\/set-current-host-user-for-docker-container-4e521cef9ffc<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/gist.github.com\/styblope\/dc55e0ad2a9848f2cc3307d4819d819f\">https:\/\/gist.github.com\/styblope\/dc55e0ad2a9848f2cc3307d4819d819f<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/stackoverflow.com\/questions\/29076194\/using-add-host-or-extra-hosts-with-docker-compose\">https:\/\/stackoverflow.com\/questions\/29076194\/using-add-host-or-extra-hosts-with-docker-compose<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/medium.com\/nttlabs\/docker-20-10-59cc4bd59d37\">https:\/\/medium.com\/nttlabs\/docker-20-10-59cc4bd59d37<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/stackoverflow.com\/questions\/48546124\/what-is-linux-equivalent-of-host-docker-internal\">https:\/\/stackoverflow.com\/questions\/48546124\/what-is-linux-equivalent-of-host-docker-internal<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/docs.docker.com\/engine\/install\/debian\/\">https:\/\/docs.docker.com\/engine\/install\/debian\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In dem Artikel Gitlab + Jenkins + buildpipeline + Maven + Java Docker Umgebung f\u00fcr Entwickler habe ich beschrieben wie ein Jenkins \u00fcber Docker aufgesetzt werden kann. Ziel ist es jetzt \u00fcber den Jenkins \u00fcber die Buildpipeline ein Dockerfile zu starten und dort einen Befehl auszuf\u00fchren.<\/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,17],"class_list":["post-368","post","type-post","status-publish","format-standard","hentry","category-softwareentwicklung","tag-docker","tag-jenkins"],"_links":{"self":[{"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/posts\/368","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=368"}],"version-history":[{"count":8,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/posts\/368\/revisions"}],"predecessor-version":[{"id":387,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/posts\/368\/revisions\/387"}],"wp:attachment":[{"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/media?parent=368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/categories?post=368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nissel.it\/index.php\/wp-json\/wp\/v2\/tags?post=368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}