<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Docker Archive - TekkieNinja</title>
	<atom:link href="https://tekkieninja.de/category/docker/feed/" rel="self" type="application/rss+xml" />
	<link>https://tekkieninja.de/category/docker/</link>
	<description>Ein Technik Blog mit dem Tekkie Ninja</description>
	<lastBuildDate>Mon, 04 Sep 2023 20:00:13 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://tekkieninja.de/wp-content/uploads/2023/04/cropped-favicon-1-32x32.png</url>
	<title>Docker Archive - TekkieNinja</title>
	<link>https://tekkieninja.de/category/docker/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Reverse Proxy in Docker mit Let&#8217;s Encrypt-Zertifikaten</title>
		<link>https://tekkieninja.de/reverse-proxy-in-docker-mit-lets-encrypt-zertifikaten/</link>
					<comments>https://tekkieninja.de/reverse-proxy-in-docker-mit-lets-encrypt-zertifikaten/#respond</comments>
		
		<dc:creator><![CDATA[Florian Keßler]]></dc:creator>
		<pubDate>Fri, 09 Jun 2023 10:11:36 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<guid isPermaLink="false">https://tekkieninja.de/?p=1292</guid>

					<description><![CDATA[<p>In diesem Blogbeitrag werden wir uns detailliert mit der Konfiguration eines Reverse Proxys in Docker mit Let&#8217;s Encrypt-Zertifikaten befassen und zeigen, wie diese in den Prozess integriert werden können. Wir werden gemeinsam Schritt für Schritt die erforderlichen Maßnahmen durchgehen, um einen sicheren und zuverlässigen Reverse Proxy aufzusetzen, der den Datenverkehr effizient verteilt und gleichzeitig eine [&#8230;]</p>
<p>Der Beitrag <a href="https://tekkieninja.de/reverse-proxy-in-docker-mit-lets-encrypt-zertifikaten/">Reverse Proxy in Docker mit Let&#8217;s Encrypt-Zertifikaten</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="1292" class="elementor elementor-1292">
				<div class="elementor-element elementor-element-990b214 e-con-full e-flex e-con e-parent" data-id="990b214" data-element_type="container" data-e-type="container">
				<div class="elementor-element elementor-element-6342ed5 elementor-widget elementor-widget-text-editor" data-id="6342ed5" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>In diesem Blogbeitrag werden wir uns detailliert mit der Konfiguration eines Reverse Proxys in Docker mit Let&#8217;s Encrypt-Zertifikaten befassen und zeigen, wie diese in den Prozess integriert werden können. Wir werden gemeinsam Schritt für Schritt die erforderlichen Maßnahmen durchgehen, um einen sicheren und zuverlässigen Reverse Proxy aufzusetzen, der den Datenverkehr effizient verteilt und gleichzeitig eine verschlüsselte Kommunikation gewährleistet.</p><p>Egal, ob du bereits mit Docker vertraut bist oder gerade erst anfängst, dieser Blogbeitrag bietet dir eine umfassende Anleitung, um Reverse Proxy und Let&#8217;s Encrypt-Zertifikate erfolgreich zu implementieren. Tauche ein in die Welt des sicheren Datenverkehrs und erfahre, wie du deine Webanwendungen oder Websites vor potenziellen Bedrohungen schützen kannst.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-3dfb4df elementor-widget elementor-widget-heading" data-id="3dfb4df" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Grundlagen</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-fe3bf31 elementor-widget elementor-widget-text-editor" data-id="fe3bf31" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Ein Reverse Proxy agiert als Vermittler zwischen den Clients und den Servern. Er nimmt eingehende Anfragen entgegen und leitet sie an die entsprechenden Backend-Server bzw. App Container weiter. Dadurch können wir den Datenverkehr effizient verteilen, Lastausgleich betreiben und zusätzliche Sicherheitsschichten einführen.</p><p>Ein wichtiger Aspekt bei der Implementierung eines Reverse Proxys ist die Integration von Let&#8217;s Encrypt-Zertifikaten. Let&#8217;s Encrypt ist eine kostenlose und automatisierte Zertifizierungsstelle, die es Website-Betreibern ermöglicht, SSL/TLS-Zertifikate einfach zu erhalten und ihre Verbindung zu verschlüsseln. Durch die Verwendung von Let&#8217;s Encrypt-Zertifikaten stellen wir sicher, dass die Kommunikation zwischen den Clients und den Backend-Servern verschlüsselt ist und vor potenziellen Angreifern geschützt wird.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-0495b40 elementor-widget elementor-widget-heading" data-id="0495b40" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Voraussetzungen</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-5ef5884 elementor-widget elementor-widget-text-editor" data-id="5ef5884" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Um den Reverse Proxy in Docker mit Let&#8217;s Encrypt-Zertifikaten erfolgreich zu implementieren, gibt es einige grundlegende Voraussetzungen, die erfüllt sein müssen. Stelle sicher, dass du die folgenden Anforderungen erfüllst, bevor du mit der Konfiguration beginnst:</p><ol><li><p>Docker und Docker Compose: Da wir Docker und Docker Compose verwenden, um den Reverse Proxy zu erstellen und zu verwalten, musst du diese Software auf deinem System installiert haben. Falls du dies noch nicht getan hast, habe ich dir eine <a href="https://tekkieninja.de/docker-compose-installieren/">Anleitung</a> verlinkt.</p></li><li><p>Grundkenntnisse von Docker: Um den Reverse Proxy in Docker effektiv zu konfigurieren, ist es wichtig, grundlegende Kenntnisse von Docker und seinen Kernkonzepten zu haben. Du solltest mit Begriffen wie Containern, Images, Dockerfiles und dem Docker-CLI (Command Line Interface) vertraut sein. Wenn du noch nicht mit Docker vertraut bist, habe ich dir eine <a href="https://tekkieninja.de/was-ist-docker/">Beitragsserie</a> zu dem Thema Docker verlinkt. </p></li><li><p>Grundkenntnisse von Docker Compose: Docker Compose ist ein Tool, das es ermöglicht, mehrere Docker-Container als Dienste zu definieren und zu verwalten. Es erleichtert die Konfiguration und das Zusammenspiel von Containern. Um den Reverse Proxy mit Let&#8217;s Encrypt-Zertifikaten in Docker zu implementieren, ist es hilfreich, grundlegende Kenntnisse von Docker Compose zu haben. Du solltest wissen, wie man eine Docker-Compose-Datei erstellt, Dienste definiert und Umgebungsvariablen festlegt. Einen kurzen Crashkurs habe ich dir hier <a href="https://tekkieninja.de/docker-compose-erklaert/">verlinkt</a>. </p></li></ol>								</div>
				</div>
				<div class="elementor-element elementor-element-4056236 elementor-widget elementor-widget-heading" data-id="4056236" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Docker-Compose-Datei</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-fa6b9bb elementor-widget elementor-widget-heading" data-id="fa6b9bb" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Docker Netzwerk</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-8828736 elementor-widget elementor-widget-text-editor" data-id="8828736" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Docker-Container können standardmäßig nicht von externen Quellen angesprochen werden. Daher müssen die Ports des Containers auf die des Host-Rechners gemappt werden. Auf diese Weise kann der Container über die IP-Adresse und den entsprechenden Port erreicht werden. Wenn jedoch bestimmte Dienste für das Internet freigegeben werden sollen, kann dies sehr aufwendig sein. Es erfordert nicht nur das Mappen der Container-Ports, sondern auch das Einrichten von Portfreigaben am Router. Dadurch entsteht eine größere Angriffsfläche für potenzielle Hacker. Zusätzlich können Container standardmäßig nicht direkt miteinander kommunizieren. Um sicherzustellen, dass der Reverse Proxy auf die verschiedenen Anwendungen zugreifen kann, muss zunächst ein separates Netzwerk erstellt werden, das unabhängig von den Containern ist.</p><p style="padding-left: 40px;"><code class="language-php">docker network create proxy_network</code></p><p>Du kannst den Namen <em>proxy_network</em> nach Belieben ändern. Durch die Verbindung der Container mit diesem Netzwerk wird sichergestellt, dass der Proxy auf die Container zugreifen kann. Es ist ratsam, nur die Container mit diesem Netzwerk zu verbinden, auf die von außerhalb des Heimnetzes zugegriffen werden soll.</p><p>Nachfolgend werden wir die Datei Schritt für Schritt gemeinsam aufbauen, damit die Installation des Revers Proxy in Docker verständlich ist.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-551e28b elementor-widget elementor-widget-heading" data-id="551e28b" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">nginx-proxy</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-efc281c elementor-widget elementor-widget-text-editor" data-id="efc281c" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>In der Docker-Compose-Datei beginnen die ersten beiden Zeilen wie in jeder anderen Datei. Die <em>version</em> gibt an, auf welcher Version die Datei aufbaut. Unter dem Abschnitt <em>services</em> definieren wir unsere Container. Zuerst wird der Reverse Proxy Container definiert.</p><pre><code>version: '3'
services:</code></pre><p>Wir haben uns für das Image von <em>jwilder</em> in der <em>alpine</em> Version entschieden, da es einen geringeren Angriffsvektor für potenzielle Angreifer bietet. Zusätzlich enthält es die empfohlenen Einstellungen der Mozilla-Organisation auf dem Intermediate-Level, um einen Kompromiss zwischen Sicherheit und Kompatibilität zu gewährleisten.</p><pre><code>nginx-proxy:
    image: jwilder/nginx-proxy:alpine</code></pre><p>Diese Zeile befasst sich mit den Labels, die dem Container zugewiesen werden sollen. Diese sind wichtig, da sie es dem nachfolgenden LetsEncrypt-Container ermöglichen, den Proxy-Container zu identifizieren.</p><pre><code>    labels:
      com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: true
</code></pre><p>Anschließend legen wir den Namen des Containers fest.</p><pre><code>    container_name: proxy
</code></pre><p>Im Abschnitt networks tragen wir den Namen des Netzwerkes ein, welches wir im Vorhinein erstellt haben. Durch diese Angabe wird der Container mit dem benannten Netzwerk verbunden.</p><pre><code>    networks:
      - proxy_network
</code></pre><p>Um den Container von außen erreichbar zu machen, ist es wichtig, den Port 80 freizugeben, da er für eine HTTP-Verbindung erforderlich ist. Auf diese Weise kann LetsEncrypt das Ziel erreichen und ein gültiges Zertifikat erstellen. Über den Port 443 wird die verschlüsselte HTTPS Verbindung aufgebaut.</p><pre><code>    ports:
      - 80:80
      - 443:443
</code></pre><p>Damit der Proxy unter anderem seine Konfiguration speichern und auf die generierten Zertifikate Zugriff hat, werden dem Container entsprechende Ordner bereitgestellt. Damit ist sichergestellt, dass diese auch nach dem beenden der Container weiter verfügbar sind.</p><pre><code>    volumes:
      - /var/proxy/vhost.d:/etc/nginx/vhost.d:ro
      - /var/proxy/html:/usr/share/nginx/html:rw
      - /var/proxy/certs:/etc/nginx/certs:ro
      - /var/proxy/conf/:/etc/nginx/conf.d/
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
</code></pre><p>Abschließend wird die Neustart Richtlinie des Container definiert. Diese definiert, dass der Container immer wieder neu gestartet wird, außer er wird manuell oder durch einen Fehler gestoppt. </p><pre><code>    restart: unless-stopped
</code></pre>								</div>
				</div>
				<div class="elementor-element elementor-element-177d89c elementor-widget elementor-widget-heading" data-id="177d89c" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">letsencrypt</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-ed4d7e7 elementor-widget elementor-widget-text-editor" data-id="ed4d7e7" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Analog dem ersten Container werden wir nachfolgend die entsprechenden Abschnitte erklären. Um Zertifikate von Let´s Encrypt zu erstellen, verwenden wir das Image von nginxproxy.</p><pre><code>  letsencrypt:
    image: nginxproxy/acme-companion
</code></pre><p>Diese Option definiert eine Abhängigkeit zum vorherigen Container, womit definiert wird, dass der Let´s Encrypt Container nach dem Proxy Container gestartet werden soll. </p><pre><code>    depends_on:
      - nginx-proxy
</code></pre><p>Anschließend legen wir den Namen des Containers fest.</p><pre><code>    container_name: proxy-acme
</code></pre><p>Im Abschnitt <em>networks</em> tragen wir analog aus dem Proxy Abschnitt das zuvor erstelle Netzwerk ein.</p><pre><code>    networks:
      - proxy_network
</code></pre><p>Damit der Let´s Encrypt Container die Konfiguration des Proxys lesen und die generierten Zertifikate speichern kann, wird dem Container die entsprechenden Ordner bereitgestellt. </p><pre><code>    volumes:
      - /var/proxy/vhost.d:/etc/nginx/vhost.d:rw
      - /var/proxy/html:/usr/share/nginx/html:rw
      - /var/proxy/certs:/etc/nginx/certs:rw
      - /var/proxy/acme:/etc/acme.sh
      - /var/proxy/conf/:/etc/nginx/conf.d/
      #- /var/proxy/acme_config/standalone.sh:/app/letsencrypt_user_data:ro # ggf. für die nächsten Abschnitte notwendig
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
</code></pre><p>Standardmäßig erneuert der Container die Zertifikate 30 Tage vor Ablauf. Um eine Benachrichtigung per E-Mail zu erhalten, falls ein Zertifikat doch nicht korrekt erneuert wird, wird die nachfolgende Variable benutzt. Hier könnt ihr eure E-Mail Adresse eintragen.</p><pre><code>    environment:
      - DEFAULT_EMAIL=EMAIL-ADRESSE
</code></pre><p>Gleichermaßen wie bei dem Proxy ist auch hier die Neustart Richtlinie definiert.</p><pre><code>    restart: unless-stopped
</code></pre><div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex items-start overflow-x-auto whitespace-pre-wrap break-words flex-col gap-4"><div class="markdown prose w-full break-words dark:prose-invert light"><p>In den beiden Containern haben wir das zuvor erstellte Proxy-Netzwerk verwendet. Um sicherzustellen, dass Docker Compose erkennt, dass es sich um ein extern erstelltes Netzwerk handelt, muss dieses zusätzlich global in die Compose-Datei eingebunden werden.</p></div></div></div><pre><code>networks:
  proxy_network:
    external:
      name: proxy_network</code></pre>								</div>
				</div>
				<div class="elementor-element elementor-element-228fc35 elementor-widget-divider--view-line elementor-widget elementor-widget-divider" data-id="228fc35" data-element_type="widget" data-e-type="widget" data-widget_type="divider.default">
				<div class="elementor-widget-container">
							<div class="elementor-divider">
			<span class="elementor-divider-separator">
						</span>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-6c31f9d elementor-widget elementor-widget-text-editor" data-id="6c31f9d" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Die vollständige Datei kannst du <a href="https://tekkieninja.de/wp-content/uploads/2023/08/proxy-compose.yaml">hier</a> herunterladen.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-49128a4 elementor-widget elementor-widget-heading" data-id="49128a4" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Docker Compose Stack starten</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-245e252 elementor-widget elementor-widget-text-editor" data-id="245e252" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Die obige Datei kannst du herunterladen und speichere diese z.B. unter dem Namen <em>proxy-compose.yml</em> ab. Anschließend kannst du den Stack mittels folgendem Befehl starten:</p><p style="padding-left: 40px;"><code>docker-compose --compatibility -f /PFAD/ZUR/COMPOSE/DATEI up -d</code></p><p>Die Container laufen im Hintergrund, damit kannst du den Reverse Proxy verwenden.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-ea44649 elementor-widget elementor-widget-heading" data-id="ea44649" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Konfiguration des Reverse Proxy in Docker mit Let´s Encrypt Zertifikaten</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-c6fc835 elementor-widget elementor-widget-heading" data-id="c6fc835" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Mehrere Container unter einer Domain (Multipath)</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-ea14222 elementor-widget elementor-widget-text-editor" data-id="ea14222" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Möchtest du mehrere Container unter einer einzigen Domain erreichen, beispielsweise <em>tekkie.ninja/app1, tekkie.ninja/app2</em> oder einfach nur <em>tekkie.ninja</em>? <br />Dieses Ziel lässt sich wie folgt realisieren: Du erstellst eine Docker-Compose-Datei, in der die entsprechenden Container Zugriff auf das Proxy-Netzwerk haben. Der Standardcontainer, der aufgerufen wird, wenn <em>tekkie.ninja</em> aufgerufen wird, erhält die Umgebungsvariable VIRTUAL_HOST=&#8230;. Anschließend erzeugst du im Verzeichnis <em>vhost.d</em> eine Datei mit dem gleichen Namen wie die im Compose-File angegebene Domain. In dieser Datei gibst du die verschiedenen Pfade an und verweist auf die entsprechenden Container.</p><p>Ein Beispiel für eine solche Datei sieht wie folgt aus:</p><p style="padding-left: 40px;"><code>location /app1 {<br />    proxy_pass http://app1:8000;<br />}</code></p><p style="padding-left: 40px;"><code><br />location /app2 {<br />    proxy_pass http://app2:8000;<br />}</code></p><p>Dabei muss der Name des Containers die in der URL definierte app1 bzw. app2 ersetzen. Der Pfad wird entsprechend auf die Containernamen angepasst.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-36cfdd9 elementor-widget elementor-widget-heading" data-id="36cfdd9" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Weiterleitung einer Domaine</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-1affb2c elementor-widget elementor-widget-text-editor" data-id="1affb2c" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-3 overflow-x-auto whitespace-pre-wrap break-words"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Wenn du beabsichtigst, eine Domain über einen Reverse Proxy mit einem SSL-Zertifikat zu betreiben, ohne sie direkt auf einen Container abzubilden, sind einige Schritte erforderlich. Abhängig vom Pfad deiner Compose-Datei ist es notwendig, eine separate *.conf-Datei in dem Konfigurationsverzeichnis des Proxys, laut obigen Beispiel <em>/var/proxy/conf</em>, zu erstellen.</p><p>Innerhalb dieser Konfigurationsdatei legst du verschiedene Parameter fest, darunter den Domänennamen, die IP-Adresse zusammen mit dem Port sowie den Pfad zu den Zertifikaten und Schlüsseln. Die markierten Abschnitte in der Datei müssen individuell an den jeweiligen Anwendungsfall angepasst werden. Für nähere Informationen zur Beschaffung eines Zertifikates empfiehlt es sich, den Abschnitt &#8222;SSL-Zertifikat ohne zugehörigen Docker-Container&#8220; zu konsultieren.</p></div></div></div><p style="padding-left: 40px;"><code># Specify domain to be forwarded<br />upstream <span style="color: #1bae70;">domainName</span> {<br />    server <span style="color: #1bae70;">IP_ADRESS:PORT</span>;<br />}<br />server {<br />            server_name <span style="color: #1bae70;">domainName</span>;<br />            listen 80 ;<br />            access_log /var/log/nginx/access.log;<br />            # Do not HTTPS redirect Let'sEncrypt ACME challenge<br />            location ^~ /.well-known/acme-challenge/ {<br />                    auth_basic off;<br />                    auth_request off;<br />                    allow all;<br />                    root /usr/share/nginx/html;<br />                    try_files $uri =404;<br />                    break;<br />        }<br />            location / {<br />                        return 301 https://$host$request_uri;<br />                }<br />}<br />server {<br />            server_name <span style="color: #1bae70;">domainName</span>;<br />            listen 443 ssl http2 ;<br />            access_log /var/log/nginx/access.log;<br />            ssl_session_timeout 5m;<br />            ssl_session_cache shared:SSL:50m;<br />            ssl_session_tickets off;<br />            ssl_certificate <span style="color: #1bae70;">/PATH/TO/domainName.crt</span>;<br />            ssl_certificate_key <span style="color: #1bae70;">/PATH/TO/domainName.key</span>;<br />            ssl_dhparam <span style="color: #1bae70;">/PATH/TO/domainName.dhparam.pem</span>;<br />            ssl_stapling on;<br />            ssl_stapling_verify on;<br />            ssl_trusted_certificate <span style="color: #1bae70;">/PATH/TO/domainName.chain.pem</span>;<br />            add_header Strict-Transport-Security "max-age=31536000" always;<br />            include /etc/nginx/vhost.d/default;<br />            location / {<br />                        proxy_pass http://<span style="color: #1bae70;">domainName</span>;<br />                }<br />}</code></p><p>Die Datei kann <a href="https://tekkieninja.de/wp-content/uploads/2023/08/domainName.conf">hier</a> heruntergeladen werden.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-8714a6f elementor-widget elementor-widget-heading" data-id="8714a6f" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">SSL-Zertifikat ohne zugehörigen Docker-Container</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-64671b8 elementor-widget elementor-widget-text-editor" data-id="64671b8" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-3 overflow-x-auto whitespace-pre-wrap break-words"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Um SSL-Zertifikate unabhängig von Containern zu generieren, benötigt der ACME-Container Zugriff auf das Konfigurationsverzeichnis des Reverse-Proxy sowie auf die Docker-Sockets, wie in der Docker Compose-Datei angegeben.</p><p>Des Weiteren wird eine Datei in das Verzeichnis /app/letsencrypt_user_data eingebunden. Diese Datei ist eine ausführbare Bash-Datei und enthält z.B. folgenden Inhalt:</p><p style="padding-left: 40px;"><code>LETSENCRYPT_STANDALONE_CERTS=('web' 'app' 'tekkie')</code><br /><code>LETSENCRYPT_web_HOST=('yourdomain.de' 'www.yourdomain.de')</code><br /><code>LETSENCRYPT_app_HOST=('yourdomain.de' 'myapp.yourotherdomain.de' 'service.yourotherdomain.tld')</code><br /><code>LETSENCRYPT_tekkie_HOST=('tekkieninja.de')</code></p><p>Dabei werden in der ersten Zeile verschiedene Zertifikate als Gruppe definiert. Dieser Gruppe können dann mehrere Domainnamen zugewiesen werden, wofür das Zertifikat gelten soll.</p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-2124793 elementor-widget elementor-widget-heading" data-id="2124793" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Befehlsergänzungen</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-1acf7ff elementor-widget elementor-widget-heading" data-id="1acf7ff" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">Proxy Container</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-822d98a elementor-widget elementor-widget-text-editor" data-id="822d98a" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Um die Konfiguration neu zu laden, wird folgender Befehl verwendet:</p><p style="padding-left: 40px;"><code>docker exec -ti proxy nginx -s reload</code></p>								</div>
				</div>
				<div class="elementor-element elementor-element-213e058 elementor-widget elementor-widget-heading" data-id="213e058" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default"> ACME Container</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-ac44a65 elementor-widget elementor-widget-text-editor" data-id="ac44a65" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Um die Zertifikatsprüfung erneut auszulösen, wird folgender Befehl verwendet:</p><p style="padding-left: 40px;"><code>docker exec proxy-acme /app/signal_le_service</code></p><p>Um die Erneuerung der Zertifikate zu erzwingen, nutzen wir den folgenden Befehl:</p><p style="padding-left: 40px;"><code>docker exec proxy-acme /app/force_renew</code></p>								</div>
				</div>
				<div class="elementor-element elementor-element-c170c0b elementor-widget elementor-widget-heading" data-id="c170c0b" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Offizielle Dokumentation</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-a5edb22 elementor-widget elementor-widget-text-editor" data-id="a5edb22" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Die offizielle Dokumentation von <em>jwilder</em> kannst du <a href="https://github.com/nginx-proxy/acme-companion/tree/main/docs">hier</a> finden.</p>								</div>
				</div>
				</div>
				</div>
		<p>Der Beitrag <a href="https://tekkieninja.de/reverse-proxy-in-docker-mit-lets-encrypt-zertifikaten/">Reverse Proxy in Docker mit Let&#8217;s Encrypt-Zertifikaten</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tekkieninja.de/reverse-proxy-in-docker-mit-lets-encrypt-zertifikaten/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Docker (-Compose) installieren</title>
		<link>https://tekkieninja.de/docker-compose-installieren/</link>
					<comments>https://tekkieninja.de/docker-compose-installieren/#respond</comments>
		
		<dc:creator><![CDATA[Florian Keßler]]></dc:creator>
		<pubDate>Sun, 23 Apr 2023 14:00:00 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<guid isPermaLink="false">https://tekkieninja.de/?p=1115</guid>

					<description><![CDATA[<p>In dem folgenden Artikel werde ich Schritt für Schritt erklären wie man Docker (-Compose) installieren kann und was es zu Beachten gilt. Bei der Recherche wie man Docker installiert fällt auf, dass oft von Docker-ce oder Docker-io die Rede ist. Beide Varianten beinhalten dasselbe Docker, aber auf unterschiedliche Weise. Docker-io geht nach dem Ansatz von [&#8230;]</p>
<p>Der Beitrag <a href="https://tekkieninja.de/docker-compose-installieren/">Docker (-Compose) installieren</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="1115" class="elementor elementor-1115">
				<div class="elementor-element elementor-element-57b9da2 e-con-full e-flex e-con e-parent" data-id="57b9da2" data-element_type="container" data-e-type="container">
				<div class="elementor-element elementor-element-c230ac3 elementor-widget elementor-widget-text-editor" data-id="c230ac3" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>In dem folgenden Artikel werde ich Schritt für Schritt erklären wie man Docker (-Compose) installieren kann und was es zu Beachten gilt.</p><p>Bei der Recherche wie man <a href="https://tekkieninja.de/was-ist-docker/">Docker</a> installiert fällt auf, dass oft von Docker-ce oder Docker-io die Rede ist. Beide Varianten beinhalten dasselbe Docker, aber auf unterschiedliche Weise. Docker-io geht nach dem Ansatz von Ubuntu/Debian und hat Paketabhängigkeiten, die separat installiert und aktualisiert werden können. Docker-ce hingegen lädt alle Abhängigkeiten separat herunter und enthält somit separate Bibliotheken. Im Folgenden werde ich beide Varianten der Installation von Docker zeigen, empfehle aber die Docker-io Version.</p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-2ca7b7b elementor-widget elementor-widget-heading" data-id="2ca7b7b" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Docker-io</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-c42ef2b elementor-widget elementor-widget-text-editor" data-id="c42ef2b" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Alte Docker Versionen können mit folgendem Befehl deinstalliert werden:</p><p style="padding-left: 40px;"><code>sudo apt-get remove docker docker-engine docker.io</code></p><p>Zunächst müssen die Paketlisten aktualisiert werden:</p><p style="padding-left: 40px;"><code>sudo apt-get update</code></p><p>Mit folgendem Befehl kann man Docker installieren:</p><p style="padding-left: 40px;"><code>sudo apt install docker.io<br /></code></p><p>Nach erfolgreicher Installation starten wir den Docker Daemon und tragen ihn in den Autostart ein, sodass Docker bei jedem Systemstart automatisch gestartet wird:</p><p style="padding-left: 40px;"><code>sudo systemctl start docker</code><br /><code>sudo systemctl enable docker</code></p><p>Um zu überprüfen, ob Docker erfolgreich installiert wurde, kann folgender Befehl ausgeführt werden:</p><p style="padding-left: 40px;"><code>docker version</code></p>								</div>
				</div>
				<div class="elementor-element elementor-element-dd0683b elementor-widget elementor-widget-heading" data-id="dd0683b" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Docker-ce</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-fce543b elementor-widget elementor-widget-text-editor" data-id="fce543b" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Analog zu Docker-io  müssen zunächst die Paketlisten aktualisiert werden:</p><p style="padding-left: 40px;"><code>sudo apt-get update</code></p><p>Als nächstes werden ein paar Voraussetzungen installiert, damit apt Pakete über HTTPS verwenden kann:</p><p style="padding-left: 40px;"><code><i>sudo apt-get install apt-transport-https ca-certificates curl software-properties-common gnupg-agent</i></code></p><p>Anschließend wird der GPG-Schlüssel für das offizielle Docker-Repository dem System hinzugefügt:</p><p style="padding-left: 40px;"><code><i>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -</i></code></p><p>Danach kann das Docker-Repository zu den APT Quellen hinzugefügt werden. Allerdings muss hier der grün markierte Teil durch die aktuell installierte Ubuntu Version ausgetauscht werden:</p><p style="padding-left: 40px;"><code><i>sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu <span style="color: #1bae70;">jammy </span>stable"</i></code></p><ul><li>Ubuntu 18.04 == bionic</li><li>Ubuntu 20.04 == focal</li><li>Ubuntu 22.04 == jammy</li></ul><p>Danach müssen die Paketquellen erneut aktualisiert werden:</p><p style="padding-left: 40px;"><code>sudo apt-get update</code></p><p>Nach der Aktualisierung der Quellen kann Docker-ce installiert werden:</p><p style="padding-left: 40px;"><code><i>sudo apt-get install docker-ce</i></code></p><p>Um zu überprüfen, ob Docker erfolgreich installiert wurde, kann folgender Befehl ausgeführt werden:</p><p style="padding-left: 40px;"><code>docker version</code></p>								</div>
				</div>
				<div class="elementor-element elementor-element-e9ab4df elementor-widget elementor-widget-heading" data-id="e9ab4df" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Docker Compose installieren</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-1511ff1 elementor-widget elementor-widget-text-editor" data-id="1511ff1" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Bevor Docker Compose installiert werden kann, muss die letzte stabile Version ermitttelt werden. Die unterschiedlichen Versionen können unter der <a href="https://github.com/docker/compose/releases">Versionswebsite</a> gefunden werden.</p><p>Nachfolgend wird mit der Version <span class="f1 text-bold d-inline mr-3" data-view-component="true"><a class="Link--primary" href="https://github.com/docker/compose/releases/tag/v2.17.3" data-view-component="true" data-turbo-frame="repo-content-turbo-frame">v2.17.3</a></span> gearbeitet. Sollte eine andere Version installiert werden, so muss nachfolgend ausschließlich die Versionsnummer ausgetauscht werden:</p><p style="padding-left: 40px;"><code>sudo curl -L "https://github.com/docker/compose/releases/download/v2.17.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose</code></p><p>Mit diesem Befehl wird die gewünschte Docker Compose Version heruntergeladen. Um die Dateien ausführbar zu machen, wird folgender Befehl verwendet:</p><p style="padding-left: 40px;"><code>sudo chmod +x /usr/local/bin/docker-compose</code></p><p>Eine erfolgreiche Installation von Docker Compose kann wie folgt überprüft werden:</p><p style="padding-left: 40px;"><code>docker-compose --version</code></p><p>Ihr wollt mehr über Docker-Compose erfahren? In dem <a href="https://tekkieninja.de/docker-compose-erklaert/">verlinkten</a> Beitrag habe ich eine Einführung für dieses Thema verfasst.</p>								</div>
				</div>
				</div>
				</div>
		<p>Der Beitrag <a href="https://tekkieninja.de/docker-compose-installieren/">Docker (-Compose) installieren</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tekkieninja.de/docker-compose-installieren/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Docker-Compose erklärt</title>
		<link>https://tekkieninja.de/docker-compose-erklaert/</link>
					<comments>https://tekkieninja.de/docker-compose-erklaert/#comments</comments>
		
		<dc:creator><![CDATA[Florian Keßler]]></dc:creator>
		<pubDate>Sun, 23 Apr 2023 11:55:19 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<guid isPermaLink="false">https://tekkieninja.de/?p=1091</guid>

					<description><![CDATA[<p>Docker Compose ermöglicht es, mehrere Container in einer einzigen Datei zu definieren und ihre Beziehungen untereinander zu definieren. Mit einem einzigen Befehl können dann alle Container gestartet werden. Dies ist besonders praktisch, da die Datei einfach geteilt werden kann, um eine einheitliche Serverumgebung zu gewährleisten. Warum müssen verschiedene Container eigentlich miteinander verknüpft werden? Ein Docker-Container [&#8230;]</p>
<p>Der Beitrag <a href="https://tekkieninja.de/docker-compose-erklaert/">Docker-Compose erklärt</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="1091" class="elementor elementor-1091">
				<div class="elementor-element elementor-element-833cfb7 e-con-full e-flex e-con e-parent" data-id="833cfb7" data-element_type="container" data-e-type="container">
				<div class="elementor-element elementor-element-20ddbb8 elementor-widget elementor-widget-text-editor" data-id="20ddbb8" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Docker Compose ermöglicht es, mehrere Container in einer einzigen Datei zu definieren und ihre Beziehungen untereinander zu definieren. Mit einem einzigen Befehl können dann alle Container gestartet werden. Dies ist besonders praktisch, da die Datei einfach geteilt werden kann, um eine einheitliche Serverumgebung zu gewährleisten.</p><p>Warum müssen verschiedene Container eigentlich miteinander verknüpft werden? Ein Docker-Container ist von Natur aus isoliert, es können keine Verbindungen nach außen oder nach innen aufgebaut werden. Es ist jedoch oft notwendig, dass Container miteinander kommunizieren müssen, zum Beispiel ein Webserver mit einer Datenbank oder ein Container mit dem Hostcomputer, auf dem er gestartet wurde.</p><p>Die Verknüpfung ermöglicht uns, bestimmte Ports freizugeben, um eine Verbindung von außen zu ermöglichen oder ein bestimmtes Verzeichnis mit dem Hostsystem zu teilen. Bei nur zwei Containern ist das noch einfach, aber in einer typischen Webumgebung müssen mehrere Container miteinander kommunizieren, wie zum Beispiel ein Webserver (z.B. Apache2), PHP und eine Datenbank.</p><p>Es wird schwierig, den Überblick über all diese verschiedenen Tools zu behalten. Docker Compose hilft uns, dies ganz einfach zu orchestrieren, auch wenn wir noch viele weitere Tools wie NodeJS, Cacheserver und Load Balancer hinzufügen.</p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-bc5d806 elementor-widget elementor-widget-heading" data-id="bc5d806" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Docker-Compose Dateiformat .yaml</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-de09d2e elementor-widget elementor-widget-text-editor" data-id="de09d2e" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Der zentrale Bestandteil von Docker Compose ist die YAML-Datei. In dieser Datei werden die Container definiert, die gestartet werden sollen, sowie ihre Beziehungen zueinander. Es können Verzeichnisse freigegeben, Ports freigeschaltet und Verknüpfungen hergestellt werden.</p><p>Auf der ersten Ebene der Datei werden die Namen der einzelnen Container festgelegt. Diese sind wichtig, da sie als Referenz auf andere Container verwendet werden können. In der nächsten Ebene werden die Eigenschaften jedes Containers beschrieben, von denen einige im Folgenden näher erläutert werden. Nachfolgend ein Beispiel:</p><p style="padding-left: 40px;"><code>container1:</code><br /><code>  image: image1</code></p><p style="padding-left: 40px;"><code>container2:</code><br /><code>  image: image2</code></p><p>Dieses Beispiel würde zwei Container starten, die jedoch nichts Besonderes tun würden, außer möglicherweise ihre definierten Images auszuführen. Um die Sache spannender zu gestalten, wird nachfolgend auf die verschiedenen Optionen von Docker-Compose eingegangen.</p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-68ad083 elementor-widget elementor-widget-heading" data-id="68ad083" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft image</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-3e8cde0 elementor-widget elementor-widget-text-editor" data-id="3e8cde0" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Zunächst wird die wichtigste Eigenschaft betrachtet: <strong>image</strong>. Mit dieser Eigenschaft legen wir fest, auf welchem Docker-Image ein Container aufbauen soll. Docker sucht nach dem angegebenen Image im <a href="https://hub.docker.com/search?q=">Docker-Hub</a>, lädt es herunter und startet von diesem aus einen Container automatisch. Da viele moderne Tools (wie Webserver etc.) bereits vorgefertigte Docker-Images bereitstellen, kann damit viel Arbeit erspart werden.</p><p>Ein Beispiel wäre nachfolgend (analog zu dem obigen):</p><p style="padding-left: 40px;"><code>apache2:</code><br /><code>  image: httpd</code></p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-5b2d1ac elementor-widget elementor-widget-heading" data-id="5b2d1ac" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft build</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-7893b9e elementor-widget elementor-widget-text-editor" data-id="7893b9e" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Im Vergleich zu image stellt <strong>Build</strong> das Gegenstück dar, wobei beide Eigenschaften exklusiv sind, das heißt, ein Container kann nur eine von beiden haben. Hier wird der Pfad zum <a href="https://tekkieninja.de/dockerfile/">Dockerfile</a> angegeben &#8211; relativ zum Ort der docker-compose.yml Datei &#8211; das beim Starten des Containers ausgeführt werden soll. Mit dieser Eigenschaft ist es möglich, alle Container individuell anzupassen, indem für jeden ein eigenes Dockerfile angeben wird. Wenn sich das Dockerfile im selben Verzeichnis wie die docker-compose.yml Datei befindet, geben wir einfach einen &#8222;.&#8220; an. Wenn das Dockerfile einen anderen Namen hat, kann der Name mit der Eigenschaft &#8222;dockerfile&#8220; geändert werden.</p><p><span style="text-decoration: underline;">Beispiel:</span></p><p style="padding-left: 40px;"><code>apache2:</code><br /><code>  build: ./apache2</code></p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-1ab789a elementor-widget elementor-widget-heading" data-id="1ab789a" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft  ports</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-57dad56 elementor-widget elementor-widget-text-editor" data-id="57dad56" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Die Eigenschaft <strong>ports</strong> öffnet die angegebenen Ports in einem Container und verbindet sie mit einem Port auf dem Host. Dies ermöglicht es, dass zwei Programme, die denselben Port benutzen, auf demselben Server laufen können, indem man einem Programm einen anderen Port auf dem Host zuweist als dem anderen. Es gibt verschiedene Schreibweisen für diese Eigenschaft:</p><ul><li>Eine einzelne Zahl öffnet einen einzelnen Port, und falls für den Host kein Port angegeben ist, wird ein zufälliger Port bestimmt.</li><li>Mit Doppelpunkten getrennte Zahlen mappen Ports von dem Host System in den Container.</li><li>Mit Bindestrich getrennte Zahlen öffnen eine Reihe von Ports.</li></ul><p>Diese Eigenschaft ist nützlich, wenn Programme wie Webserver oder MariaDB in einem Container ausgeführt werden sollen und andere Container darauf zugreifen müssen. Dabei müssen die entsprechenden Ports, wie beispielsweise 80/443 für den Webserver oder 3306 für MariaDB, freigegeben werden.</p><p><span style="text-decoration: underline;">Beispiel:</span></p><p style="padding-left: 40px;"><code>apache2:</code><br /><code>  image: httpd</code><br /><code>  ports: </code><br /><code>   - 80:80</code><br /><code>   - 443:443</code></p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-457fca4 elementor-widget elementor-widget-heading" data-id="457fca4" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft volumes</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-3b5dda4 elementor-widget elementor-widget-heading" data-id="3b5dda4" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">interne Volumes</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-755acd9 elementor-widget elementor-widget-text-editor" data-id="755acd9" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Durch die <strong>volumes</strong>-Eigenschaft können Verzeichnisse (oder auch mehrere) vom Host im Container zugänglich gemacht werden. Der Pfad auf dem Host, wo das Verzeichnis zu finden ist, wird einfach angegeben. Optional kann auch ein Pfad angegeben werden, auf den das Verzeichnis im Container gemappt werden soll. Änderungen, die auf einer Seite vorgenommen werden (z. B. im Container), sind automatisch auch auf der anderen Seite (auf dem Host) verfügbar. Dies ist eine einfache Möglichkeit, Datenkonsistenz zu gewährleisten, da normalerweise Daten, die in einem Container gespeichert sind, beim beenden des Containers gelöscht werden. Wenn sie jedoch über ein solches Volume auf dem Hostrechner gespeichert werden, bleiben sie auch nach einem Container-Neustart erhalten.</p><p><span style="text-decoration: underline;">Beispiel:</span></p><p style="padding-left: 40px;"><code>apache2:</code><br /><code>  image: httpd</code><br /><code>  volumes: </code><br /><code>   - /var/project_Blog/html:/var/www/html</code></p>								</div>
				</div>
				<div class="elementor-element elementor-element-382c458 elementor-widget elementor-widget-heading" data-id="382c458" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">externe Volumes</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-c61a7ee elementor-widget elementor-widget-text-editor" data-id="c61a7ee" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Das Verwenden eines externen Volumes unterscheidet sich sowohl in der Anwendung als auch darin, dass es zuvor angelegt werden muss. Ein externes Volume bleibt auch nach dem Beenden des Containers erhalten. Alle Volumes werden unter <em>/var/lib/docker/volumes/VOLUME-NAME</em> abgelegt.</p><p><span style="text-decoration: underline;">Beispiel:</span></p><p>Zunächst wird ein externes Volume für MariaDB erstellt. Im Anschluss wird eine Docker Compose Datei gezeigt, die demonstriert, wie das externe Volume eingebunden wird.</p><p><code>docker volume create mariadbV1</code></p><p>Details zu dem gerade erstellten Volume kann mittels folgendem Befehl angezeigt werden:</p><p><code>docker volume inspect mariadbV1</code><code></code></p><p><code>version: '3'</code></p><p><code>services:</code><br /><code>  mariadb:</code><br /><code>    image: mariadb</code><br /><code>    container_name: mariadb</code><code></code><br /><code>    ports:</code><br /><code>      - 3306:3306</code><br /><code>    volumes:</code><br /><code>      - mariadb:/var/lib/mysql</code></p><p><code>volumes:</code><br /><code>    mariadb:</code><br /><code>     external: true</code><br /><code>     name:</code><br /><code>        mariadbV1</code></p>								</div>
				</div>
				<div class="elementor-element elementor-element-d78aa33 elementor-widget elementor-widget-heading" data-id="d78aa33" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">volumes_from</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-3225e4e elementor-widget elementor-widget-text-editor" data-id="3225e4e" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Die Eigenschaft <strong>volumes_from</strong> ähnelt sehr der vorherigen, ist jedoch nicht identisch. Sie ermöglicht es uns, alle Volumes, die wir in einem anderen Container haben, in diesen Container zu übernehmen. Das ist äußerst praktisch, um immer Zugriff auf dieselben Daten zu haben. Das ist zum Beispiel wichtig, wenn wir einen Container für einen Webserver und einen weiteren für PHP haben. Beide benötigen Zugriff auf die PHP-Dateien. Hier wird der Name des Containers angegeben, wie in der docker-compose.yml Datei.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-f237654 elementor-widget elementor-widget-heading" data-id="f237654" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft container Name</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-fd2a0da elementor-widget elementor-widget-text-editor" data-id="fd2a0da" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Durch die Verwendung von <strong>container_name</strong> kann einem Docker-Container ein spezifischer Name zugewiesen werden. Das ist besonders nützlich, wenn viele Container gleichzeitig laufen, da sonst zufällige Namen vergeben werden und es schwierig wird, den Überblick zu behalten.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-b938224 elementor-widget elementor-widget-heading" data-id="b938224" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft networks</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-3dde70d elementor-widget elementor-widget-heading" data-id="3dde70d" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">Allgemeine Verwendung</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-f064c47 elementor-widget elementor-widget-text-editor" data-id="f064c47" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Um Container miteinander zu verknüpfen, wird dies in Netzwerken realisiert. Netzwerke sind vergleichbar mit einem lokalen Netzwerk zu Hause, wo die einzelnen Geräte miteinander kommunizieren können, aber von außen (Internet / Router) nicht zugänglich sind. Ein Beispiel für die Verwendung von Netzwerken sieht folgendermaßen aus. Um Netzwerke nutzen zu können, muss der Block &#8222;networks&#8220; auf der gleichen Ebene wie &#8222;services&#8220; angelegt werden. In diesem Block spezifizieren wir das Netzwerk, das auch von den Containern verwendet werden soll. Hier ist ein Beispiel:</p><p style="padding-left: 40px;"><code>apache2:</code><br /><code>  image: httpd</code><br /><code>  ports: </code><br /><code>   - 80:80</code><br /><code>   - 443:443</code><br /><code>  networks: </code><br /><code>   - NETZWERKNAME</code><br /><code>  volumes:</code><br /><code>   - /var/project_Blog/html:/var/www/html</code></p><p style="padding-left: 40px;"><code>php-fpm:</code><br /><code>  image: php:fpm</code><br /><code>  volumes_from:</code><br /><code>   - </code><code>apache2</code><br /><code>  networks: </code><br /><code>   - NETZWERKNAME</code></p><p style="padding-left: 40px;"><code>network:</code><br /><code>   - NETZWERKNAME:</code></p>								</div>
				</div>
				<div class="elementor-element elementor-element-8eb07af elementor-widget elementor-widget-heading" data-id="8eb07af" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">Spezifische IP-Adressen</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-3a9e44b elementor-widget elementor-widget-text-editor" data-id="3a9e44b" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Um Container spezifische IP-Adressen zuweisen zu können, ist es notwendig, das Subnetz des erstellten Netzwerks festzulegen. Für IPv4-Netzwerke mit einem /29-Präfix sind beispielsweise 6 Clients möglich, wobei die .0-Adresse die Subnetz-Adresse und die letzte Adresse die Broadcast-Adresse ist. Hier ist ein konkretes Beispiel:</p><p style="padding-left: 40px;"><code>version: "3"</code></p><p style="padding-left: 40px;"><code>services:</code><br /><code>  pihole:</code><br /><code>    ...</code><br /><code>    networks:</code><br /><code>      pihole_network:</code><br /><code>        ipv4_address: 10.0.0.1</code></p><p style="padding-left: 40px;"><code></code><code></code><code></code><br /><code>networks:</code><br /><code>  pihole_network:</code><br /><code>    ipam:</code><br /><code>      config:</code><br /><code>        - subnet: 10.0.0.0/29</code></p><p>Gibt man keine spezifische IP-Adresse an, wird dem Container eine zufällige Adresse zugewiesen.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-407798f elementor-widget elementor-widget-heading" data-id="407798f" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft  environment / env_file</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-70175f1 elementor-widget elementor-widget-text-editor" data-id="70175f1" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Durch die Verwendung von Environments können Kommandos innerhalb eines Containers ausgeführt werden. Im nachfolgenden Beispiel wird beim ersten Start des Containers eine Datenbank erstellt, zusammen mit einem Benutzer und einem Passwort für die Datenbank. Es wird auch ein Root-Benutzer für die Datenbank erstellt, da sonst das Bearbeiten oder Erstellen von Datenbanken nicht möglich ist. </p><p><code>version: '3'</code></p><p><code>services:</code><br /><code>  mariadb:</code><br /><code>    image: mariadb</code><br /><code>    container_name: mariadb</code><br /><code>    environment:</code><br /><code>      - MYSQL_ROOT_PASSWORD<i>=---------------</i></code><br /><code>      - MYSQL_PASSWORD<i>=---------------</i></code><br /><code>      - MYSQL_DATABASE<i>=---------------</i></code><br /><code>      - MYSQL_USER<i>=---------------</i></code></p><p>Wenn viele Variablen in einer Compose Datei stehen, kann dies schnell unübersichtlich werden. Außerdem kann es vorkommen, dass die Docker-Compose Datei mit einer anderen Person geteilt werden soll, aber nicht die Zugangsdaten. In einem solchen Fall ist die sogenannte <strong>env_file</strong> Eigenschaft nützlich. Damit können die oben gezeigten Werte in eine Datei ausgelagert werden. Die Datei sollte im gleichen Verzeichnis liegen wie die Compose Datei.</p><p style="padding-left: 40px;"><code>version: '3'</code></p><p style="padding-left: 40px;"><code>services:</code><br /><code>  apache2:</code><br /><code>    image: httpd</code><br /><code>    env_file:</code><br /><code>      - a.env</code><br /><code>      - b.env</code></p><p>Die Datei ist simpel im <em>VAR=VAL</em>-Format aufgebaut. VAR stellt den Variablennamen dar und VAL der entsprechende Wert. Sollten die selben Variablennamen in mehreren Dateien genutzt werden, so wird der letzte Wert aus der letzten Datei als entgültiger angenommen. Dadurch kann die Reihenfolge der Dateien im Compose File eine Rolle spielen.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-9c4137c elementor-widget elementor-widget-heading" data-id="9c4137c" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft restart</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-39ffa7a elementor-widget elementor-widget-text-editor" data-id="39ffa7a" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Um die Neustart-Richtlinie für einen Container zu konfigurieren, kann die Eigenschaft <strong>restart</strong> verwendet werden. Der Wert des kann einer der folgenden sein:</p><ul><li><em>no</em>: Der Container wird nicht automatisch neu gestartet (Standard).</li><li><em>on-failure[:max-retries]</em>: Der Container wird neu gestartet, wenn er aufgrund eines Fehlers mit einem Exit-Code ungleich <em>Null</em> beendet wird. Optional kann mit der Option <em>:max-retries</em> die Anzahl der Versuche des Docker-Dämons begrenzt werden, den Container neu zu starten.</li><li><em>always</em>: Der Container wird immer neu gestartet, wenn er gestoppt wird. Wenn er manuell gestoppt wird, wird er nur neu gestartet, wenn der Docker-Daemon neu gestartet wird oder der Container selbst manuell neu gestartet wird.</li><li><em>unless-stopped</em>: Analog zu <em>always</em>, außer dass der Container nicht neu gestartet wird, wenn er manuell oder anderweitig gestoppt wird, selbst wenn der Docker-Daemon neu gestartet wird.</li></ul>								</div>
				</div>
				<div class="elementor-element elementor-element-d99dc79 elementor-widget elementor-widget-heading" data-id="d99dc79" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft  depends_on</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-b8cb486 elementor-widget elementor-widget-text-editor" data-id="b8cb486" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Um die Beziehungen zwischen den Diensten in Docker Compose auszudrücken, können Abhängigkeiten definiert werden. Diese bestimmen das Start- und Stop-Verhalten der Dienste:</p><ul><li>Wenn man <em>docker-compose up</em> ausführt, werden die Dienste in der Reihenfolge ihrer Abhängigkeiten gestartet. Im Beispiel werden <em>db</em> und <em>redis</em> vor <em>web</em> gestartet.</li><li>Wenn man <em>docker-compose stop</em> ausführt, werden die Dienste in umgekehrter Abhängigkeitsreihenfolge gestoppt. Im Beispiel wird <em>web</em> vor <em>db</em> und <em>redis</em> gestoppt.</li></ul><p><code>version: '3'</code></p><p><code>services:</code><br /><code>  web:</code><br /><code>    image: httpd<br /></code><code>    depends_on:<br /></code><code>      - redis<br />      - db</code></p><p><code></code><code>  redis:</code><br /><code>    image: redis</code></p><p><code>  db:</code><br /><code>    image: mariadb</code></p><p>Aber <strong>ACHTUNG</strong>: <strong>depends_on</strong> wartet nicht darauf, dass db und redis lauffähig sind, bevor der Web-Dienst gestartet wird, sondern nur bis sie gestartet wurden.<br />Wenn man einen Stack im Schwarm-Modus mit einer Compose-Datei der Version 3 bereitstellt, wird die <strong>depends_on</strong>-Option ignoriert.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-70d95e6 elementor-widget elementor-widget-heading" data-id="70d95e6" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Eigenschaft deploy (Schwerpunkt Resourcen)</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-d19f9a6 elementor-widget elementor-widget-text-editor" data-id="d19f9a6" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Um zu verhindern, dass der Kernel des Betriebssystems die Docker Engine bei einem Fehler eines Containers beendet, ist es empfehlenswert, die Ressourcen zu begrenzen. Dies kann durch Hinzufügen von Limits und Reservations in der deploy-Sektion der docker-compose-Datei erreicht werden.</p><p>Die Limits bestimmen die maximale Menge an Ressourcen, die ein Container verwenden kann, während die Reservations eine Mindestmenge an Ressourcen garantieren, die dem Container zur Verfügung stehen.</p><p>Folgende zwei Ressourcen Gruppen können beschränkt werden:</p><ul><li>cpus: Diese Option gibt an, wie viel der verfügbaren CPU-Ressourcen ein Container nutzen kann.</li><li>memory:Diese Option gibt an, wie viel der verfügbaren RAM-Ressourcen ein Container nutzen kann.</li></ul><p>Es ist auch möglich, die Optionen &#8211;cpu-shares und &#8211;memory-swap zu verwenden, um die Ressourcen auf andere Weise zu begrenzen. Weitere Informationen zu diesen Optionen finden in der <a href="https://docs.docker.com/config/containers/resource_constraints/">Docker-Dokumentation</a>.</p><p>Ab Compose Version 3 muss die Docker Engine im Swarm-Modus laufen, damit die Ressourcen Begrenzung greift. Wenn Sie jedoch den Kompatibilitätsmodus verwenden möchten, können Sie den Befehl &#8222;docker-compose &#8211;compatibility&#8220; verwenden. Weitere Informationen dazu sind in der <a href="https://docs.docker.com/config/containers/resource_constraints/">Docker-Dokumentation</a> zu finden.</p><p> </p>								</div>
				</div>
				<div class="elementor-element elementor-element-9eb3161 elementor-widget elementor-widget-heading" data-id="9eb3161" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Grundlegende Befehle</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-2adb4a3 elementor-widget elementor-widget-text-editor" data-id="2adb4a3" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Nach der Vorbereitung unseres docker-compose.yml-Files stellt sich die Frage: Wie starten oder beenden wir die konfigurierten Container? Hier sind einige Befehle, mit denen wir unsere Container verwalten können.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-a4cb2c2 elementor-widget elementor-widget-heading" data-id="a4cb2c2" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">docker-compose up</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-65ed45f elementor-widget elementor-widget-text-editor" data-id="65ed45f" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Der erste Befehl ist <strong>docker-compose up</strong>. Dieser erstellt und startet die Container, die wir in unserem YAML-File definiert haben. Mit diesem einen Befehl können wir also alle unsere Container starten &#8211; genial.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-94d4b7e elementor-widget elementor-widget-heading" data-id="94d4b7e" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">docker-compose build</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-f3033e3 elementor-widget elementor-widget-text-editor" data-id="f3033e3" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Der Befehl <strong>docker-compose build</strong> baut alle Container zusammen und taggt sie, damit sie beim nächsten Start schneller verfügbar sind. Wenn sich also etwas im Build-Verzeichnis oder im Dockerfile ändert, führen wir einfach diesen Befehl aus, um die Änderungen in unserer Docker Compose Umgebung zu integrieren.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-995a71d elementor-widget elementor-widget-heading" data-id="995a71d" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">docker-compose ps</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-8349ddc elementor-widget elementor-widget-text-editor" data-id="8349ddc" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Analog wie <strong>docker ps</strong> listet auch <strong>docker-compose ps</strong> die aktiven Container auf, die von Docker Compose verwaltet werden.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-370044b elementor-widget elementor-widget-heading" data-id="370044b" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">docker-compose start / stop</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-954e987 elementor-widget elementor-widget-text-editor" data-id="954e987" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Mithilfe der Namen, die wir im docker-compose ps Befehl sehen können, können einzelne Container mit den Befehlen <strong>docker-compose start / stop</strong> gestartet bzw. gestoppt werden.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-61bdd87 elementor-widget elementor-widget-heading" data-id="61bdd87" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h5 class="elementor-heading-title elementor-size-default">docker-compose rm</h5>				</div>
				</div>
				<div class="elementor-element elementor-element-6ebf4d5 elementor-widget elementor-widget-text-editor" data-id="6ebf4d5" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Mit dem Namen kann auch ein getaggtrn Container mit dem Befehl <strong>docker-compose rm</strong> entfernt werden. Wenn anschließend docker-compose up ausgeführt wird, dann wird der Container wieder neu erstellt.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-db9c6cf elementor-widget elementor-widget-spacer" data-id="db9c6cf" data-element_type="widget" data-e-type="widget" data-widget_type="spacer.default">
				<div class="elementor-widget-container">
							<div class="elementor-spacer">
			<div class="elementor-spacer-inner"></div>
		</div>
						</div>
				</div>
				<div class="elementor-element elementor-element-c440156 elementor-widget elementor-widget-text-editor" data-id="c440156" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Ich hoffe euch hat dieser Artikel zu Docker-Compose erklären gefallen. Habt Ihr Anmerkungen oder Wünsche? Dann teilt Sie mir gerne mit.</p>								</div>
				</div>
				</div>
				</div>
		<p>Der Beitrag <a href="https://tekkieninja.de/docker-compose-erklaert/">Docker-Compose erklärt</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tekkieninja.de/docker-compose-erklaert/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Dockerfile</title>
		<link>https://tekkieninja.de/dockerfile/</link>
					<comments>https://tekkieninja.de/dockerfile/#respond</comments>
		
		<dc:creator><![CDATA[Florian Keßler]]></dc:creator>
		<pubDate>Fri, 21 Apr 2023 14:01:00 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<guid isPermaLink="false">https://tekkieninja.de/?p=1085</guid>

					<description><![CDATA[<p>Die Verwendung von Docker Images ist ein wichtiger Schritt in Richtung Docker, aber es gibt noch weitere nützliche Funktionen. Eine davon ist das Dockerfile, das es ermöglicht, das Image auf einfache Weise Schritt für Schritt zu erstellen. Es beschreibt, wie die Umgebung aufgebaut werden soll, ähnlich wie in anderen Umgebungen wie Vagrant. Das Dockerfile ist [&#8230;]</p>
<p>Der Beitrag <a href="https://tekkieninja.de/dockerfile/">Dockerfile</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="1085" class="elementor elementor-1085">
				<div class="elementor-element elementor-element-b3f8ce2 e-con-full e-flex e-con e-parent" data-id="b3f8ce2" data-element_type="container" data-e-type="container">
				<div class="elementor-element elementor-element-da0ceb7 elementor-widget elementor-widget-text-editor" data-id="da0ceb7" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Die Verwendung von Docker Images ist ein wichtiger Schritt in Richtung Docker, aber es gibt noch weitere nützliche Funktionen. Eine davon ist das Dockerfile, das es ermöglicht, das Image auf einfache Weise Schritt für Schritt zu erstellen. Es beschreibt, wie die Umgebung aufgebaut werden soll, ähnlich wie in anderen Umgebungen wie Vagrant.</p><p>Das Dockerfile ist eine einfache Textdatei, die den Aufbau des Docker Images beschreibt und als Schritt-für-Schritt-Anleitung fungiert, um das Image immer wieder auf dieselbe Art zu erstellen. Mit einem Dockerfile kann das Image leicht erstellt und Teamkollegen zur Verfügung gestellt werden, damit sie dasselbe Image erzeugen können.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-5d94037 elementor-widget elementor-widget-heading" data-id="5d94037" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Image aus dem Dockerfile erzeugen</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-427eab1 elementor-widget elementor-widget-text-editor" data-id="427eab1" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Um ein fertiges Image aus einem Dockerfile zu erzeugen, müssen wir folgenden Befehl ausführen:</p><p style="padding-left: 40px;"><code>docker build</code></p><p>Dieser Befehl benötigt einen Kontext als Parameter, der das Verzeichnis enthält, in dem sich das Dockerfile befindet. Standardmäßig sucht Docker im Kontextverzeichnis nach der Datei. Wenn ein anderer Speicherort angeben werden soll, kann der Parameter <strong>-f</strong> verwendet werden.</p><p>Wenn ein Image aus dem Dockerfile erstellt werden soll, wird auf der Konsole in das Verzeichnis gewechselt, das das Dockerfile enthält, und geben den folgenden Befehl ein:</p><p style="padding-left: 40px;"><code>docker build -t tekkie/ninja-php-server</code></p><p>Durch die Verwendung des Parameters <strong>-t</strong> kann dem Image, das aus dem Dockerfile erstellt wird, einen Namen zuweisen, der später verwendet werden kann. Der Punkt am Ende steht für das aktuelle Verzeichnis und gibt an, dass das Kontextverzeichnis für das Erstellen des Images verwendet werden soll.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-2e8609f elementor-widget elementor-widget-heading" data-id="2e8609f" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Aufbau eines Dockerfiles</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-6a75093 elementor-widget elementor-widget-text-editor" data-id="6a75093" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Das Dockerfile ist einfach aufgebaut und besteht aus einer einzelnen Befehlszeile pro Zeile. Die Befehle werden durch die Konvention <strong>BEFEHL parameter</strong> getrennt, wobei der Befehl großgeschrieben wird. Kommentare können mit einem <strong>#</strong> am Anfang einer Zeile hinzugefügt werden.</p><p>Beim Bauen des Dockerfiles wird jeder Befehl in jeder Zeile nacheinander ausgeführt, um ein Zwischenimage zu erzeugen. Dieses Zwischenimage dient dann als Basis für den nächsten Befehl. Wenn ein Befehl erfolgreich ausgeführt wird, bleibt das Image erhalten. Das bedeutet, dass Docker beim nächsten Aufruf des build-Befehls an der gleichen Stelle weitermachen kann, solange sich im Dockerfile nichts ändert. Dies ist besonders nützlich, wenn aufwendige Befehle wie die Installation mehrerer Anwendungen ausgeführt werden müssen, da viel Zeit gespart werden kann.</p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-e27bfbe elementor-widget elementor-widget-heading" data-id="e27bfbe" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Befehl FROM</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-b2b4cbc elementor-widget elementor-widget-text-editor" data-id="b2b4cbc" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Der entscheidende Befehl im Dockerfile lautet <strong>FROM</strong> und steht am Anfang. Er definiert klar, welches Image als Basis für das neue Image dienen soll. Dabei kann es sich um ein Basisimage wie <em>ubuntu</em> oder <em>ubuntu:trusty</em> handeln, oder um von Nutzern oder uns selbst erstellte Images wie <em>tekkie/ninja-test-server</em>.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-ac73a3f elementor-widget elementor-widget-heading" data-id="ac73a3f" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Befehl MAINTAINER</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-aa20478 elementor-widget elementor-widget-text-editor" data-id="aa20478" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Mit dem MAINTAINER Befehl kann der Autor des Images gesetzt werden.</p><p style="padding-left: 40px;"><code>MAINTAINER Tekkie Ninja &lt;tekkieninja.blog@gmail.com&gt;</code></p>								</div>
				</div>
				<div class="elementor-element elementor-element-65a0f42 elementor-widget elementor-widget-heading" data-id="65a0f42" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Befehl RUN</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-41756e2 elementor-widget elementor-widget-text-editor" data-id="41756e2" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Einer der wichtigsten Befehle im Dockerfile ist der Befehl <strong>RUN</strong>. Mit diesem können wir den Parameter als Shell Befehl ausführen und damit quasi alles in unserer virtuellen Maschine tun. Der Befehl</p><p style="padding-left: 40px;"><code>RUN sudo apt-get install -y apache2</code></p><p>wird intern wie folgt übersetzt:</p><p style="padding-left: 40px;"><code>/bin/sh -c sudo apt-get install -y apache2</code></p><p>Eine weitere Möglichkeit, den RUN Befehl auszuführen, ist die sogenannte exec Syntax:</p><p style="padding-left: 40px;"><code>RUN [„executable“, „param1“, „param2“]</code></p><p>In den meisten Fällen werden die Dockerfiles eine Verkettung von vielen RUN Befehlen beinhalten. Hier ist es wichtig zu beachten, dass jeder RUN Befehl einen neuen Layer im Image erzeugt und damit Speicher verbraucht. Daher sollten wir die Anzahl der RUN Befehle möglichst gering halten und mehrere Dinge innerhalb eines Befehls erledigen.</p><p><span style="text-decoration: underline;">Negativ Beispiel:</span></p><p style="padding-left: 40px;"><code>RUN sudo apt-get install -y apache2</code></p><p style="padding-left: 40px;"><code>RUN sudo apt-get install -y php8.2</code></p><p style="padding-left: 40px;"><code>RUN sudo apt-get install -y nodejs</code></p><p style="padding-left: 40px;"><code>RUN sudo apt-get install -y npm</code></p><p><span style="text-decoration: underline;">Empfohlene Variante:</span></p><p style="padding-left: 40px;"><code>RUN sudo apt-get install -y apache2 php8.2 nodejs npm</code></p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-8ffecf3 elementor-widget elementor-widget-heading" data-id="8ffecf3" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Befehl CMD</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-64dac9c elementor-widget elementor-widget-text-editor" data-id="64dac9c" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Der Befehl CMD definiert den Standardbefehl, der in einem Container ausgeführt wird, wenn er aus unserem Image erzeugt wird. Es ist jedoch möglich, dass der Container diesen Befehl überschreibt. Ein Docker Image kann nur einen CMD Befehl haben. Wenn mehrere definiert sind, wird nur der letzte Befehl als gültig angesehen. Die Syntax von CMD ist identisch mit der Syntax von RUN.</p><p><span style="text-decoration: underline;">Beispiel:</span></p><p style="padding-left: 40px;"><code>CMD echo "Hello world from Tekkie Ninja"</code></p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-9ff2c3e elementor-widget elementor-widget-heading" data-id="9ff2c3e" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Befehl ADD / COPY</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-80e82eb elementor-widget elementor-widget-text-editor" data-id="80e82eb" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>ADD und COPY sind zwei ähnliche Befehle, wobei ADD etwas mehr Funktionen hat als COPY. Nachfolgend wird nicht näher auf die Unterschiede der beiden Funtkionen eingegangen.</p><p>Beide Befehle ermöglichen es, eine Datei oder ein Verzeichnis vom Host-System in das Dateisystem des Images zu kopieren. Die Syntax ist einfach:</p><p style="padding-left: 40px;"><code>ADD directory /var/www/html/directory</code></p><p>Hier wird zuerst das Verzeichnis oder die Datei angegeben, die kopiert werden soll, und dann das Ziel. Die Syntax für den COPY-Befehl ist identisch. Beide Befehle haben auch eine alternative Syntax, die verwendet werden muss, wenn der Dateiname Leerzeichen enthält:</p><p style="padding-left: 40px;"><code>COPY ["directory", "/var/www/html/directory"]</code></p><p>Dank dieser Befehle können wir Konfigurationsdateien (z.B. die Apache2-Konfiguration oder eine php.ini) in unser neues Image kopieren.</p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-5d20ba8 elementor-widget elementor-widget-heading" data-id="5d20ba8" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h4 class="elementor-heading-title elementor-size-default">Befehl WORKDIR</h4>				</div>
				</div>
				<div class="elementor-element elementor-element-c5a64c8 elementor-widget elementor-widget-text-editor" data-id="c5a64c8" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Jeder Befehl RUN, CMD, ADD und COPY bezieht sich standardmäßig auf das Root-Verzeichnis. Wenn dies geändert werden soll, kann dies mit dem Befehl WORKDIR erfolgen. Dieser setzt das neue Referenzverzeichnis für alle nachfolgenden Befehle fest oder bis zum nächsten Aufruf von WORKDIR.</p><p><span style="text-decoration: underline;">Zum Beispiel:</span></p><p style="padding-left: 40px;"><code>WORKDIR /var/www</code></p><p>Es kann auch ein relativer Pfad angeben werden, der sich am letzten Aufruf von WORKDIR orientiert:</p><p style="padding-left: 40px;"><code>WORKDIR vhosts/<a href="https://tekkieninja.de">tekkieninja.de</a></code></p><p>Nach den beiden oben genannten Befehlen wäre der neue Referenzpfad also <em>var/www/vhosts/<a href="https://tekkieninja.de">tekkieninja.de</a>.</em></p></div></div></div>								</div>
				</div>
				</div>
				</div>
		<p>Der Beitrag <a href="https://tekkieninja.de/dockerfile/">Dockerfile</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tekkieninja.de/dockerfile/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Docker Images</title>
		<link>https://tekkieninja.de/docker-images/</link>
					<comments>https://tekkieninja.de/docker-images/#respond</comments>
		
		<dc:creator><![CDATA[Florian Keßler]]></dc:creator>
		<pubDate>Wed, 19 Apr 2023 13:28:49 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<guid isPermaLink="false">https://tekkieninja.de/?p=990</guid>

					<description><![CDATA[<p>Docker-Images stellen den Zustand eines Containers zu einem bestimmten Zeitpunkt dar. Wenn wir beispielsweise einen Docker-Container mit einem Ubuntu-Image starten, wird es erst einmal nicht viel tun. Wir können darin Apache2 installieren und diesen Zustand speichern. Von nun an wird jeder Container, der von diesem Image gestartet wird, Apache2 enthalten. Auf diese Weise bauen die [&#8230;]</p>
<p>Der Beitrag <a href="https://tekkieninja.de/docker-images/">Docker Images</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="990" class="elementor elementor-990">
				<div class="elementor-element elementor-element-92d98f2 e-con-full e-flex e-con e-parent" data-id="92d98f2" data-element_type="container" data-e-type="container">
				<div class="elementor-element elementor-element-c4aa873 elementor-widget elementor-widget-text-editor" data-id="c4aa873" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Docker-Images stellen den Zustand eines Containers zu einem bestimmten Zeitpunkt dar. Wenn wir beispielsweise einen Docker-Container mit einem Ubuntu-Image starten, wird es erst einmal nicht viel tun. Wir können darin Apache2 installieren und diesen Zustand speichern. Von nun an wird jeder Container, der von diesem Image gestartet wird, Apache2 enthalten. Auf diese Weise bauen die Images aufeinander auf.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-3f2149d elementor-widget elementor-widget-heading" data-id="3f2149d" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Grundlagen</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-0f653ae elementor-widget elementor-widget-text-editor" data-id="0f653ae" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Nehmen wir an, wir haben Apache2 in unserem Image installiert und nennen es &#8222;ninja-apache2-server&#8220;. Jetzt benötigen wir eine Möglichkeit, um eine Webanwendung auf verschiedenen PHP-Versionen zu testen. Wir können ein Image erstellen, das auf &#8222;ninja-apache2-server&#8220; aufbaut und PHP 7.4 installiert, nennen es &#8222;ninja-php74-server&#8220;. Außerdem können wir ein weiteres Docker Image erstellen, das auch auf &#8222;ninja-apache2-server&#8220; aufbaut, aber PHP 8.2 installiert, und nennen es &#8222;ninja-php82-server&#8220;.</p><p>Dies bietet uns mehrere Vorteile:</p><ul><li>Wir können mit einem einfachen &#8222;docker run&#8220;-Befehl blitzschnell virtuelle Maschinen mit verschiedenen PHP-Versionen starten, ohne uns mit mehreren PHP-Versionen innerhalb einer Maschine befassen oder ständig eine andere PHP-Version installieren zu müssen.</li><li>Wenn wir unsere Grundlage ändern möchten (in diesem Fall z.B. die Apache2-Version), können wir dies zentral im &#8222;ninja-apache2-server&#8220;-Image vornehmen, dieses speichern und die darauf aufbauenden Images können diese Änderungen einfach übernehmen. Das spart natürlich viel Zeit, da wir die Änderungen nicht in jeder virtuellen Testmaschine einzeln anpassen müssen.</li></ul><p>Dieses einfache Beispiel zeigt uns bereits den Mehrwert einer gut durchdachten Docker-Entwicklungsumgebung. Stellen wir uns das Ganze in einem echten Webumfeld mit Webserver, Datenbank, PHP, NodeJS, Plugins und ständig vielfältiger werdenden Tools vor, dann verwundert die rasant ansteigende Beliebtheit von Docker nicht mehr. Eine Übersicht aller Images ist unter folgendem <a href="https://hub.docker.com/search?q=">Link</a> einsehbar.</p><p>Zur Zusammensetzung des Namens eines Docker Images dient das folgende Beispiel: &#8222;tekkie/ninja-apache2-server:0.1&#8220;. Der Teil vor dem Schrägstrich (&#8222;tekkie&#8220;) ist der Name bzw. Account des Autors, der das Image hochgeladen hat. Der Teil danach (&#8222;ninja-apache2-server&#8220;) ist der Name des Images selbst. Zusammen bilden diese das sogenannte Repository. Ein Repository kann mehrere Versionen eines Images enthalten. Diese Versionen werden anhand von Tags unterschieden, welche hinter dem Doppelpunkt stehen. Wenn kein Tag angegeben wird, wird automatisch der Tag &#8222;latest&#8220; vergeben. Unser PHP-Beispiel von oben hätten wir auch eleganter lösen können, indem wir ein Image &#8222;ninja-php-server&#8220; erstellen und es mit den Tags &#8222;7.4&#8220; und &#8222;8.2&#8220; versehen.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-6bf0ba5 elementor-widget elementor-widget-heading" data-id="6bf0ba5" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Docker Images Verwaltung</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-f1bb160 elementor-widget elementor-widget-text-editor" data-id="f1bb160" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Zunächst betrachten wir, wie wir herausfinden können, welche Images bereits auf unserem Host installiert sind. Hierfür verwenden wir den Befehl:</p><p style="padding-left: 40px;"><em><code>docker images</code></em></p><p>Falls wir ein bestimmtes Image nicht installiert haben, wird es beim Ausführen von &#8222;docker run&#8220; automatisch heruntergeladen.</p><p>Wenn wir ein Image manuell herunterladen möchten &#8211; möglicherweise, weil wir im Zielnetzwerk keinen Zugriff auf das Internet haben -, können wir dies problemlos mit dem Befehl durchführen:</p><p style="padding-left: 40px;"><em><code>docker pull author/image:tag</code></em></p><p>Zuletzt können wir selbstverständlich auch ein vorhandenes Docker-Image löschen.</p><p style="padding-left: 40px;"><em><code>docker rmi author/image:tag</code></em></p><p>Beachten Sie hierbei das <strong>i</strong> bei <strong>rmi</strong>. Der &#8222;docker rm&#8220;-Befehl ist bereits für das Entfernen von Containern vorgesehen.</p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-b99e87c elementor-widget elementor-widget-heading" data-id="b99e87c" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Docker Images aktualisieren</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-eba6f3c elementor-widget elementor-widget-text-editor" data-id="eba6f3c" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Um ein Docker-Image zu aktualisieren, z.B. wenn eine neue Softwareversion verfügbar ist oder sich die Anforderungen geändert haben, gibt es eine einfache Methode. Zunächst müssen wir einen Container aus dem vorhandenen Image starten (wie bereits im vorherigen Artikel erklärt). Die ID des Containers muss notiert werden, da sie später benötigt wird.</p><p>Dann können alle erforderlichen Änderungen innerhalb des Containers durchgeführt werden, z.B. die Installation von curl mit dem Befehl apt-get install curl.</p><p>Sobald die Installation abgeschlossen ist und alles funktioniert, kann der Container mit exit verlassen werden.</p><p>Jetzt wird die oben erwähnte Container-ID benötigt, um den Befehl</p><p style="padding-left: 40px;"><em><code>docker commit -m "curl installiert" -a "Tekkie Ninja" CONTAINER-ID tekkie/ninja-test-server:1.2</code></em></p><p>auszuführen.</p><p>Dieser etwas längere Befehl kann in seine Einzelteile zerlegt werden:</p><ul><li><strong>docker commit</strong> bedeutet, dass wir ein Image an das Repository senden möchten.</li><li><strong>-m</strong> ermöglicht es uns, einen Kommentar zu diesem Commit hinzuzufügen (wie bei GIT), damit wir später wissen, was wir in welchem Commit geändert haben.</li><li><strong>-a</strong> zeigt den Autor des Commits an, damit wir in einem Team wissen, wer was gemacht hat.</li><li><strong>CONTAINER-ID</strong> ist die zuvor erwähnte ID des Docker-Containers, den wir zuvor verändert haben.</li><li><strong>tekkie/ninja-test-server:1.2</strong> ist der Name, unter dem wir das neue Image speichern möchten (wie bereits oben besprochen).</li></ul></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-3cd41d2 elementor-widget elementor-widget-heading" data-id="3cd41d2" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Docker Images taggen</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-0ff6423 elementor-widget elementor-widget-text-editor" data-id="0ff6423" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Zuletzt gibt es noch einen Befehl, um ein Image nachträglich zu taggen. Wie zuvor erwähnt, wird standardmäßig immer das Tag &#8222;latest&#8220; zugewiesen, aber wir möchten möglicherweise für unsere eigenen Zwecke ein anderes Tag verwenden. Hierfür benötigen wir die ID des Images, die wir mit dem Befehl &#8222;docker images&#8220; in der Image-Liste finden können.</p><p style="padding-left: 40px;"><em><code>docker tag IMAGE-ID tekkie/ninja-test-server:neuerTag</code></em></p></div></div></div>								</div>
				</div>
				</div>
		<div class="elementor-element elementor-element-edd2d23 e-con-full e-flex e-con e-parent" data-id="edd2d23" data-element_type="container" data-e-type="container">
				<div class="elementor-element elementor-element-14279a5 elementor-widget elementor-widget-text-editor" data-id="14279a5" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Im folgenden Artikel werden wir uns genauer mit dem Dockerfile beschäftigen und einen genaueren Blick darauf werfen.</p><p style="text-align: right;">Hier gehts weiter.</p>								</div>
				</div>
				</div>
				</div>
		<p>Der Beitrag <a href="https://tekkieninja.de/docker-images/">Docker Images</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tekkieninja.de/docker-images/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Was sind Docker Container und wie funktionieren sie?</title>
		<link>https://tekkieninja.de/was-sind-docker-container-und-wie-funktionieren-sie/</link>
					<comments>https://tekkieninja.de/was-sind-docker-container-und-wie-funktionieren-sie/#respond</comments>
		
		<dc:creator><![CDATA[Florian Keßler]]></dc:creator>
		<pubDate>Sun, 16 Apr 2023 13:41:12 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<guid isPermaLink="false">https://tekkieninja.de/?p=879</guid>

					<description><![CDATA[<p>Docker Container sind eine der Hauptgründe, warum sich Docker so schnell verbreitet hat. Ein Docker Container ist eine einfach konfigurierbare, abgeschlossene Einheit, in der Anwendungen ausgeführt werden können. Ein Container kann als Frachtcontainer betrachtet werden, in dem sich ein Männchen befindet, das eine bestimmte Aufgabe ausführt. Innerhalb des Containers sieht es immer gleich aus, unabhängig [&#8230;]</p>
<p>Der Beitrag <a href="https://tekkieninja.de/was-sind-docker-container-und-wie-funktionieren-sie/">Was sind Docker Container und wie funktionieren sie?</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="879" class="elementor elementor-879">
				<div class="elementor-element elementor-element-e053b9d e-con-full e-flex e-con e-parent" data-id="e053b9d" data-element_type="container" data-e-type="container">
				<div class="elementor-element elementor-element-4781b2c elementor-widget elementor-widget-text-editor" data-id="4781b2c" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Docker Container sind eine der Hauptgründe, warum sich Docker so schnell verbreitet hat. Ein Docker Container ist eine einfach konfigurierbare, abgeschlossene Einheit, in der Anwendungen ausgeführt werden können. Ein Container kann als Frachtcontainer betrachtet werden, in dem sich ein Männchen befindet, das eine bestimmte Aufgabe ausführt. Innerhalb des Containers sieht es immer gleich aus, unabhängig davon, wo sich der Container gerade befindet. Unabhängig ob auf dem privaten Windows Rechner oder auf einem Server mit einem Linux Betriebssystem. Ein Dockerfile beschreibt den Container so, dass er auf einem anderen Rechner genau gleich aufgebaut werden kann.</p><p>Docker Images sind die Baupläne für Container, die über das zentrale <a href="https://hub.docker.com/search?q=">Docker Hub</a> mit anderen Entwicklern geteilt werden können. Aus den Images werden dann die jeweiligen Container gestartet, vergleichbar mit der objektorientierten Programmierung, wo aus einer Klasse mehrere Instanzen erzeugt werden. Wenn mehrere Container vorhanden sind, die miteinander kommunizieren sollen, können sie über das sogenannte Linking miteinander verknüpft werden. Dadurch können Kommunikationswege wie offene Ports oder gemeinsame Ordner festgelegt werden.</p><p>Ein weiterer Vorteil von Docker Containern besteht darin, dass sie nur so lange leben, wie sie etwas tun. Alles, was innerhalb des Containers passiert, verschwindet, sobald er beendet wird. Wenn jedoch mit persistenten Daten gearbeitet werden soll, können Ordner zwischen dem Host-Rechner und dem Container geteilt werden, um sicherzustellen, dass Änderungen auf beiden Seiten automatisch aktualisiert werden.</p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-2f5a18c elementor-widget elementor-widget-heading" data-id="2f5a18c" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Den ersten Docker Container starten</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-daa1768 elementor-widget elementor-widget-text-editor" data-id="daa1768" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Beginnen wir mit einem einfachen Schritt und starten einen Docker-Container. Container basieren immer auf einem Docker-Image, auch wenn sie von Entwicklern erstellt werden. <a href="https://hub.docker.com/search?q=">Docker Hub</a> bietet hunderte von verschiedenen Images für alle möglichen Situationen an. Ein Basisimage könnte beispielsweise die Grundfunktionalität von Ubuntu sein, die als ubuntu:22.04 bezeichnet wird. Die 22.04 ist dabei eine Art Version.</p><p>Wenn wir ein Docker-Container starten wollen, geben wir einfach den folgenden Befehl ein:</p><p style="padding-left: 40px;"><em><code>docker run ubuntu echo "Hello World"</code><code></code></em></p><p>Dies ist ein einfaches &#8222;Hello World&#8220;-Beispiel, aber man muss irgendwo anfangen. Was passiert eigentlich bei diesem Befehl?</p><p>Zunächst überprüft Docker, ob es das Image &#8222;ubuntu&#8220; lokal gespeichert hat. Wenn nicht, wird es automatisch heruntergeladen. Da kein Tag angegeben wurde, wird automatisch das neueste Image genommen.<br />Docker startet einen Container aus dem angegebenen Image und führt den Befehl &#8222;echo &#8218;Hello World'&#8220; innerhalb des Containers aus, der einfach nur &#8222;Hello World&#8220; ausgibt. Docker beendet den Container wieder, da er seinen Zweck erfüllt hat.</p><p>Das hat zwar etwas gedauert, um nur &#8222;Hello World&#8220; auf dem Bildschirm zu sehen, aber das Herunterladen des Images brauchte seine Zeit. Wenn wir den Befehl jetzt ein zweites Mal ausführen, wird die Ausgabe sofort angezeigt, da das Image bereits lokal gespeichert ist.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-b8f69bf elementor-widget elementor-widget-heading" data-id="b8f69bf" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Run Parameter</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-37b3dd1 elementor-widget elementor-widget-text-editor" data-id="37b3dd1" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Standardmäßig wird der Container sofort nach dem Ausführen des Befehls beendet. Wenn wir das Standardverhalten ändern möchten, gibt es verschiedene Parameter für den &#8222;docker run&#8220;-Befehl, die wir verwenden können. Hier sind einige davon:</p><ul><li><strong>-i</strong> sorgt dafür, dass der Container interaktiv ist. Das bedeutet, wir können während der Laufzeit damit interagieren.</li><li><strong>-t</strong> bindet unsere Ein- und Ausgaben an diesen interaktiven Container.</li><li><strong>-d</strong> sorgt dafür, dass der Container im Hintergrund weiterläuft (Daemon-Modus). Das ist nützlich für Container, die dauerhaft laufen sollen (beispielsweise Container, die Server enthalten oder Aufgaben, die einige Minuten oder Stunden dauern können).</li><li><strong>-p</strong> bindet Ports von unserem Host an den Container. Ein Beispiel wäre &#8222;-p 80:5000&#8220;, das unseren Hostport 80 auf den Containerport 5000 mappt. Das kann sinnvoll sein, wenn wir denselben Container mehrfach aufrufen und die Ports andernfalls kollidieren würden.</li><li><strong>-v</strong> verlinkt ein Verzeichnis auf unserem Hostrechner mit einem Verzeichnis innerhalb des Containers. So können Daten persistent gespeichert werden, da diese normalerweise mit dem Auslaufen des Containers verschwinden. Ein Beispiel wäre &#8222;-v ./folder:/var/folder&#8220;. Vor dem Doppelpunkt steht das Verzeichnis auf dem Hostrechner und danach das Verzeichnis innerhalb des Containers &#8211; genau wie bei den Ports.</li><li><strong>-name</strong> gibt unserem Container einen Namen. Dieser wird andernfalls automatisch vergeben, ist aber nicht immer leicht zu merken. Namen können als Ersatz für die (sehr kryptische) Container-ID verwendet werden und machen daher durchaus Sinn. Hierbei ist zu beachten, dass die Namen auf dem Hostrechner eindeutig sein müssen. Wenn wir also einen neuen Container mit diesem Namen an.</li></ul>								</div>
				</div>
				<div class="elementor-element elementor-element-5e75c95 elementor-widget elementor-widget-heading" data-id="5e75c95" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Container auflisten und stoppen</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-8b6ca29 elementor-widget elementor-widget-text-editor" data-id="8b6ca29" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Wenn wir Informationen über die aktuell ausgeführten Docker Container benötigen, können wir den Befehl</p><p style="padding-left: 40px;"><em><code>docker ps</code><code></code></em></p><p>verwenden. Dieser Befehl zeigt uns wichtige Eigenschaften wie die Container-ID, das Image, die zugeordneten Ports oder den Namen des Containers an.</p><p>Standardmäßig werden nur laufende Container aufgelistet. Wenn wir alle Container auf unserem Host anzeigen lassen möchten, verwenden wir einfach den Parameter <strong>-a</strong>.</p><p>Wenn wir einen laufenden Container beenden möchten, können wir den Befehl</p><p style="padding-left: 40px;"><em><code>docker stop NAME/ID</code><code></code></em></p><p>verwenden. Der Container wird dann gestoppt, aber er bleibt weiterhin vorhanden und behält den Zustand des Docker-Images bei, das beim Ausführen von <em>docker run</em> verwendet wurde. Wenn wir das Image aktualisieren, müssen wir <em>docker run</em> erneut ausführen, um die Änderungen wirksam zu machen.</p><p>Um den Container später wieder zu starten, verwenden wir einfach den Befehl</p><p style="padding-left: 40px;"><em><code>docker start NAME/ID</code><code></code></em></p></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-896bbfb elementor-widget elementor-widget-heading" data-id="896bbfb" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Container entfernen</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-0fff87d elementor-widget elementor-widget-text-editor" data-id="0fff87d" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Wie bereits erwähnt, muss ein Docker-Container entfernt werden, wenn er erneut mit dem gleichen Namen über den docker run Befehl gestartet werden soll. Hierfür kann der Befehl</p><p><em><code>docker rm NAME/ID</code><code></code></em></p><p>verwendet werden, allerdings muss der Container zuvor mit dem Befehl docker stop gestoppt werden.</p></div></div></div>								</div>
				</div>
				</div>
		<div class="elementor-element elementor-element-82b7b8e e-con-full e-flex e-con e-parent" data-id="82b7b8e" data-element_type="container" data-e-type="container">
				<div class="elementor-element elementor-element-4d21a2e elementor-widget elementor-widget-text-editor" data-id="4d21a2e" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Im folgenden Artikel werden wir uns genauer mit Docker Images beschäftigen und einen genaueren Blick darauf werfen.</p><p style="text-align: right;"><a href="https://tekkieninja.de/docker-images/">Hier gehts weiter.</a></p>								</div>
				</div>
				</div>
				</div>
		<p>Der Beitrag <a href="https://tekkieninja.de/was-sind-docker-container-und-wie-funktionieren-sie/">Was sind Docker Container und wie funktionieren sie?</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tekkieninja.de/was-sind-docker-container-und-wie-funktionieren-sie/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Was ist Docker?</title>
		<link>https://tekkieninja.de/was-ist-docker/</link>
					<comments>https://tekkieninja.de/was-ist-docker/#respond</comments>
		
		<dc:creator><![CDATA[Florian Keßler]]></dc:creator>
		<pubDate>Sun, 16 Apr 2023 13:13:42 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<guid isPermaLink="false">https://tekkieninja.de/?p=874</guid>

					<description><![CDATA[<p>Docker ermöglicht es uns, Anwendungen in Containern auszuführen und damit komplexe Infrastrukturen zu erstellen. Diese Container können aufeinander aufbauen und miteinander kommunizieren, was uns die Erstellung von flexiblen und skalierbaren Systemen erleichtert. Im Gegensatz zu herkömmlichen virtuellen Maschinen müssen Container nicht jedes Mal ein vollständiges Betriebssystem mitbringen, sondern können nur die notwendigen Daten und Anwendungen [&#8230;]</p>
<p>Der Beitrag <a href="https://tekkieninja.de/was-ist-docker/">Was ist Docker?</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="874" class="elementor elementor-874">
				<div class="elementor-element elementor-element-2097137 e-con-full e-flex e-con e-parent" data-id="2097137" data-element_type="container" data-e-type="container">
				<div class="elementor-element elementor-element-994eb67 elementor-widget elementor-widget-text-editor" data-id="994eb67" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Docker ermöglicht es uns, Anwendungen in Containern auszuführen und damit komplexe Infrastrukturen zu erstellen. Diese Container können aufeinander aufbauen und miteinander kommunizieren, was uns die Erstellung von flexiblen und skalierbaren Systemen erleichtert. Im Gegensatz zu herkömmlichen virtuellen Maschinen müssen Container nicht jedes Mal ein vollständiges Betriebssystem mitbringen, sondern können nur die notwendigen Daten und Anwendungen enthalten. Das ermöglicht es uns, Serverumgebungen einfach auf unserem eigenen Rechner zu replizieren und Kompatibilitätsprobleme zu vermeiden.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-57ec87c elementor-widget elementor-widget-heading" data-id="57ec87c" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Vorteile von Docker</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-d7f4fc3 elementor-widget elementor-widget-text-editor" data-id="d7f4fc3" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Besonders in der Webentwicklung bietet Docker entscheidende Vorteile. Wir können die Serverumgebung, auf der unsere Webanwendung später laufen wird, genau auf unserem eigenen Rechner nachbilden, unabhängig vom verwendeten Betriebssystem. Das Teilen von Containern erfolgt über das Docker-Hub, wo wir eine Vielzahl von vorkonfigurierten Images finden können. Unter folgendem <a href="https://hub.docker.com/search?q=">Link</a> kann ein erster Überblick über die verschiedenen Images verschafft werden. In dieser Artikelreihe werde ich die Grundlagen von Docker und Docker-Compose erläutern und einige Beispiele geben, um Ihnen den Einstieg zu erleichtern.</p><div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>Ein wichtiger Vorteil von Containerisierung ist, dass sie uns die Möglichkeit gibt, Cloud-Hosting-Anbieter zu nutzen. Wenn wir ein Image erstellen und konfigurieren, können wir den Anbieter einfach auffordern, einen Container mit genau dieser Konfiguration zu starten. Dies bietet Flexibilität und Effizienz bei der Skalierung und Verwaltung von Anwendungen.</p></div></div></div></div></div></div>								</div>
				</div>
				<div class="elementor-element elementor-element-79e5eae elementor-widget elementor-widget-heading" data-id="79e5eae" data-element_type="widget" data-e-type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
					<h3 class="elementor-heading-title elementor-size-default">Trennung von Anwendungen und Abhängigkeiten</h3>				</div>
				</div>
				<div class="elementor-element elementor-element-657ad58 elementor-widget elementor-widget-text-editor" data-id="657ad58" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<p>Containerisierung bietet auch die Möglichkeit, Anwendungen und ihre Abhängigkeiten voneinander zu trennen, was die Wartung und Aktualisierung von Anwendungen erleichtert. Dies ist einer der Gründe, warum ich mich eingehender mit Containerisierung beschäftigt habe. Die Vielseitigkeit dieser Technologie ist beeindruckend und bietet eine großartige Möglichkeit, Anwendungen sicher und effektiv zu betreiben.</p>								</div>
				</div>
				<div class="elementor-element elementor-element-f26265b elementor-widget elementor-widget-text-editor" data-id="f26265b" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
									<hr /><div class="flex flex-grow flex-col gap-3"><div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap"><div class="markdown prose w-full break-words dark:prose-invert light"><p>In dieser Blogserie geht es um die Grundlagen von Docker und Docker-Compose sowie um praktische Beispiele. Im Folgenden findest du Links zu den einzelnen Beiträgen, in denen ich speziell auf folgende Themen eingegangen bin:</p></div></div></div><ol><li><a href="https://tekkieninja.de/was-sind-docker-container-und-wie-funktionieren-sie/">Was sind Container und wie funktionieren sie?</a></li><li><a href="https://tekkieninja.de/docker-images/">Was sind diese Images?</a></li><li><a href="https://tekkieninja.de/dockerfile/">Wie kann ich ein Dockerfile selbst schreiben?</a></li><li><a href="https://tekkieninja.de/docker-compose-erklaert/">Compose in seinen Grundlagen erklärt</a></li><li><a href="https://tekkieninja.de/docker-compose-installieren/">Installation</a></li></ol><p>Ich wünsche euch viel Spaß beim lesen!</p>								</div>
				</div>
				</div>
				</div>
		<p>Der Beitrag <a href="https://tekkieninja.de/was-ist-docker/">Was ist Docker?</a> erschien zuerst auf <a href="https://tekkieninja.de">TekkieNinja</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tekkieninja.de/was-ist-docker/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
