{"id":28,"date":"2021-01-10T22:19:39","date_gmt":"2021-01-10T21:19:39","guid":{"rendered":"https:\/\/informatik.htwk-leipzig.de\/seminar\/?p=28"},"modified":"2021-02-01T20:06:10","modified_gmt":"2021-02-01T19:06:10","slug":"docker-auf-dem-raspberry-pi","status":"publish","type":"post","link":"https:\/\/informatik.htwk-leipzig.de\/seminar\/lehrveranstaltungen\/betriebliche-informationssysteme\/2021\/docker-auf-dem-raspberry-pi\/","title":{"rendered":"Docker auf dem Raspberry Pi"},"content":{"rendered":"<h2>Docker<\/h2>\n<hr \/>\n<p>Docker ist eine Containerisierungstechnologie, die es erm\u00f6glicht eine leichtgewichtige Virtualisierung zu erreichen. Im Unterschied zu VMs wird bei Docker Containern keine Emulation der Hardware verwendet, sondern Applikationen mittels <a href=\"https:\/\/lwn.net\/Articles\/528078\/\" target=\"_blank\" rel=\"noopener\">namespaces <\/a>isoliert. <a href=\"https:\/\/www.docker.com\/resources\/what-container\">Docker Container<\/a> stellen abgekapselte Einheiten dar, die unabh\u00e4ngig voneinander ausgef\u00fchrt werden k\u00f6nnen, egal wo sie sich gerade befinden. Die Container sind schnell und effizient skalierbar, falls mehr Instanzen einer Anwendung ben\u00f6tigt werden. Die Basis eines Docker Containers bildet ein Docker-Image, das alle Komponenten enth\u00e4lt um eine Applikation plattformunabh\u00e4ngig auszuf\u00fchren.<\/p>\n<figure>\n<img decoding=\"async\" src=\"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-content\/uploads\/2021\/01\/docker-containerized-appliction-blue-border_2.png\" alt=\"Virtualisierung mit Docker\" \/><figcaption>Aufbau der Virtualisierung mit Docker<\/figcaption><small>Quelle: https:\/\/www.docker.com\/sites\/default\/files\/d8\/2018-11\/docker-containerized-appliction-blue-border_2.png<\/small><br \/>\n<\/figure>\n<h2>Installation von Docker<\/h2>\n<p>Herunterladen des <a href=\"https:\/\/get.docker.com\" target=\"_blank\" rel=\"noopener\">Installations-Skripts<\/a> und Ausf\u00fchrung dieses Skriptes<br \/>\n<code>curl -sSL https:\/\/get.docker.com | sh<\/code><\/p>\n<p>Pi-Benutzer die Erlaubnis zum Ausf\u00fchren von Docker-Befehlen erteilen<br \/>\n<code>sudo usermod -aG docker pi<\/code><br \/>\nNach des Befehls sollte der Raspberry Pi neugestartet werden, oder die n\u00e4chsten Befehle sollten mit <code>sudo<\/code> ausgef\u00fchrt werden!<\/p>\n<p>Um zu testen ob Docker funktioniert kann <a href=\"https:\/\/hub.docker.com\/_\/hello-world\" target=\"_blank\" rel=\"noopener\">Hello-World<\/a> ausgef\u00fchrt werden<br \/>\n<code>docker run hello-world<\/code><\/p>\n<p>Als Ausgabe sollte nun folgende sein, wenn alles funktioniert hat:<br \/>\n<code>Hello from Docker!<br \/>\nThis message shows that your installation appears to be working correctly.<br \/>\n...<\/code><\/p>\n<h2>Eigenes Docker-Image<\/h2>\n<p>Das Schreiben eines <a href=\"https:\/\/docs.docker.com\/develop\/develop-images\/baseimages\/\">Dockerfiles<\/a> ist der erste Schritt zum Image-Erstellen einer Anwendung. Das Dockerfile in der Bulletin-Board-Anwendung sieht wie folgt aus:<br \/>\n<code># Use the official image as a parent image.<br \/>\nFROM node:current-slim<\/code><\/p>\n<p># Set the working directory.<br \/>\nWORKDIR \/usr\/src\/app<\/p>\n<p># Copy the file from your host to your current location.<br \/>\nCOPY package.json .<\/p>\n<p># Run the command inside your image filesystem.<br \/>\nRUN npm install<\/p>\n<p># Add metadata to the image to describe which port the container is listening on at runtime.<br \/>\nEXPOSE 8080<\/p>\n<p># Run the specified command within the container.<br \/>\nCMD [ &#8222;npm&#8220;, &#8222;start&#8220; ]<\/p>\n<p># Copy the rest of your app&#8217;s source code from your host to your image filesystem.<br \/>\nCOPY . .<\/p>\n<h2>Dotnet Anwendung als Docker-Image<\/h2>\n<h3>Installation der Dotnet-Runtime<\/h3>\n<p><code># Herunterladen der Dotnet-Runtime 3.5<br \/>\nwget https:\/\/download.visualstudio.microsoft.com\/download\/pr\/a2223d1f-c138-4586-8cd1-274c5387e975\/623ece755546aca8f4be268f525683c5\/aspnetcore-runtime-3.1.10-linux-arm.tar.gz<br \/>\n# Erstellen des Verzeichnisses<br \/>\nsudo mkdir -p $HOME\/dotnet<br \/>\n# Entpacken der Anwendung ins ausgew\u00e4hlte Verzeichnis<br \/>\nsudo tar zxf dotnet-sdk-3.1.100-linux-arm.tar.gz -C $HOME\/dotnet<br \/>\n# Setzen der Pfade f\u00fcr Dotnet<br \/>\nexport DOTNET_ROOT=$HOME\/dotnet<br \/>\n# Verlinkung der Dotnet Anwendung<br \/>\nexport PATH=$PATH:$HOME\/dotnet<\/code><\/p>\n<h3> Beispielanwendung <\/h3>\n<p>Zu Demonstrationszwecken wurde eine kleine C# Test-Awendung erstellt, welche Dotnet-Core Runtime ben\u00f6tigt. Das Update-script kompiliert das Programm und erstellt danach das Docker-Image. Hierbei wird auch noch Dotnet-Core SDK ben\u00f6tigt. Die Anwendung wird beim Image-Build vom Hauptverzeichniss in das App Verzeichniss im Docker-Image kopiert und dann ausgef\u00fchrt. Da es nur eine Konsolen-Applikation mit einem einmaligen Log ist, beendet sich der Container sofort wieder. Wenn der Container dauerhauft laufen soll, muss eine Endlosschleife in der Anwendung ausgef\u00fchrt werden.<\/p>\n<h3>Dockerfile auf dem Raspberry Pi<\/h3>\n<p><code>FROM mcr.microsoft.com\/dotnet\/core\/runtime:3.1.9-buster-slim-arm32v7<\/code><\/p>\n<p>WORKDIR \/app<\/p>\n<p>COPY program\/bin\/Release\/netcoreapp3.0\/ .<br \/>\nCOPY data data<\/p>\n<p>CMD [&#8222;.\/program&#8220;]<\/p>\n<h3>Update-script<\/h3>\n<p><code>#!\/bin\/bash<br \/>\ncd \/home\/pi\/Projects\/docker\/program\/<br \/>\ngit fetch<br \/>\nif git status | grep -q \"behind\"; then<br \/>\ngit pull<br \/>\ndotnet build --configuration Release<br \/>\ncd ..<br \/>\ndocker rm $(docker stop $(docker ps -a -q --filter ancestor=program:1.0 --format=\"{{.ID}}\"))<br \/>\ndocker build --tag program:1.0 .<br \/>\ndocker container run program:1.0<br \/>\nfi<\/code><\/p>\n<p>Das folgende EPK zeigt die funktionsweise des Updatescriptes.<\/p>\n<figure>\n<img decoding=\"async\" src=\"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-content\/uploads\/2021\/01\/plantuml.png\" alt=\"Aktivit\u00e4tsdiagramm der Beispielanwendung\" \/><figcaption>EPK der Beispielanwendung mit Dotnet Core<\/figcaption><\/figure>\n<h3>Cron-Jobs<\/h3>\n<p><code># aufrufen aller cron jobs<br \/>\ncrontab -e<br \/>\n# akuteller cron job auf dem Raspberry pi<br \/>\n5 * * * * \/home\/pi\/Projects\/docker\/update.sh<\/code><br \/>\n<a href=\"https:\/\/gitlab.imn.htwk-leipzig.de\/spoetter\/docker-on-pi\" target=\"_blank\" rel=\"noopener\">Git Repo<\/a><\/p>\n<h3>Debugging<\/h3>\n<p><code>docker exec -it &lt;id&gt; bash<\/code><\/p>\n<hr \/>\n<h2>Alternative Ger\u00e4te und Boards<\/h2>\n<p><a href=\"http:\/\/www.orangepi.org\/\" target=\"_blank\" rel=\"noopener\">OrangePi<\/a><br \/>\n<a href=\"http:\/\/www.banana-pi.org\/\" target=\"_blank\" rel=\"noopener\">BananaPi<\/a><br \/>\n<a href=\"https:\/\/wiki.radxa.com\/Rockpi4\" target=\"_blank\" rel=\"noopener\">RockPi4<\/a><br \/>\n<a href=\"https:\/\/www.intel.com\/content\/www\/us\/en\/products\/boards-kits\/compute-stick.html\" target=\"_blank\" rel=\"noopener\">Intel: System on a Stick<\/a><br \/>\n<a href=\"https:\/\/www.lattepanda.com\/\" target=\"_blank\" rel=\"noopener\">LattePanda 4G\/64G<\/a><\/p>\n<h2>Vortragsfolien<\/h2>\n<p><a href=\"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-content\/uploads\/2021\/01\/Betriebliche_Informationssysteme___Docker_auf_Raspberry1.pdf\">Vortragsfolien: Docker auf Raspberry Pi<\/a><\/p>\n<p><!--more--><br \/>\nAutoren: Sebastian P\u00f6tter, Mathis Greve<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Docker Docker ist eine Containerisierungstechnologie, die es erm\u00f6glicht eine leichtgewichtige Virtualisierung zu erreichen. Im Unterschied zu VMs wird bei Docker<\/p>\n","protected":false},"author":8,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[9,8,7],"class_list":["post-28","post","type-post","status-publish","format-standard","hentry","category-betriebliche-informationssysteme","tag-docker","tag-server","tag-virtualisierung"],"_links":{"self":[{"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/posts\/28","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/comments?post=28"}],"version-history":[{"count":22,"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/posts\/28\/revisions"}],"predecessor-version":[{"id":592,"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/posts\/28\/revisions\/592"}],"wp:attachment":[{"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/media?parent=28"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/categories?post=28"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/informatik.htwk-leipzig.de\/seminar\/wp-json\/wp\/v2\/tags?post=28"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}