{"id":7945,"date":"2021-11-21T19:17:34","date_gmt":"2021-11-21T17:17:34","guid":{"rendered":"https:\/\/u-labs.de\/portal\/?p=7945"},"modified":"2022-12-12T18:25:05","modified_gmt":"2022-12-12T16:25:05","slug":"docker-container-im-autostart-restartpolicies-von-docker-statt-systemd-dienst-raspberry-pi","status":"publish","type":"post","link":"https:\/\/u-labs.de\/portal\/docker-container-im-autostart-restartpolicies-von-docker-statt-systemd-dienst-raspberry-pi\/","title":{"rendered":"Docker-Container im Autostart: RestartPolicies von Docker statt Systemd-Dienst &#8211; Raspberry Pi"},"content":{"rendered":"<p>Alexander hat zum Beitrag &#8222;Mein erster Container&#8220; eine Zuschauerfrage gestellt: Er kommt aus der <em>klassischen<\/em> Linux Welt und fragt, wie er einen Docker-Container automatisch starten kann und ob daf\u00fcr ein Daemon oder andere spezielle Konfiguration notwendig ist.<\/p>\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2021\/11\/grafik-9.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"255\" src=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2021\/11\/grafik-9-1024x255.png\" alt=\"\" class=\"wp-image-7946\" srcset=\"https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2021\/11\/grafik-9-1024x255.png 1024w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2021\/11\/grafik-9-300x75.png 300w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2021\/11\/grafik-9-768x191.png 768w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2021\/11\/grafik-9-70x17.png 70w, https:\/\/u-labs.de\/portal\/wp-content\/uploads\/2021\/11\/grafik-9.png 1401w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<p>Ich hatte darauf schon kurz geantwortet, an dieser Stelle noch einmal Danke f\u00fcr dein Feedback! In diesem Beitrag m\u00f6chte ich die Restart-Policys ausf\u00fchrlicher vorstellen. Mit Ihnen k\u00f6nnt ihr das Startverhalten von Containern steuern. Parallel dazu werden wir einen Blick auf den klassischen Weg mit (Systemd) Diensten und an der relevanten Stelle auch auf den Aufbau von Docker, um zu verstehen, wie Docker den Autostart ohne separate Dienste erm\u00f6glicht. <\/p>\n<p>Im folgenden werde ich mich auf das Beispielszenario aus seinem Kommentar fokussieren, also einen Nginx Webserver. Grunds\u00e4tzlich l\u00e4sst sich dies aber auch auf andere Dienste anwenden &#8211; egal ob es sich um einen Apache2-Webserver oder ganz andere Programme handelt, die automatisch im Hintergrund gestartet werden sollen. Es geht also mehr ums Konzept als um den konkreten Anwendungsfall.<\/p>\n<h2 class=\"wp-block-heading\">Ein Schritt zur\u00fcck: So funktioniert der Autostart von Hintergrunddiensten ohne Docker<\/h2>\n<p>Systemd kommt mittlerweile unter nahezu allen g\u00e4ngigen Linux-Distributionen als Init-System zum Einsatz. Die Grunds\u00e4tzliche Aufgabe eines Init-Systemes ist die gesamte Verwaltung aller Dienste. Konkret sind die wichtigsten dabei in unserem Szenario:<\/p>\n<ol class=\"wp-block-list\">\n<li>Nach dem Booten den Nginx-Webserver im Hintergrund starten<\/li>\n<li>Beim Herunterfahren Nginx beenden<\/li>\n<\/ol>\n<p>Das Init-System k\u00fcmmert sich noch um eine Reihe zus\u00e4tzlicher Dinge. Beispielsweise das parallele Starten mehrere Dienste, soweit m\u00f6glich. Oder um Abh\u00e4ngigkeiten. Ein Dienst der aufs Internet zugreift, wird etwa erst gestartet, wenn die Netzwerkverbindung steht.<\/p>\n<p>Unter Systemd legt man daf\u00fcr ein sogenanntes <strong>Service Unit<\/strong> an, mit allen Details: Wie wird der Dienst gestartet, wie gestoppt, welche Abh\u00e4ngigkeiten gibt es usw. Installiert ihr entsprechende Programme per APT, kommt in der Regel ein entsprechend konfiguriertes <strong>Service Unit<\/strong> gleich mit. Der Nginx startet dadurch automatisch, ohne dass man mit dem Systemd-Dienst gro\u00dfartig in Ber\u00fchrung kommt &#8211; au\u00dfer einem Neustart per <strong>systemctl restart nginx<\/strong>. Im Hintergrund l\u00e4dt Systemd beim Booten die Unit und startet unseren Webserver als Hintergrundprozess.<\/p>\n<h2 class=\"wp-block-heading\">Wie funktioniert Docker?<\/h2>\n<p>Bei Docker haben wir eine Client-Server Architektur: Es gibt den Docker-Daemon, welcher letztendlich auch nur ein Systemd-Dienst ist und dadurch automatisch nach dem Booten gestartet wird. Wenn ihr Docker oder Docker-Compose nutzt, kommunizierten diese Programme im Hintergrund mit dem Daemon, welcher die Befehle ausf\u00fchrt.<\/p>\n<p>Beispiel: Wir starten einen Nginx-Container. Der Docker-Client (egal ob Docker oder Docker-Compose) sendet an den Docker-Daemon einen Befehl, dass er den Nginx-Container mit dem entsprechendem Image, Tag, Name und so weiter starten soll. Dieser l\u00e4dt das Image herunter falls notwendig und erzeugt den Container. Anschlie\u00dfend erh\u00e4lt der Client eine R\u00fcckmeldung, ob es funktioniert hat oder Fehler aufgetreten sind.<\/p>\n<p>Diese Architektur hat auch Nachteile und es gibt Alternativen. Das k\u00f6nnen wir uns in einem eigenen Beitrag mal genauer anschauen, an dieser Stelle w\u00fcrde es den Rahmen sprengen &#8211; daher fokussieren wir uns hier auf den Autostart.<\/p>\n<h2 class=\"wp-block-heading\">Restart-Policys: Docker-Container automatisch starten, z.B. beim Systemstart<\/h2>\n<p>Jedem Container kann man eine sogenannte <strong>Restart-Policy<\/strong> zuweisen. Es gibt 4 verschiedene Policies:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>no<\/strong> ist die Standard-Policy: Es gibt keine automatischen Starts oder Neustarts. Der Container l\u00e4uft nur, wenn ihr ihn von Hand startet.<\/li>\n<li><strong>on-failure<\/strong> startet den Container nur neu, wenn er abst\u00fcrzt und dies sauber durch einen Exitcode ungleich 0 mitteilt. Es gibt keinen Autostart beim Booten!<\/li>\n<li><strong>always<\/strong> sorgt daf\u00fcr, dass der Container immer gestartet wird. <\/li>\n<li><strong>unless-stopped<\/strong> verh\u00e4lt sich wie <strong>always<\/strong>, mit einem einzigen Unterschied: Wird der Docker-Daemon neu gestartet (z.B: Systemneustart), dann startet er den Container nur dann, wenn er vor dem Neustart auch lief. Wenn wir also den Container mit z.B. <strong>docker stop<\/strong> stoppen und dann neu starten, l\u00e4uft er danach nicht. Wogegen <strong>always<\/strong> ihn starten w\u00fcrde.<\/li>\n<\/ul>\n<p>Beim Beispiel des Webservers machen nur <strong>always<\/strong> und <strong>unless-stopped<\/strong> Sinn, wobei ich an dieser Stelle <strong>always<\/strong> nutzen w\u00fcrde. Bootet ihr neu, startet Systemd den Docker-Daemon. Dieser pr\u00fcft anhand der Restart-Policies, welche Container er starten soll. Auf die Startreihenfolge habt ihr allerdings nur innerhalb einer Docker-Compose Datei durch die Abh\u00e4ngigkeiten Einfluss! Dies ist meistens kein Problem und wird es erst bei gr\u00f6\u00dferen Docker-Hosts, die entsprechend schwergewichtige Container wie z.B. umfangreiche Java-Anwendungen starten.<\/p>\n<h3 class=\"wp-block-heading\">Demonstration der Restart-Policies<\/h3>\n<p>Um das zu verdeutlichen, erstellen wir in einer <strong>docker-compose.yml<\/strong> vier Nginx Webserver:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\nversion: &quot;2.4&quot;\n\nservices:\n  nginx_no:\n    image: nginx:1.21\n    restart: &quot;no&quot;\n\n  nginx_on-failture:\n    image: nginx:1.21\n    restart: on-failure\n\n  nginx_always:\n    image: nginx:1.21\n    restart: always\n\n  nginx_unless-stopped:\n    image: nginx:1.21\n    restart: unless-stopped\n\n<\/pre>\n<\/div>\n<p>Die Portfreigaben werden f\u00fcr den Test nicht ben\u00f6tigt und wurden daher weggelassen. Starten wir die Container mit <strong>docker-compose up -d<\/strong> und starten den Pi neu, sollten nur jene mit der Restart-Policy <strong>always<\/strong> und <strong>unless-stopped<\/strong> automatisch gestartet worden sein:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n$ docker-compose ps\nNAME                                             COMMAND                  SERVICE                STATUS              PORTS\ndocker-restart-policies-nginx_always-1           &quot;\/docker-entrypoint.\u2026&quot;   nginx_always           running             80\/tcp\ndocker-restart-policies-nginx_no-1               &quot;\/docker-entrypoint.\u2026&quot;   nginx_no               exited (0)\ndocker-restart-policies-nginx_on-failture-1      &quot;\/docker-entrypoint.\u2026&quot;   nginx_on-failture      exited (0)\ndocker-restart-policies-nginx_unless-stopped-1   &quot;\/docker-entrypoint.\u2026&quot;   nginx_unless-stopped   running             80\/tcp\n<\/pre>\n<\/div>\n<p>Stoppen wir den Container mit der Policy <strong>unless-stopped<\/strong> und starten den Docker-Daemon neu, l\u00e4uft nach dem Starten des Daemon nur noch der Container mit der Policy <strong>always<\/strong>:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \">\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n$ docker stop docker-restart-policies-nginx_unless-stopped-1\n$ sudo systemctl restart docker\n...\n$ docker-compose ps\nNAME                                             COMMAND                  SERVICE                STATUS              PORTS\ndocker-restart-policies-nginx_always-1           &quot;\/docker-entrypoint.\u2026&quot;   nginx_always           running             80\/tcp\ndocker-restart-policies-nginx_no-1               &quot;\/docker-entrypoint.\u2026&quot;   nginx_no               exited (0)\ndocker-restart-policies-nginx_on-failture-1      &quot;\/docker-entrypoint.\u2026&quot;   nginx_on-failture      exited (0)\ndocker-restart-policies-nginx_unless-stopped-1   &quot;\/docker-entrypoint.\u2026&quot;   nginx_unless-stopped   exited (0)\n\n<\/pre>\n<\/div>\n<h2 class=\"wp-block-heading\">Fazit: Eigene Systemd-Dienste braucht man mit Docker in der Regel nicht<\/h2>\n<p>Wird Docker eingesetzt, m\u00fcssen wir uns lediglich f\u00fcr eine Restart-Policy entscheiden &#8211; um alles weitere k\u00fcmmert sich der Docker-Daemon. Auch f\u00fcr selbst entwickelte Programme braucht keine <em>Systemd Unit<\/em> erstellt werden. Das reicht in den meisten F\u00e4llen v\u00f6llig aus. <\/p>\n<p>Ich hoffe, damit etwas Klarheit in das Autostartkonzept von Docker-Containern gebracht zu haben. Falls du noch weitere Fragen und Themenvorschl\u00e4ge hast, poste sie gerne ins Forum. Ich versuche sie zu beantworten und werde bei Themen, die f\u00fcr viele interessant sein k\u00f6nnen, weitere Beitr\u00e4ge anhand von Zuschauerfragen erstellen. In jedem Falle w\u00fcnsche ich dir viel Erfolg mit deinen Projekten!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Alexander hat zum Beitrag &#8222;Mein erster Container&#8220; eine Zuschauerfrage gestellt: Er kommt aus der klassischen Linux Welt und fragt, wie er einen Docker-Container automatisch starten kann und ob daf\u00fcr ein Daemon oder andere spezielle Konfiguration notwendig ist. Ich hatte darauf schon kurz geantwortet, an dieser Stelle noch einmal Danke f\u00fcr dein Feedback! In diesem Beitrag &#8230;<\/p>\n","protected":false},"author":5,"featured_media":7953,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[671],"tags":[497,75,989],"class_list":["post-7945","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-raspberry-pi","tag-docker","tag-linux","tag-systemd"],"_links":{"self":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/7945","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/comments?post=7945"}],"version-history":[{"count":9,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/7945\/revisions"}],"predecessor-version":[{"id":9811,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/7945\/revisions\/9811"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media\/7953"}],"wp:attachment":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media?parent=7945"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/categories?post=7945"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/tags?post=7945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}