<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>docker on Tim Schumacher</title>
    <link>https://tim.schumacher.im/tags/docker/</link>
    <description>Recent content in docker on Tim Schumacher</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Fri, 23 Feb 2018 00:00:00 +0000</lastBuildDate>
    
        <atom:link href="https://tim.schumacher.im/tags/docker/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Was zum Docker</title>
      <link>https://tim.schumacher.im/blog/was-zum-docker/</link>
      <pubDate>Fri, 23 Feb 2018 00:00:00 +0000</pubDate>
      
      <guid>https://tim.schumacher.im/blog/was-zum-docker/</guid>
      <description>

&lt;p&gt;Ein guter Freund von mir berichtete, dass er seit einem Docker-Update einen PostgreSQL-Container nicht mehr starten konnte, ihn deshalb löschen musste und dann seine Daten verloren gingen. Datenverlust ist nie lustig und aus diesem Grund will ich dem geneigten Leser einige Erfahrungen mit auf den Weg geben, die ich in den letzten anderthalb Jahren bei &lt;a href=&#34;http://www.flyacts.com&#34;&gt;meinem Arbeitgeber&lt;/a&gt; sammeln konnte.&lt;/p&gt;

&lt;h2 id=&#34;container-sind-zustandslos-und-unveränderbar&#34;&gt;Container sind zustandslos und unveränderbar&lt;/h2&gt;

&lt;h3 id=&#34;was-heißt-zustandslos&#34;&gt;Was heißt „zustandslos“?&lt;/h3&gt;

&lt;p&gt;Zwar verhält es sich nicht immer so, dass Container zustandslos und unveränderbar sind, aber man sollte sie dennoch so betrachten. Damit wird dann die Frage aufgeworfen, wenn der Zustand der Anwendung nicht im Container gespeichert wird, wo wird er dann gespeichert? &lt;a href=&#34;https://docs.docker.com/storage/&#34;&gt;Das Handbuch&lt;/a&gt; gibt hier zwei Möglichkeiten vor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Volumes&lt;/li&gt;
&lt;li&gt;Bind-mount&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&#34;docker-volumes&#34;&gt;docker volumes&lt;/h4&gt;

&lt;p&gt;Volumes sind &lt;a href=&#34;https://docs.docker.com/storage/volumes/&#34;&gt;laut Dokumentation&lt;/a&gt; der präferierte Weg den Zustand eines Containers zu persistieren. Meine persönliche Erfahrung ist eine andere. Ich benutze lieber bind mounts, da hier keine Verwaltung von nöten ist. Volumes kann ich auch wesentlich einfacher aus Versehen löschen, ein Ordner im Dateisystem erfordert mehr Aufwand.&lt;/p&gt;

&lt;h4 id=&#34;bind-mounts&#34;&gt;bind mounts&lt;/h4&gt;

&lt;p&gt;Mittels eines „&lt;a href=&#34;https://unix.stackexchange.com/questions/198590/what-is-a-bind-mount/198591#198591&#34;&gt;bind mounts&lt;/a&gt;“ kann ich auf einem Linux-System einen Ordner auf einen anderen Ordner zeigen lassen, so dass beide über den selben Inhalt verfügen. So kann ein Ordner auf dem Hostsystem und in dem Docker-Container den selben Inhalt besitzen. Dadurch wird der Zustand des Containers außerhalb des Containers gespeichert und man kann ihn mit seinen regulären Werkzeugen sichern und beobachten.&lt;/p&gt;

&lt;h3 id=&#34;was-heißt-unveränderbar&#34;&gt;Was heißt „unveränderbar“?&lt;/h3&gt;

&lt;p&gt;Nachdem ich nun den Zustand der Datenbank außerhalb des Containers speichere, gilt es die zweite Eigenschaft „unveränderbar“ (engl immuteable) zu betrachten. Es ist zwar möglich einen Container zu bearbeiten, aber spätestens wenn man diesen Container löscht oder einen zweiten anlegt, wird sich das rächen, da die Änderung weg ist. Willst du wirklich eine Änderung an einem Container vornehmen, empfiehlt es sich, das dem Container zugrunde liegende Abbild zu modifizieren und in ein eigenes abzuspeichern.&lt;/p&gt;

&lt;h2 id=&#34;aber-ich-kann-doch-nicht-den-container-löschen&#34;&gt;Aber ich kann doch nicht den Container löschen&lt;/h2&gt;

&lt;p&gt;Was mich am meisten verdutzt an der Aussage des Freundes war, dass das Löschen eines Containers so ein großer Akt ist. Auf Arbeit mache ich das ständig. Das liegt primär daran, dass wir mit &lt;a href=&#34;https://docs.docker.com/compose/&#34;&gt;docker-compose&lt;/a&gt; arbeiten und dies selbst für jeden kleinsten Dienst. Das Arbeiten mit compose hat den großen Vorteil, dass die Konfiguration der Docker Container in einer &lt;a href=&#34;https://de.wikipedia.org/wiki/YAML&#34;&gt;YAML-Konfigurationsdatei&lt;/a&gt; gespeichert ist und diese Datei über GIT versioniert ist.&lt;/p&gt;

&lt;h2 id=&#34;einen-dienst-mit-docker-compose-einrichten&#34;&gt;Einen Dienst mit &lt;code&gt;docker-compose&lt;/code&gt; einrichten&lt;/h2&gt;

&lt;p&gt;Privat benutze ich für ein Projekt &lt;a href=&#34;https://www.odoo.com/&#34;&gt;odoo&lt;/a&gt; und verwende &lt;code&gt;docker-compose&lt;/code&gt; für die Konfiguration der Anwendung. Hier meine komplette &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;version: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;
services:
  web:
    image: odoo:&lt;span style=&#34;color:#ae81ff&#34;&gt;10.0&lt;/span&gt;
    depends_on:
      - db
    volumes:
      - ./data:/var/lib/odoo
      - ./config:/etc/odoo
      - ./addons:/mnt/extra-addons
    ports:
      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;127.0.0.1:18069:8069&amp;#34;&lt;/span&gt;
    environment:
      - HOST=db
      - USER=odoo
      - PASSWORD=somethingrandom
  db:
    image: postgres:&lt;span style=&#34;color:#ae81ff&#34;&gt;9.6&lt;/span&gt;
    volumes:
        - ./postgres:/usr/local/var/lib/postgresql
    environment:
        - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PGDATA=/usr/local/var/lib/postgresql&amp;#34;&lt;/span&gt;
        - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;POSTGRES_PASSWORD=somethingrandom&amp;#34;&lt;/span&gt;
        - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;POSTGRES_USER=odoo&amp;#34;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Ich habe hier 2 Container definiert. Einmal den Container &lt;code&gt;web&lt;/code&gt; für die Anwendung an sich, in diesem Fall habe ich mit &lt;code&gt;image: odoo:10.0&lt;/code&gt; ein Image &lt;a href=&#34;https://hub.docker.com&#34;&gt;aus dem Hub&lt;/a&gt; angegeben. Man könnte aber auch ein Dockerfile angeben, dann würde &lt;code&gt;docker-compose&lt;/code&gt; zuerst das image bauen. Als nächstes habe ich mit &lt;code&gt;depends_on&lt;/code&gt; definiert, dass der Container &lt;code&gt;web&lt;/code&gt; von dem Container &lt;code&gt;db&lt;/code&gt; abhängig ist. Das bedeuted auch, dass zuerst &lt;code&gt;db&lt;/code&gt; gestartet wird und dann &lt;code&gt;web&lt;/code&gt;. Ob die PostgreSQL-Datenbank so schnell hoch fährt, dass sie bereit ist, wenn die Anwendung sie benötigt ist unter Umständen nicht gegeben, kann also je nach Anwendungen zu Problemen führen und sollte im im Hinterkopf behalten werden. Im Fall von Odoo ist das allerdings kein Problem. Die Abhängigkeit bietet auch den Vorteil das compose einen Eintrag in der Datei &lt;code&gt;/etc/hosts&lt;/code&gt; vornimmt, so dass man den Datenbank-Container mit seinem Namen referenzieren kann. Mit dem Eintrag &lt;code&gt;volumes&lt;/code&gt; spezifiziere ich 3 bind mounts, die von dem lokalen Dateisystem in das Container Dateisystem zeigen. Über das Schlüsselwort &lt;code&gt;ports&lt;/code&gt; kann ich Port-Weiterleitungen von dem Host-System in dem Container erstellen. Dabei sollte man beachten, dass man Ports immer lokal bindet und nicht auf allen Geräten zur Verfügung stellt. Über &lt;code&gt;environment&lt;/code&gt; kann man zusätzliche Umgebungsvariablen in den Container reinreichen. Bei dem PostgreSQL-Image gibt es z.B. einige Variablen, mit denen man das Image konfigurieren kann.&lt;/p&gt;

&lt;p&gt;Man startet die Komposition mit dem Befehl up:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ docker-compose up&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Wenn das System ordentlich hochfährt, kann man es mit STRG+C beenden und dann mit dem parameter &lt;code&gt;-d&lt;/code&gt; starten, damit es im Hintergrund verschwindet:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ docker-compose up -d&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Will man die Dienste runterfahren, gibt es den Befehl &lt;code&gt;down&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ docker-compose down&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Dabei werden sogar etwaige Container schon gelöscht. Aber da der komplette Zustand der beiden Container außerhalb im aktuellen Verzeichnis des Host-Systems gespeichert wird, ist das alles kein Problem.&lt;/p&gt;

&lt;h2 id=&#34;fazit&#34;&gt;Fazit&lt;/h2&gt;

&lt;p&gt;Alles in allem hoffe ich, dass ich darlegen konnte, wieso Container zustandslos (stateless) und unveränderbar (immuteable) sein sollen. Zusätzlich sollte man sich immer bei Docker überlegen, wo sich die Daten befinden. Es ist nämlich schnell und sehr leicht passiert, dass die Daten im Container sind, weil man sich das Image nicht genau angesehen hat oder sich auch einfach nicht überlegt hat, wo die Daten sein könnten.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>