<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>docker on private Homepage von Rainer Rose</title>
    <link>https://www.rainerrose.de/tags/docker/</link>
    <description>Recent content in docker on private Homepage von Rainer Rose</description>
    <generator>Hugo</generator>
    <language>de</language>
    <copyright>Copyright © 1998-2026 Rainer Rose. All Rights Reserved.
</copyright>
    <lastBuildDate>Sun, 22 Feb 2026 18:21:03 +0100</lastBuildDate><atom:link href="https://www.rainerrose.de/tags/docker/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Paperless-ngx: Major-Upgrade oder Wechsel der Datenbank in Docker</title>
      <link>https://www.rainerrose.de/docs/howto/paperless-postgres-mariadb-upgrades/</link>
      <pubDate>Sun, 22 Feb 2026 18:21:03 +0100</pubDate>
      <guid>https://www.rainerrose.de/docs/howto/paperless-postgres-mariadb-upgrades/</guid>
      <description><![CDATA[<!-- Anreißer -->
<p>Durch Freunde wurde ich auf das Document Management System <code>paperless</code> aufmerksam, dass im derzeit aktuellen Fork <a href="https://tools.rainerrose.de/redirect.php?id=56" target="_blank" rel="noopener noreferrer">paperless-ngx<i class="fas fa-external-link-square-alt ms-1"></i></a> weiterlebt.
In Verbindung mit einem Einzugsscanner ist es ein wahr gewordener Traum, der mich sehr in meinem Alltag entlastet.</p>
<p>Das Aktualisieren von <em>paperless-ngx</em> (im Folgenden nur noch <em>paperless</em> genannt) unter <em>Docker</em> ist zwar in der <a href="https://tools.rainerrose.de/redirect.php?id=57" target="_blank" rel="noopener noreferrer">Dokumentation<i class="fas fa-external-link-square-alt ms-1"></i></a> recht gut beschrieben, aber das Updaten der Datenbank, finde ich zu kompliziert, weil es nur auf die offizielle <em>PostgreSQL</em>-Dokumentation verweist.</p>
<p>Hier müsste ich mit den CLI-Tools wie <code>pg_dumpall</code> und <code>pg_upgrade</code>  hantieren, was arbeiten im <em>Docker</em>-Container notwendig macht und vermutlich auch doppelte <em>Docker</em>-Container-Instanzen nötig macht. Eine automagische Migration unterstützen die <em>postgres</em>-images nach meinem Wissen derzeit nicht. Also habe ich eine andere Möglichkeit gesucht und auch gefunden!</p>]]></description>
      <content:encoded><![CDATA[<!-- Anreißer -->
<p>Durch Freunde wurde ich auf das Document Management System <code>paperless</code> aufmerksam, dass im derzeit aktuellen Fork <a href="https://tools.rainerrose.de/redirect.php?id=56" target="_blank" rel="noopener noreferrer">paperless-ngx<i class="fas fa-external-link-square-alt ms-1"></i></a> weiterlebt.
In Verbindung mit einem Einzugsscanner ist es ein wahr gewordener Traum, der mich sehr in meinem Alltag entlastet.</p>
<p>Das Aktualisieren von <em>paperless-ngx</em> (im Folgenden nur noch <em>paperless</em> genannt) unter <em>Docker</em> ist zwar in der <a href="https://tools.rainerrose.de/redirect.php?id=57" target="_blank" rel="noopener noreferrer">Dokumentation<i class="fas fa-external-link-square-alt ms-1"></i></a> recht gut beschrieben, aber das Updaten der Datenbank, finde ich zu kompliziert, weil es nur auf die offizielle <em>PostgreSQL</em>-Dokumentation verweist.</p>
<p>Hier müsste ich mit den CLI-Tools wie <code>pg_dumpall</code> und <code>pg_upgrade</code>  hantieren, was arbeiten im <em>Docker</em>-Container notwendig macht und vermutlich auch doppelte <em>Docker</em>-Container-Instanzen nötig macht. Eine automagische Migration unterstützen die <em>postgres</em>-images nach meinem Wissen derzeit nicht. Also habe ich eine andere Möglichkeit gesucht und auch gefunden!</p>
<p><code>paperless</code> liefert die beiden Tools <code>document_exporter</code> und <code>document_importer</code> mit, die ein <strong>vollständiges</strong> Backup und Wiederherstellung (Restore) der kompletten Instanz bereitstellt.</p>
<p>Mit diesen beiden Tools lässt sich ein Major-Upgrade bewerkstelligen. Wie ich heute rausfand ist sogar der Wechsel der Datenbank-Engine ohne allzu große Umstände möglich.</p>

<h2 id="überblick" data-numberify>Überblick<a class="anchor ms-1" href="#überblick"></a></h2>
<p>Der grobe Pfad für ein Major-Upgrade ist daher:</p>
<ul>
<li>Zuerst ein vollständiges Backup anfertigen.</li>
<li>Alle Daten inklusive Volumes wegwerfen.</li>
<li>Die <em>PostgreSQL</em>-Version im <code>docker-compose.yml</code> anpassen.</li>
<li>Schlussendlich alle Daten wieder importieren.</li>
</ul>
<p>Das hat bisher anstandslos geklappt.</p>
<p>Der Wechsel auf eine andere Datenbank-Engine wird weiter unten beschrieben.</p>

<h2 id="voraussetzungen" data-numberify>Voraussetzungen<a class="anchor ms-1" href="#voraussetzungen"></a></h2>
<p>Es setzt voraus, dass die Daten außerhalb der Docker-Umgebung landen. Das <code>export</code> Volume ist also als Verzeichnis unterhalb der <code>docker-compose.yml</code> so wie in den <a href="https://tools.rainerrose.de/redirect.php?id=58" target="_blank" rel="noopener noreferrer">Beispielen<i class="fas fa-external-link-square-alt ms-1"></i></a> definiert.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="w">      </span>- <span class="l">./export:/usr/src/paperless/export</span><span class="w">
</span></span></span></code></pre></div><p>Wie ich ein Datenbank-Upgrade im Detail durchführe, beschreibe ich im Folgenden.</p>
<p>Zuerst sollte sichergestellt sein, dass keine Importe ins <em>Paperless</em> stattfinden. Da ich alleine auf dem System arbeite und keinen E-Mail-Import verwende, kann ich das gut sicherstellen.</p>

<h2 id="backup" data-numberify>Backup<a class="anchor ms-1" href="#backup"></a></h2>
<p>Als ersten Schritt fertige ich ein Backup an. Dies geht wunderbar mit dem bereits erwähnten <code>document_exporter</code> folgendermaßen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker compose <span class="nb">exec</span> -T webserver document_exporter ../export -z -zn full-backup
</span></span></code></pre></div><p>Hier sollte dann eine Datei namens <code>full-backup.zip</code> außerhalb des Docker-Umgebung entstanden sein. Dies enthält alle relevanten Informationen für ein Desaster-Recovery.</p>

<blockquote class="alert alert-success" role="alert">
    <p class="alert-heading fw-bold">
      <i class="fas fa-lightbulb me-2"></i>Tipp
    </p>
    <p>Der zusätzliche Parameter <code>--no-progress-bar</code> sorgt für weniger Ausgaben in Backup-Scripten.</p>
</blockquote>

<h2 id="zurück-auf-null" data-numberify>Zurück auf Null<a class="anchor ms-1" href="#zurück-auf-null"></a></h2>
<p>Danach fahre ich alle Container herunter und lösche gleichzeitig alle <em>Docker</em> Volumes:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker compose down --volumes
</span></span></code></pre></div><p>Die Ausgabe sollte ungefähr so aussehen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln">1</span><span class="cl">[+] down 8/8
</span></span><span class="line"><span class="ln">2</span><span class="cl"> ✔ Container paperless-webserver-1 Removed   5.6s
</span></span><span class="line"><span class="ln">3</span><span class="cl"> ✔ Container paperless-broker-1    Removed   0.4s
</span></span><span class="line"><span class="ln">4</span><span class="cl"> ✔ Container paperless-db-1        Removed   0.3s
</span></span><span class="line"><span class="ln">5</span><span class="cl"> ✔ Volume paperless_media          Removed   0.2s
</span></span><span class="line"><span class="ln">6</span><span class="cl"> ✔ Volume paperless_pgdata         Removed   0.0s
</span></span><span class="line"><span class="ln">7</span><span class="cl"> ✔ Volume paperless_data           Removed   0.0s
</span></span><span class="line"><span class="ln">8</span><span class="cl"> ✔ Volume paperless_redisdata      Removed   0.0s
</span></span><span class="line"><span class="ln">9</span><span class="cl"> ✔ Network paperless_default       Removed                     
</span></span></code></pre></div>
<h2 id="neue-version-wählen" data-numberify>Neue Version wählen<a class="anchor ms-1" href="#neue-version-wählen"></a></h2>
<p>Nun kann ich in der <code>docker-compose.yml</code>-Datei das Datenbank-Image auf die gewünschte Version der Datenbank hochziehen.</p>
<p>Für PostgreSQL gibt es <a href="https://tools.rainerrose.de/redirect.php?id=59" target="_blank" rel="noopener noreferrer">hier im Repo eine Vorlage<i class="fas fa-external-link-square-alt ms-1"></i></a> an der ich mich orientiert habe. Im Mai 2025 war es die Version 17.
Also änderte ich den Eintrag <code>docker-compose.yml</code> von der Version 16.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="w">  </span><span class="nt">db</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">docker.io/library/postgres:16</span><span class="w">
</span></span></span></code></pre></div><p>auf die Version 17</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="w">  </span><span class="nt">db</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">docker.io/library/postgres:17</span><span class="w">
</span></span></span></code></pre></div><p>Es empfiehlt sich eh ab und zu da mal einzuschauen, ob nicht z.B. eine neue redis-Version unterstützt wird.
Ich selbst stütze mich nur auf die Haupt (Major-Versionen). Bei Minor- oder Patch-Updates pulle ich das jeweilige neue Image und starte alle Docker-Container neu, das reicht mir und hat sich bei mir bewährt.</p>

<blockquote class="alert alert-warning" role="alert">
    <p class="alert-heading fw-bold">
      <i class="fas fa-exclamation-circle me-2"></i>Hinweis
    </p>
    <p>Aktuell ist im Repo die <em>PostgreSQL</em>-Version 18 angegeben. Leider wirft der Docker-Container <code>db-1</code> einiges an Fehlermeldungen und startet sich immer wieder neu. Eine Lösung dazu beschreibe ich weiter unten; hier soll es jetzt erst einmal mit dem Upgrade von 16 auf 17 weiter gehen; schließlich hat das Update von 15 auf 16 vor einiger Zeit genauso geklappt.</p>
</blockquote>

<h2 id="erster-start" data-numberify>Erster Start<a class="anchor ms-1" href="#erster-start"></a></h2>
<p>Nach dem Ändern der Major-Version (bzw. des Tags) vom <em>postgres</em>-Image, können die Docker-Container von <em>paperless</em> schon wieder gestartet werden. Sofern das Image lokal noch nicht vorliegt, wird es automatisch heruntergeladen.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker compose up -d
</span></span></code></pre></div><p>Folgendes sollte als Ausgabe zu sehen sein:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln"> 1</span><span class="cl">[+] up 22/22
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"> ✔ Image docker.io/library/postgres:18 Pulled     15.3s
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"> ✔ Network paperless_default           Created    0.0s
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"> ✔ Volume paperless_data               Created    0.0s
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"> ✔ Volume paperless_media              Created    0.0s
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"> ✔ Volume paperless_redisdata          Created    0.0s
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"> ✔ Volume paperless_pgdata             Created    0.0s
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"> ✔ Container paperless-db-1            Created    0.2s
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"> ✔ Container paperless-broker-1        Created    0.2s
</span></span><span class="line"><span class="ln">10</span><span class="cl"> ✔ Container paperless-webserver-1     Created   
</span></span></code></pre></div><p>Nun muss solange gewartet, bis die Login-Maske wieder mit dem Browser besuchbar ist.</p>
<p>Da dies einer Neuinstallation entspricht und daher Datenbanken etc. eingerichtet werden müssen, dauert dies je nach Rechenpower etwas. Daher ist etwas Geduld erforderlich.</p>
<p>Zeigt&rsquo;s im Browser <code>502 Bad Gateway</code> ist noch nicht alles fertig.  Neugierige werfen ein Blick in die Docker-Logs</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker compose logs -f
</span></span></code></pre></div><p>Wenn ungefähr folgende Log-Einträge zu sehen sind</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span> <span class="p">[</span><span class="n">tasks</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">bulk_edit</span><span class="o">.</span><span class="n">delete</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">signals</span><span class="o">.</span><span class="n">handlers</span><span class="o">.</span><span class="n">send_webhook</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="n">bulk_update_documents</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="n">check_scheduled_workflows</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="n">consume_file</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="n">empty_trash</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="n">index_optimize</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="n">sanity_check</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="n">train_classifier</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">documents</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="n">update_document_content_maybe_archive_file</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">paperless_mail</span><span class="o">.</span><span class="n">mail</span><span class="o">.</span><span class="n">apply_mail_action</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">paperless_mail</span><span class="o">.</span><span class="n">mail</span><span class="o">.</span><span class="n">error_callback</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span>   <span class="o">.</span> <span class="n">paperless_mail</span><span class="o">.</span><span class="n">tasks</span><span class="o">.</span><span class="n">process_mail_accounts</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span> 
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span> <span class="p">[</span><span class="mi">2025</span><span class="o">-</span><span class="mi">05</span><span class="o">-</span><span class="mi">29</span> <span class="mi">12</span><span class="p">:</span><span class="mi">50</span><span class="p">:</span><span class="mi">03</span><span class="p">,</span><span class="mi">792</span><span class="p">]</span> <span class="p">[</span><span class="n">INFO</span><span class="p">]</span> <span class="p">[</span><span class="n">celery</span><span class="o">.</span><span class="n">worker</span><span class="o">.</span><span class="n">consumer</span><span class="o">.</span><span class="n">connection</span><span class="p">]</span> <span class="n">Connected</span> <span class="n">to</span> <span class="n">redis</span><span class="p">:</span><span class="o">//</span><span class="n">broker</span><span class="p">:</span><span class="mi">6379</span><span class="o">//</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="n">webserver_1</span>  <span class="o">|</span> <span class="p">[</span><span class="mi">2025</span><span class="o">-</span><span class="mi">05</span><span class="o">-</span><span class="mi">29</span> <span class="mi">12</span><span class="p">:</span><span class="mi">50</span><span class="p">:</span><span class="mi">03</span><span class="p">,</span><span class="mi">982</span><span class="p">]</span> <span class="p">[</span><span class="n">INFO</span><span class="p">]</span> <span class="p">[</span><span class="n">celery</span><span class="o">.</span><span class="n">apps</span><span class="o">.</span><span class="n">worker</span><span class="p">]</span> <span class="n">celery</span><span class="err">@</span><span class="mf">7e94</span><span class="n">fdb4f941</span> <span class="n">ready</span><span class="o">.</span>
</span></span></code></pre></div><p>sollte die Login-Maske zur Einrichtung des ersten Benutzerkontos verfügbar sein und es kann mit dem nächsten Schritt weiter gemacht werden.</p>
<p><picture><img class="img-fluid " alt="Paperless-ngx Anmelde-Maske zur Einrichtung des ersten Benutzerkontos" src="https://www.rainerrose.de/images/docs/paperless-login-initial.png?v=960c44cf92448b0054d81f613282f43c" loading="lazy" width="405" height="716" />
</picture>

</p>

<h2 id="daten-wieder-importieren" data-numberify>Daten wieder importieren<a class="anchor ms-1" href="#daten-wieder-importieren"></a></h2>
<p>Über den <code>document_importer</code> lässt sich nun wieder alles importieren: Alle Dokumente, alle Tags, alle Benutzeraccounts, gespeicherten Ansichten usw.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker compose <span class="nb">exec</span> -T webserver document_importer ../export/full-backup.zip
</span></span></code></pre></div><p>Ausgabe:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln">1</span><span class="cl">Checking the manifest
</span></span><span class="line"><span class="ln">2</span><span class="cl">Installed 4248 object(s) from 1 fixture(s)
</span></span><span class="line"><span class="ln">3</span><span class="cl">Copy files into paperless...
</span></span><span class="line"><span class="ln">4</span><span class="cl">100%|██████████| 1014/1014 [00:04&lt;00:00, 210.59it/s]
</span></span><span class="line"><span class="ln">5</span><span class="cl">Updating search index...
</span></span><span class="line"><span class="ln">6</span><span class="cl">100%|██████████| 1014/1014 [00:10&lt;00:00, 94.50it/s] 
</span></span></code></pre></div><p>Falls im Browser Weiterleitung auf den Unterpfad <code>/accounts/signup/?next=%2F</code> stattfand, diesen Pfad löschen!
Im Browser also wieder die gewohnte URL ansurfen und es sollte wieder die gewohnte Login-Maske erscheinen.</p>

<h2 id="fertig-anmelden" data-numberify>Fertig, anmelden<a class="anchor ms-1" href="#fertig-anmelden"></a></h2>
<p>Schlussendlich stoße ich noch einmal vorsichtshalber mein Backup-Script von Paperless noch an und bin fertig.</p>

<h2 id="postgresql-18" data-numberify>PostgreSQL 18<a class="anchor ms-1" href="#postgresql-18"></a></h2>
<p>Während ich diesen Artikel schrieb, stellte ich fest, dass in den <a href="https://tools.rainerrose.de/redirect.php?id=60" target="_blank" rel="noopener noreferrer">Vorlagen im Repo<i class="fas fa-external-link-square-alt ms-1"></i></a> zu <code>docker-compose.yml</code> schon <em>PostgreSQL</em> 18 unterstützt wird.
Ich bin daher genau nach meiner Anleitung vorgegangen und musste feststellen, dass der Datenbank-Container nicht nach oben kam.</p>
<p>In den Docker-Logs entdeckte ich dann folgende Meldungen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span> <span class="n">Error</span><span class="p">:</span> <span class="ow">in</span> <span class="mi">18</span><span class="o">+</span><span class="p">,</span> <span class="n">these</span> <span class="n">Docker</span> <span class="n">images</span> <span class="n">are</span> <span class="n">configured</span> <span class="n">to</span> <span class="n">store</span> <span class="n">database</span> <span class="n">data</span> <span class="ow">in</span> <span class="n">a</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">format</span> <span class="n">which</span> <span class="n">is</span> <span class="n">compatible</span> <span class="n">with</span> <span class="s2">&#34;pg_ctlcluster&#34;</span> <span class="p">(</span><span class="n">specifically</span><span class="p">,</span> <span class="n">using</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">major</span><span class="o">-</span><span class="n">version</span><span class="o">-</span><span class="n">specific</span> <span class="n">directory</span> <span class="n">names</span><span class="p">)</span><span class="o">.</span>  <span class="n">This</span> <span class="n">better</span> <span class="n">reflects</span> <span class="n">how</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">PostgreSQL</span> <span class="n">itself</span> <span class="n">works</span><span class="p">,</span> <span class="ow">and</span> <span class="n">how</span> <span class="n">upgrades</span> <span class="n">are</span> <span class="n">to</span> <span class="n">be</span> <span class="n">performed</span><span class="o">.</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span> 
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">See</span> <span class="n">also</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">docker</span><span class="o">-</span><span class="n">library</span><span class="o">/</span><span class="n">postgres</span><span class="o">/</span><span class="n">pull</span><span class="o">/</span><span class="mi">1259</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span> 
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">Counter</span> <span class="n">to</span> <span class="n">that</span><span class="p">,</span> <span class="n">there</span> <span class="n">appears</span> <span class="n">to</span> <span class="n">be</span> <span class="n">PostgreSQL</span> <span class="n">data</span> <span class="ow">in</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>          <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">postgresql</span><span class="o">/</span><span class="n">data</span> <span class="p">(</span><span class="n">unused</span> <span class="n">mount</span><span class="o">/</span><span class="n">volume</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span> 
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">This</span> <span class="n">is</span> <span class="n">usually</span> <span class="n">the</span> <span class="n">result</span> <span class="n">of</span> <span class="n">upgrading</span> <span class="n">the</span> <span class="n">Docker</span> <span class="n">image</span> <span class="n">without</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">upgrading</span> <span class="n">the</span> <span class="n">underlying</span> <span class="n">database</span> <span class="n">using</span> <span class="s2">&#34;pg_upgrade&#34;</span> <span class="p">(</span><span class="n">which</span> <span class="n">requires</span> <span class="n">both</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">versions</span><span class="p">)</span><span class="o">.</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span> 
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">The</span> <span class="n">suggested</span> <span class="n">container</span> <span class="n">configuration</span> <span class="k">for</span> <span class="mi">18</span><span class="o">+</span> <span class="n">is</span> <span class="n">to</span> <span class="n">place</span> <span class="n">a</span> <span class="n">single</span> <span class="n">mount</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">at</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">postgresql</span> <span class="n">which</span> <span class="n">will</span> <span class="n">then</span> <span class="n">place</span> <span class="n">PostgreSQL</span> <span class="n">data</span> <span class="ow">in</span> <span class="n">a</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">subdirectory</span><span class="p">,</span> <span class="n">allowing</span> <span class="n">usage</span> <span class="n">of</span> <span class="s2">&#34;pg_upgrade --link&#34;</span> <span class="n">without</span> <span class="n">mount</span> <span class="n">point</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">boundary</span> <span class="n">issues</span><span class="o">.</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span> 
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">See</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">docker</span><span class="o">-</span><span class="n">library</span><span class="o">/</span><span class="n">postgres</span><span class="o">/</span><span class="n">issues</span><span class="o">/</span><span class="mi">37</span> <span class="k">for</span> <span class="n">a</span> <span class="p">(</span><span class="n">long</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span>         <span class="o">|</span>        <span class="n">discussion</span> <span class="n">around</span> <span class="n">this</span> <span class="n">process</span><span class="p">,</span> <span class="ow">and</span> <span class="n">suggestions</span> <span class="k">for</span> <span class="n">how</span> <span class="n">to</span> <span class="k">do</span> <span class="n">so</span><span class="o">.</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="n">db</span><span class="o">-</span><span class="mi">1</span> <span class="n">exited</span> <span class="n">with</span> <span class="n">code</span> <span class="mi">1</span> <span class="p">(</span><span class="n">restarting</span><span class="p">)</span>
</span></span></code></pre></div><p>Der Downgrade auf 17 war nach der obigen Anleitung recht schnell erledigt und <em>paperless</em> lief wieder zufriedenstellend mit der Version 17 von <em>PostgreSQL</em>.</p>

<h2 id="umstellung-auf-mariadb-12" data-numberify>Umstellung auf MariaDB 12<a class="anchor ms-1" href="#umstellung-auf-mariadb-12"></a></h2>
<p>Ich nahm dies als Anlass, die Datenbank-Engine auf MariaDB umzustellen.
Im Repo des Projektes gibt es dazu ebenfalls <a href="https://tools.rainerrose.de/redirect.php?id=61" target="_blank" rel="noopener noreferrer">eine Vorlage<i class="fas fa-external-link-square-alt ms-1"></i></a>.
Es gab drei Stellen, die ich dafür anpassen musste.</p>
<p>Es mussten im Abschnitt von <code>db</code> ein paar Umgebungsvariablen und natürlich das <code>image</code> umgestellt werden; hier ist 12 gerade aktuell.</p>
<p>Weiter unten im Abschnitt <code>webserver</code> mussten ebenfalls noch ein paar Umgebungsvariablen hinzugefügt werden.</p>
<p>Als letztes musste ich den Volume-Namen im Abschnitt <code>volumes</code> umbenennen.
Danach konnte ich die Container wieder starten und die Daten importieren, wie weiter oben beschrieben.</p>
<p>Nachfolgend ein <code>diff</code> aus meinem <em>ansible</em>-Playbook. (Ja, ich habe <code>restart</code> auch noch gleich umstellt bzw. an die neue Vorlage aus dem Projekt angeglichen. )</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-diff" data-lang="diff"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="gd">--- a/roles/paperless/files/docker-compose.yml
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="gd"></span><span class="gi">+++ b/roles/paperless/files/docker-compose.yml
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="gi"></span><span class="gu">@@ -28,26 +28,24 @@
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="gu"></span> 
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"> services:
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">   broker:
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="gd">-    image: docker.io/library/redis:8
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="gd">-    restart: unless-stopped
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="gd"></span><span class="gi">+    image: docker.io/library/redis:7
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="gi">+    restart: always
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="gi"></span>     volumes:
</span></span><span class="line"><span class="ln">12</span><span class="cl">       - redisdata:/data
</span></span><span class="line"><span class="ln">13</span><span class="cl"> 
</span></span><span class="line"><span class="ln">14</span><span class="cl">   db:
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="gd">-    image: docker.io/library/mariadb:12
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="gd">-    restart: unless-stopped
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="gd"></span><span class="gi">+    image: docker.io/library/postgres:17
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="gi">+    restart: always
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="gi"></span>     volumes:
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="gd">-      - dbdata:/var/lib/mysql
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="gd"></span><span class="gi">+      - pgdata:/var/lib/postgresql/data
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="gi"></span>     environment:
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="gd">-      MARIADB_HOST: paperless
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="gd">-      MARIADB_DATABASE: paperless
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="gd">-      MARIADB_USER: paperless
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="gd">-      MARIADB_PASSWORD: paperless
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="gd">-      MARIADB_ROOT_PASSWORD: paperless
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="gd"></span><span class="gi">+      POSTGRES_DB: paperless
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="gi">+      POSTGRES_USER: paperless
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="gi">+      POSTGRES_PASSWORD: paperless
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="gi"></span> 
</span></span><span class="line"><span class="ln">32</span><span class="cl">   webserver:
</span></span><span class="line"><span class="ln">33</span><span class="cl">     image: ghcr.io/paperless-ngx/paperless-ngx:latest
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="gd">-    restart: unless-stopped
</span></span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="gd"></span><span class="gi">+    restart: always
</span></span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="gi"></span>     depends_on:
</span></span><span class="line"><span class="ln">37</span><span class="cl">       - db
</span></span><span class="line"><span class="ln">38</span><span class="cl">       - broker
</span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="gu">@@ -68,13 +66,9 @@ services:
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="gu"></span>       - extra.env
</span></span><span class="line"><span class="ln">41</span><span class="cl">     environment:
</span></span><span class="line"><span class="ln">42</span><span class="cl">       PAPERLESS_REDIS: redis://broker:6379
</span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="gd">-      PAPERLESS_DBENGINE: mariadb
</span></span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="gd"></span>       PAPERLESS_DBHOST: db
</span></span><span class="line"><span class="ln">45</span><span class="cl"><span class="gd">-      PAPERLESS_DBUSER: paperless # only needed if non-default username
</span></span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="gd">-      PAPERLESS_DBPASS: paperless # only needed if non-default password
</span></span></span><span class="line"><span class="ln">47</span><span class="cl"><span class="gd">-      PAPERLESS_DBPORT: 3306
</span></span></span><span class="line"><span class="ln">48</span><span class="cl"><span class="gd"></span> volumes:
</span></span><span class="line"><span class="ln">49</span><span class="cl">   data:
</span></span><span class="line"><span class="ln">50</span><span class="cl">   media:
</span></span><span class="line"><span class="ln">51</span><span class="cl"><span class="gd">-  dbdata:
</span></span></span><span class="line"><span class="ln">52</span><span class="cl"><span class="gd"></span><span class="gi">+  pgdata:
</span></span></span><span class="line"><span class="ln">53</span><span class="cl"><span class="gi"></span>   redisdata:
</span></span></code></pre></div>]]></content:encoded>
    <enclosure url="https://www.rainerrose.de/images/docs/paperless.png" length="8086" type="image/.png" />
    </item>
    
    <item>
      <title>Bash-Tricks</title>
      <link>https://www.rainerrose.de/docs/linux/bash-tricks/</link>
      <pubDate>Sun, 22 Sep 2024 17:38:20 +0200</pubDate>
      <guid>https://www.rainerrose.de/docs/linux/bash-tricks/</guid>
      <description><![CDATA[<!-- Anreißer -->
<p>Eine kleine Sammlung an <code>bash</code>-Kniffen, Tricks und HowTos.</p>
<p>Diese Unterseite ist bisher ohne durchdachte Sortierung. Werde für Interessierte das Neueste immer oben anfügen.</p>

<h2 id="boot-stick-erstellen" data-numberify>Boot-Stick erstellen<a class="anchor ms-1" href="#boot-stick-erstellen"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo dd <span class="nv">bs</span><span class="o">=</span>4M <span class="k">if</span><span class="o">=</span>/path/to/manjaro.iso <span class="nv">of</span><span class="o">=</span>/dev/sd<span class="o">[</span>drive letter<span class="o">]</span> <span class="nv">status</span><span class="o">=</span>progress <span class="nv">oflag</span><span class="o">=</span>sync
</span></span></code></pre></div>
<h2 id="dateien-anlegen-via-allokierung" data-numberify>Dateien anlegen via Allokierung<a class="anchor ms-1" href="#dateien-anlegen-via-allokierung"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">fallocate -l 10GB meine_grosse_datei
</span></span></code></pre></div><p>ggf. Parameter <code>-o offset</code> und <code>-n</code> beachten, bei Größenänderung swap-File.</p>]]></description>
      <content:encoded><![CDATA[<!-- Anreißer -->
<p>Eine kleine Sammlung an <code>bash</code>-Kniffen, Tricks und HowTos.</p>
<p>Diese Unterseite ist bisher ohne durchdachte Sortierung. Werde für Interessierte das Neueste immer oben anfügen.</p>

<h2 id="boot-stick-erstellen" data-numberify>Boot-Stick erstellen<a class="anchor ms-1" href="#boot-stick-erstellen"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo dd <span class="nv">bs</span><span class="o">=</span>4M <span class="k">if</span><span class="o">=</span>/path/to/manjaro.iso <span class="nv">of</span><span class="o">=</span>/dev/sd<span class="o">[</span>drive letter<span class="o">]</span> <span class="nv">status</span><span class="o">=</span>progress <span class="nv">oflag</span><span class="o">=</span>sync
</span></span></code></pre></div>
<h2 id="dateien-anlegen-via-allokierung" data-numberify>Dateien anlegen via Allokierung<a class="anchor ms-1" href="#dateien-anlegen-via-allokierung"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">fallocate -l 10GB meine_grosse_datei
</span></span></code></pre></div><p>ggf. Parameter <code>-o offset</code> und <code>-n</code> beachten, bei Größenänderung swap-File.</p>

<h2 id="passwort-generieren" data-numberify>Passwort generieren<a class="anchor ms-1" href="#passwort-generieren"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">tr -dc A-Za-z0-9 &lt;/dev/urandom <span class="p">|</span> head -c <span class="m">64</span>
</span></span></code></pre></div><p>Als kleine Script-Version in meinem <a href="https://tools.rainerrose.de/redirect.php?id=38" target="_blank" rel="noopener noreferrer">GitLab-Repository<i class="fas fa-external-link-square-alt ms-1"></i></a></p>

<h2 id="datumsberechnungen" data-numberify>Datumsberechnungen<a class="anchor ms-1" href="#datumsberechnungen"></a></h2>

<h3 id="übermorgen" data-numberify>Übermorgen<a class="anchor ms-1" href="#übermorgen"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">date  --date<span class="o">=</span><span class="s2">&#34;2 days&#34;</span> +<span class="s2">&#34;%d.%m.%Y&#34;</span>
</span></span></code></pre></div>
<h3 id="vorgestern" data-numberify>Vorgestern<a class="anchor ms-1" href="#vorgestern"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">date  --date<span class="o">=</span><span class="s2">&#34;2 days ago&#34;</span> +<span class="s2">&#34;%d.%m.%Y&#34;</span>
</span></span></code></pre></div>
<h2 id="ausgabe-von-du" data-numberify>Ausgabe von “du”<a class="anchor ms-1" href="#ausgabe-von-du"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">du -sk * <span class="p">|</span> sort -n
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">du -sb * <span class="p">|</span> sort -n <span class="p">|</span> numfmt --to<span class="o">=</span>iec
</span></span></code></pre></div><p>Etwas mehr Erklärung <a href="/posts/disk-usage/">hier im Blog-Artikel</a>.</p>

<h2 id="binary-installiert-" data-numberify>Binary installiert ?<a class="anchor ms-1" href="#binary-installiert-"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">if</span> ! <span class="nb">type</span> <span class="s2">&#34;docker-compose&#34;</span> &gt; /dev/null<span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="nb">echo</span> <span class="s1">&#39;Error: docker-compose is not installed.&#39;</span> &gt;<span class="p">&amp;</span><span class="m">2</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    show_error_function
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="k">fi</span>
</span></span></code></pre></div>
<h2 id="eingaben" data-numberify>Eingaben<a class="anchor ms-1" href="#eingaben"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">read</span> -rp <span class="s2">&#34;Hier eine Entscheidungsfrage (j/n): &#34;</span> VARIABLE_WO_DER_INHALT_REIN_SOLL
</span></span></code></pre></div>
<h2 id="tabellarische-umformartierung" data-numberify>tabellarische Umformartierung<a class="anchor ms-1" href="#tabellarische-umformartierung"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;a11 b12_Text c13&#34;</span> &gt; /tmp/beispiel
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;a21 b22 c23&#34;</span> &gt;&gt; /tmp/beispiel
</span></span><span class="line"><span class="ln">3</span><span class="cl">column -t /tmp/beispiel
</span></span></code></pre></div><p><strong>Ausgabe:</strong></p>
<pre><code>a11  b12_Text  c13
a21  b22       c23
</code></pre>

<h2 id="alias" data-numberify>Alias<a class="anchor ms-1" href="#alias"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">alias</span> <span class="nv">sdf</span><span class="o">=</span><span class="s1">&#39;df -h|egrep -v &#39;</span><span class="se">\&#39;</span><span class="s1">&#39;^(overlay|nsfs|shm|cgroup|tmpfs|debugfs|mqueue)&#39;</span><span class="se">\&#39;</span><span class="s1">&#39;&#39;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">alias</span> <span class="nv">smount</span><span class="o">=</span><span class="s1">&#39;mount|egrep -v &#39;</span><span class="se">\&#39;</span><span class="s1">&#39;^(overlay|nsfs|shm|cgroup|tmpfs|debugfs|mqueue)&#39;</span><span class="se">\&#39;</span><span class="s1">&#39;&#39;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">alias</span> <span class="nv">dc</span><span class="o">=</span><span class="s1">&#39;docker-compose&#39;</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">de<span class="o">()</span> <span class="o">{</span> docker <span class="nb">exec</span> -it <span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span> bash<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="nb">alias</span> <span class="nv">dpa</span><span class="o">=</span><span class="s1">&#39;docker ps -f status=exited&#39;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">psg<span class="o">()</span> <span class="o">{</span> ps aux <span class="p">|</span> grep <span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span> <span class="p">|</span> grep -v grep<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="nb">alias</span> <span class="nv">t</span><span class="o">=</span><span class="s1">&#39;ls -lrt --color=auto&#39;</span>
</span></span></code></pre></div>
<h2 id="prompting" data-numberify>Prompting<a class="anchor ms-1" href="#prompting"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nv">PS1</span><span class="o">=</span><span class="s2">&#34;[\u@\H:\w]\$ &#34;</span>
</span></span></code></pre></div><p>Ggf <code>\n</code> einstreuen für extra Zeile.</p>

<h2 id="verzeichniswechsel" data-numberify>Verzeichniswechsel<a class="anchor ms-1" href="#verzeichniswechsel"></a></h2>
<p>Mal wieder beim Verzeichniswechsel vertippt?</p>
<p>Die <code>bash</code> speichert das letzte Verzeichnis, in welchem man sich
befunden hat in der Variable <code>$OLDPWD</code>.</p>
<p>Ein</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">cd</span> <span class="nv">$OLDPWD</span>
</span></span></code></pre></div><p>bringt einen also wieder zurück ins alte Verzeichnis.</p>
<p>Kürzer wird es mit:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">cd</span> -
</span></span></code></pre></div>
<h2 id="aktuelles-verzeichnis" data-numberify>aktuelles Verzeichnis<a class="anchor ms-1" href="#aktuelles-verzeichnis"></a></h2>
<p>Das aktuelle Verzeichnis kann man sich mit <code>pwd</code> ausgeben lassen.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">pwd</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">erde:~$ <span class="nb">cd</span> /etc
</span></span><span class="line"><span class="ln">2</span><span class="cl">erde:/etc$ <span class="nb">cd</span> /var
</span></span><span class="line"><span class="ln">3</span><span class="cl">erde:/var$ <span class="nb">cd</span> -
</span></span><span class="line"><span class="ln">4</span><span class="cl">/etc
</span></span><span class="line"><span class="ln">5</span><span class="cl">erde:/etc$ <span class="nb">cd</span> <span class="nv">$OLDPWD</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">erde:/var$
</span></span></code></pre></div>
<h2 id="schreiben-auf-stderr" data-numberify>Schreiben auf STDERR<a class="anchor ms-1" href="#schreiben-auf-stderr"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Dieser Text erscheint auf STDERR&#34;</span> &gt;<span class="p">&amp;</span><span class="m">2</span>
</span></span></code></pre></div>
<h2 id="fehlermeldungen-umleiten" data-numberify>Fehlermeldungen umleiten<a class="anchor ms-1" href="#fehlermeldungen-umleiten"></a></h2>

<h3 id="in-log-datei" data-numberify>in Log-Datei<a class="anchor ms-1" href="#in-log-datei"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">./foo.sh bar/* &gt;foo-bar.log  2&gt;<span class="p">&amp;</span><span class="m">1</span>
</span></span></code></pre></div>
<h3 id="wegwerfen" data-numberify>wegwerfen<a class="anchor ms-1" href="#wegwerfen"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">./foo.sh &gt; /dev/null 2&gt;<span class="p">&amp;</span><span class="m">1</span>
</span></span></code></pre></div>
<h2 id="backup-einer-datei" data-numberify>Backup einer Datei<a class="anchor ms-1" href="#backup-einer-datei"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">cp -p foo<span class="o">{</span>,.bak<span class="o">}</span>
</span></span></code></pre></div><p>ist dasselbe wie</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">cp -p foo foo.bak
</span></span></code></pre></div>
<h2 id="spezial-variablen" data-numberify>Spezial-Variablen<a class="anchor ms-1" href="#spezial-variablen"></a></h2>
<p>Es gibt ein paar Spezialvariablen in der bash, die einem das Tippen
ersparen.</p>

<h3 id="umgebungsvariablen" data-numberify>Umgebungsvariablen<a class="anchor ms-1" href="#umgebungsvariablen"></a></h3>
<table>
  <thead>
      <tr>
          <th>Name</th>
          <th>Erklärung</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>$$</code></td>
          <td>Prozess-ID (PID) des laufenden Programms</td>
      </tr>
      <tr>
          <td><code>$?</code></td>
          <td>Rückgabewert des letzten Befehls</td>
      </tr>
  </tbody>
</table>

<h3 id="in-scripten" data-numberify>in Scripten<a class="anchor ms-1" href="#in-scripten"></a></h3>
<p><code>$*</code> Alle dem Programm übergebenen Parameter, durch Leerzeichen getrennt.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nv">$*</span><span class="o">=</span><span class="nv">$1</span> <span class="nv">$2</span> <span class="nv">$3</span> <span class="nv">$4</span> ...
</span></span></code></pre></div><p><code>&quot;$*&quot; </code>	Alle dem Programm übergebenen Parameter in Anführungszeichen, durch das 1. Zeichen der Variablen $IFS getrennt.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="s2">&#34;</span><span class="nv">$*</span><span class="s2">&#34;</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">c</span><span class="nv">$2</span><span class="s2">c</span><span class="nv">$3</span><span class="s2">c</span><span class="nv">$4</span><span class="s2">&#34;</span>...
</span></span></code></pre></div><p><code>$@ </code>	Alle dem Programm übergebenen Parameter, durch Leerzeichen getrennt.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nv">$@</span><span class="o">=</span><span class="nv">$1</span> <span class="nv">$2</span> <span class="nv">$3</span> <span class="nv">$4</span>
</span></span></code></pre></div><p><code>&quot;$@&quot;</code> 	Alle dem Programm übergebenen Parameter, einzeln in Anführungszeichen eingeschlossen und durch Leerzeichen getrennt.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="s2">&#34;</span><span class="nv">$@</span><span class="s2">&#34;</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$2</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$3</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="nv">$4</span><span class="s2">&#34;</span> ...
</span></span></code></pre></div><p><code>$#</code> 	Anzahl der übergebenen Parameter</p>

<h3 id="historie" data-numberify>Historie<a class="anchor ms-1" href="#historie"></a></h3>
<p><code>!$</code>   letzter Parameter des vorhergehenden Befehls</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">$ ls -l foo
</span></span><span class="line"><span class="ln">2</span><span class="cl">$ <span class="nb">echo</span> !$
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">echo</span> foo
</span></span><span class="line"><span class="ln">4</span><span class="cl">foo
</span></span></code></pre></div><p><code>!!</code>   letzter Befehl inkl. aller Parameter</p>

<h4 id="mal-wieder-sudo-vergessen-kein-problem" data-numberify>Mal wieder sudo vergessen? Kein Problem:<a class="anchor ms-1" href="#mal-wieder-sudo-vergessen-kein-problem"></a></h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">$ ein script
</span></span><span class="line"><span class="ln">2</span><span class="cl">$ sudo !!
</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>kurz</th>
          <th>lang</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>history 10</code></td>
          <td><code>history | tail</code></td>
      </tr>
      <tr>
          <td><code>cd !$:h</code></td>
          <td><code>cd !!:$:h</code></td>
      </tr>
  </tbody>
</table>
<p><strong>Beispiel</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">$ ls -l /etc/apt/apt.conf.d/20auto-upgrades 
</span></span><span class="line"><span class="ln">2</span><span class="cl">$ <span class="nb">cd</span> !$:h
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">cd</span> /etc/apt/apt.conf.d
</span></span></code></pre></div>
<h4 id="eselsbrücke-regex-like" data-numberify>Eselsbrücke: RegEx-like<a class="anchor ms-1" href="#eselsbrücke-regex-like"></a></h4>
<table>
  <thead>
      <tr>
          <th>Eingabe</th>
          <th>Funktion</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>!?abc</code></td>
          <td>das erste Kommando in der History suchen, das <code>abc</code> enthält</td>
      </tr>
      <tr>
          <td><code>!abc</code></td>
          <td>das erste Kommando in der History suchen, das mit <code>abc</code> beginnt</td>
      </tr>
      <tr>
          <td><code>!!</code></td>
          <td>zuletzt aufgerufener Befehl</td>
      </tr>
      <tr>
          <td><code>!^</code></td>
          <td>erster Parameter im vorherigen Befehl</td>
      </tr>
      <tr>
          <td><code>!*</code></td>
          <td>alle Parameter im vorherigen Befehl</td>
      </tr>
      <tr>
          <td><code>!$</code></td>
          <td>letzter Parameter im vorherigen Befehl</td>
      </tr>
      <tr>
          <td><code>!n</code></td>
          <td>Befehl an Position <code>n</code> in der History</td>
      </tr>
      <tr>
          <td><code>!-n</code></td>
          <td>Befehl, der an der <code>n</code>-ten Stelle von hinten in der History steht <code>:2</code></td>
      </tr>
      <tr>
          <td><code>:2</code></td>
          <td>Nur der zweite Parameter des Befehls</td>
      </tr>
      <tr>
          <td><code>:2-5</code></td>
          <td>der zweite bis fünfte Parameter des Befehls</td>
      </tr>
      <tr>
          <td><code>:2-$</code></td>
          <td>der zweite und alle weiteren Parameter des Befehls</td>
      </tr>
      <tr>
          <td><code>:*</code></td>
          <td>Sämtliche Parameter des Befehls</td>
      </tr>
      <tr>
          <td><code>:q</code></td>
          <td>den Text in Anführungsstriche setzen</td>
      </tr>
      <tr>
          <td><code>:p</code></td>
          <td>&quot;print&quot; den Befehl nur ausgeben</td>
      </tr>
      <tr>
          <td><code>:h</code></td>
          <td>≈ <code>dirname</code> in einer Pfadangabe das Ende abschneiden <code>/etc/apt/apt.conf.d</code></td>
      </tr>
      <tr>
          <td><code>:t</code></td>
          <td>≈ <code>basename</code> das Ende einer Pfadangabe (zum Beispiel der Dateiname) <code>20auto-upgrades</code></td>
      </tr>
      <tr>
          <td></td>
          <td><code>ls -l /foo/bar.baz</code></td>
      </tr>
      <tr>
          <td><code>:r</code></td>
          <td><strong>remove</strong> alles hinter dem letzten Punkt <strong>abschneiden</strong> (zum Beispiel die Dateiendung) <code>/foo/bar</code></td>
      </tr>
      <tr>
          <td><code>:e</code></td>
          <td><strong>Endung</strong> alles hinter dem letzten Punkt (zum Beispiel die Dateiendung) = <code>baz</code></td>
      </tr>
  </tbody>
</table>
<p><strong>Beispiel Befehlssuche</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">$ <span class="nb">echo</span> foo bar baz
</span></span><span class="line"><span class="ln">2</span><span class="cl">foo bar baz
</span></span><span class="line"><span class="ln">3</span><span class="cl">$ <span class="nb">echo</span> !echo:2
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="nb">echo</span> bar
</span></span><span class="line"><span class="ln">5</span><span class="cl">bar
</span></span></code></pre></div><p>Nur ausgeben:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">$ <span class="nb">echo</span> foo bar baz
</span></span><span class="line"><span class="ln">2</span><span class="cl">foo bar baz
</span></span><span class="line"><span class="ln">3</span><span class="cl">$ <span class="nb">echo</span> !echo:2:p
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="nb">echo</span> bar
</span></span></code></pre></div>
<h2 id="schnell-in-bash-mal-würfeln" data-numberify>schnell in bash mal würfeln<a class="anchor ms-1" href="#schnell-in-bash-mal-würfeln"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">let</span> <span class="nv">zufallszahl</span><span class="o">=</span><span class="nv">$RANDOM</span>%6
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">echo</span> <span class="nv">$zufallszahl</span>
</span></span></code></pre></div><table>
  <thead>
      <tr>
          <th>Datum</th>
          <th>Änderung</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>03.11.2023</td>
          <td>Passwort generieren</td>
      </tr>
      <tr>
          <td>14.02.2024</td>
          <td>Hinweis auf <code>gen_passwort.sh</code> im GitLab-Repository</td>
      </tr>
      <tr>
          <td>11.09.2024</td>
          <td>fallocate</td>
      </tr>
      <tr>
          <td>22.09.2024</td>
          <td>Bootstick</td>
      </tr>
      <tr>
          <td>13.11.2024</td>
          <td>Fix Typo</td>
      </tr>
      <tr>
          <td>10.02.2026</td>
          <td>Zufallszahl mehr erläutert</td>
      </tr>
  </tbody>
</table>]]></content:encoded>
    </item>
    
    <item>
      <title>Sonstiges</title>
      <link>https://www.rainerrose.de/docs/linux/sonstiges/</link>
      <pubDate>Fri, 28 Jun 2024 23:16:19 +0200</pubDate>
      <guid>https://www.rainerrose.de/docs/linux/sonstiges/</guid>
      <description><![CDATA[<!-- Anreißer -->
<p>Alles was nicht so recht in eine Kategorie passt oder wo ich zu faul war zu kategorisieren. :-D</p>

<h2 id="curl-mit-ipv6" data-numberify>curl mit IPv6<a class="anchor ms-1" href="#curl-mit-ipv6"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl  <span class="s2">&#34;http://[ipv6:addresse]:port/&#34;</span>
</span></span></code></pre></div>
<h2 id="root-passwort-wieder-löschen" data-numberify>root passwort wieder löschen<a class="anchor ms-1" href="#root-passwort-wieder-löschen"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">passwd -dl root
</span></span></code></pre></div>
<h2 id="magic-sys-key" data-numberify>Magic Sys Key<a class="anchor ms-1" href="#magic-sys-key"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">echo</span> s &gt; /proc/sysrq-trigger
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">echo</span> u &gt; /proc/sysrq-trigger
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">echo</span> b &gt; /proc/sysrq-trigger
</span></span></code></pre></div><p>Und im Falle von Turnschuhnetzwerk und direkt vor dem Rechner geht das auch mit:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln">1</span><span class="cl">ALT-PrintScr-S
</span></span><span class="line"><span class="ln">2</span><span class="cl">ALT-PrintScr-U
</span></span><span class="line"><span class="ln">3</span><span class="cl">ALT-PrintScr-B 
</span></span></code></pre></div>]]></description>
      <content:encoded><![CDATA[<!-- Anreißer -->
<p>Alles was nicht so recht in eine Kategorie passt oder wo ich zu faul war zu kategorisieren. :-D</p>

<h2 id="curl-mit-ipv6" data-numberify>curl mit IPv6<a class="anchor ms-1" href="#curl-mit-ipv6"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl  <span class="s2">&#34;http://[ipv6:addresse]:port/&#34;</span>
</span></span></code></pre></div>
<h2 id="root-passwort-wieder-löschen" data-numberify>root passwort wieder löschen<a class="anchor ms-1" href="#root-passwort-wieder-löschen"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">passwd -dl root
</span></span></code></pre></div>
<h2 id="magic-sys-key" data-numberify>Magic Sys Key<a class="anchor ms-1" href="#magic-sys-key"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">echo</span> s &gt; /proc/sysrq-trigger
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">echo</span> u &gt; /proc/sysrq-trigger
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">echo</span> b &gt; /proc/sysrq-trigger
</span></span></code></pre></div><p>Und im Falle von Turnschuhnetzwerk und direkt vor dem Rechner geht das auch mit:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln">1</span><span class="cl">ALT-PrintScr-S
</span></span><span class="line"><span class="ln">2</span><span class="cl">ALT-PrintScr-U
</span></span><span class="line"><span class="ln">3</span><span class="cl">ALT-PrintScr-B 
</span></span></code></pre></div>
<h2 id="xubuntu-auf-neues-distro-upgrade-checken" data-numberify>XUbuntu auf neues Distro-Upgrade checken<a class="anchor ms-1" href="#xubuntu-auf-neues-distro-upgrade-checken"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">do</span>-release-upgrade -c
</span></span></code></pre></div>
<h2 id="resolvconf-wird-immer-überschrieben" data-numberify>resolv.conf wird immer überschrieben<a class="anchor ms-1" href="#resolvconf-wird-immer-überschrieben"></a></h2>
<p>Nach Änderung des DNS-Servers wird die <code>/etc/resolv.conf</code> immer wieder überschrieben?</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">systemctl restart NetworkManager.service
</span></span></code></pre></div><p>Erst mal alle Interfaces anzeigen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">nmcli -p connection show
</span></span></code></pre></div><p>In diesem Fall half, das Interface neu hochzufahren</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">nmcli c up enp0s8
</span></span></code></pre></div>
<h2 id="netzwerkkarten-konfiguration" data-numberify>Netzwerkkarten-Konfiguration<a class="anchor ms-1" href="#netzwerkkarten-konfiguration"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">nmtui
</span></span><span class="line"><span class="ln">2</span><span class="cl">systemctl restart NetworkManager.service
</span></span><span class="line"><span class="ln">3</span><span class="cl">ip link <span class="nb">set</span> enp0s8 down
</span></span><span class="line"><span class="ln">4</span><span class="cl">ip link <span class="nb">set</span> enp0s8 up
</span></span></code></pre></div>
<h2 id="ignore-case-bei-less" data-numberify>Ignore case bei less<a class="anchor ms-1" href="#ignore-case-bei-less"></a></h2>
<ol>
<li>im Befehlsmodus <code>-i</code></li>
<li>gleich als Parameter aufrufen <code>less -i</code></li>
</ol>

<h2 id="eben-mal-schnell-konvertieren" data-numberify>Eben mal schnell konvertieren<a class="anchor ms-1" href="#eben-mal-schnell-konvertieren"></a></h2>
<p>Eben mal schnell ein Dokument von einem Format ins andere konvertieren? Nicht überall gibt es <code>pandoc</code> oder zum Teil nur in einer veralteten Version. <code>docker</code> hilft hier:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker run --rm --volume <span class="s2">&#34;`pwd`:/data&#34;</span> --user <span class="sb">`</span>id -u<span class="sb">`</span>:<span class="sb">`</span>id -g<span class="sb">`</span> pandoc/latex <span class="nv">$*</span>
</span></span></code></pre></div><p>Benennt man das Script z.B. <code>pandoc.sh</code> lässt es sich zum Beispiel so von Markdown in Dokuwiki umwandeln</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">pandoc.sh -f markdown -t dokuwiki index.md
</span></span></code></pre></div>
<h2 id="usb-palm" data-numberify>USB-Palm<a class="anchor ms-1" href="#usb-palm"></a></h2>
<p>Wo schließe ich denn meinen USB-Palm an? Das Device heiß:
<code>/dev/usb/ttyUSB1</code></p>
<p>Im Kernel ist es zu konfigurieren als:</p>
<pre><code>USB support ---&gt; USB Serial Converter support ---&gt; USB Serial Converter support
USB Handspring Visor / Palm m50x / Sony Clie Driver
</code></pre>
<p>Am besten einfach einen symbolischen Link drauflegen.</p>

<h2 id="suchen-eines-textes-in-dateien-im-aktuellen-verzeichnis" data-numberify>Suchen eines Textes in Dateien im aktuellen Verzeichnis<a class="anchor ms-1" href="#suchen-eines-textes-in-dateien-im-aktuellen-verzeichnis"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">find . <span class="p">|</span> xargs grep Suchmuster 2&gt; /dev/null
</span></span></code></pre></div>
<h2 id="vergessen-in-welches-verzeichnis-ein-programm-installiert-wurde" data-numberify>Vergessen, in welches Verzeichnis ein Programm installiert wurde?<a class="anchor ms-1" href="#vergessen-in-welches-verzeichnis-ein-programm-installiert-wurde"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">which Programm-Name
</span></span></code></pre></div><p>liefert den absoluten Pfad, sofern es sich im Suchpfad befindet.</p>

<h2 id="scsii-zip-drive" data-numberify>SCSII-ZIP-Drive<a class="anchor ms-1" href="#scsii-zip-drive"></a></h2>
<p>Das SCSII-ZIP-Drive erst nach dem booten angeschlossen?</p>
<p>Kein Problem:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;scsi add-single-device 0 0 6 0&#34;</span> &gt; /proc/scsi/scsi
</span></span></code></pre></div><p>und mit</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">mount -t dateisystem /dev/sd?4 /mnt
</span></span></code></pre></div><p>ins Dateisystem einhängen.</p>
<p>Falls das ZIP-Drive die ID <code>5</code> hat, einfach oben die <code>6</code> durch die <code>5</code>
ersetzen.</p>

<h2 id="multivolume-archive-erstellen" data-numberify>Multivolume Archive erstellen<a class="anchor ms-1" href="#multivolume-archive-erstellen"></a></h2>

<h3 id="mit-gleichem-dateinamen" data-numberify>Mit gleichem Dateinamen<a class="anchor ms-1" href="#mit-gleichem-dateinamen"></a></h3>
<p>erstellen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">tar -c -L &lt;Größe in MB&gt; -f &lt;arch.tar&gt;
</span></span></code></pre></div><p>entpacken:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">tar -xMf &lt;archiv.tar&gt;
</span></span></code></pre></div><p>Mit unterschiedlichem Dateinamen (<code>archiv.tar.aa, archiv.tar..ab, archiv.tar..ac, archiv.tar..&lt;PREFIX&gt;...</code> )</p>

<h3 id="mit-temporärer-datei" data-numberify>Mit temporärer Datei<a class="anchor ms-1" href="#mit-temporärer-datei"></a></h3>
<p>erstellen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">tar -czf &lt;archiv.tar&gt; &lt;Source&gt;<span class="p">;</span> split -b&lt;Größe in MB&gt;M &lt;archiv.tar&gt; &lt;archiv.tar.split.&gt;
</span></span></code></pre></div><p>Bsp (95MB-Archive):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">tar czf /mnt/zip /home/user<span class="p">;</span> split -b95 archiv.tz archiv.tgz.split.
</span></span></code></pre></div><p>entpacken:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">cat &lt;archiv.tar.split.&gt;* &gt; archiv.tar
</span></span></code></pre></div><p>Bsp:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">cat archiv.tgz.split.* &gt; archiv.tgz
</span></span></code></pre></div>
<h3 id="ohne-temporärer-datei" data-numberify>ohne temporärer Datei<a class="anchor ms-1" href="#ohne-temporärer-datei"></a></h3>
<p>erstellen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">tar cz &lt;Source&gt; <span class="p">|</span> split -b&lt;Größe in MB&gt;M &lt;archiv.tar.split.&gt;
</span></span></code></pre></div><p>Bsp (95MB-Archive):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">tar cz /home/user <span class="p">|</span> split -b95M - archiv.tgz.split.
</span></span></code></pre></div><p>entpacken:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">cat &lt;archiv.tar.split.*&gt; <span class="p">|</span> tar xz
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="sb">```</span> bash
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">Bsp: 
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="sb">```</span> bash
</span></span><span class="line"><span class="ln">6</span><span class="cl">cat archiv.tgz.split.* <span class="p">|</span> tar xz
</span></span></code></pre></div><p>entpacken unter Dos:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">copy /b archiv.tgz.split.aa+archiv.tgz.split.ab+archiv.split.ac archiv.tgz
</span></span></code></pre></div><p>Alle Dateien müssen beim <code>copy</code>-Befehl angegeben werden! Danach normal
das tgz-Archiv entpacken.</p>

<h2 id="datei-endung-datei-format-verbaselt-gelöscht-unbekannt" data-numberify>Datei-Endung, Datei-Format verbaselt, gelöscht, unbekannt<a class="anchor ms-1" href="#datei-endung-datei-format-verbaselt-gelöscht-unbekannt"></a></h2>
<p>mit dem kleinen Progrämmchen file bekommen Sie es heraus.</p>
<p>Beispiel:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">file unbekanntes_Datei-Format
</span></span><span class="line"><span class="ln">2</span><span class="cl">unbekanntes_Datei-Format: gzip compressed data, deflated, last modified: Wed Jan <span class="m">16</span> 21:36:14 2002, os: Unix
</span></span></code></pre></div>
<h2 id="attachments-in-der-mail" data-numberify>Attachments in der Mail<a class="anchor ms-1" href="#attachments-in-der-mail"></a></h2>
<p>Man kennt, es. Attachments landen mal wieder in der Mail.</p>
<ol>
<li>Mail in einer TextDatei abspeichern.</li>
<li>Alles vor dem: <code>begin 666 dateiname</code> in der Textdatei löschen.</li>
<li><code>uudecode -oneuer_dateiname codierte_datei_im_bin_format</code></li>
</ol>
<p>Fertich. (Version: uudecode (GNU sharutils) 4.2c)</p>

<h2 id="reguläre-ausdrücke" data-numberify>Reguläre Ausdrücke<a class="anchor ms-1" href="#reguläre-ausdrücke"></a></h2>
<p>Reguläre Ausdrücke (Englisch: Regular Expression, RegExp) sind
Suchmuster, die mittels Platzhalterzeichen (Jokers) gebildet werden. Sie
dienen hauptsächlich zum Suchen nach und dem Ersetzen von Textstellen.
Platzhalterzeichen sind Sonderzeichen wie z.B. der Stern (<code>*</code>) unter DOS
und Windows. Anders als dort sind in der Unix-Welt Reguläre Ausdrücke
mit zahlreichen weiteren Platzhalterzeichen und -sequenzen möglich. Die
wichtigsten sind nachstehend aufgeführt:</p>
<table>
  <thead>
      <tr>
          <th>Steuerzeichen</th>
          <th>Erläuterung</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>[xyz...]</code></td>
          <td>Eines dieser Zeichen</td>
      </tr>
      <tr>
          <td><code>[^xyz...]</code></td>
          <td>Keines dieser Zeichen</td>
      </tr>
      <tr>
          <td><code>.</code></td>
          <td>Ein beliebiges Zeichen</td>
      </tr>
      <tr>
          <td><code>.*</code></td>
          <td>Keines, eines oder mehrere beliebige Zeichen. Greedy (gefräßig)Suche</td>
      </tr>
      <tr>
          <td><code>.+</code></td>
          <td>Eines oder mehrere beliebige Zeichen</td>
      </tr>
      <tr>
          <td><code>.?</code></td>
          <td>Keines oder ein beliebiges Zeichen</td>
      </tr>
      <tr>
          <td><code>.*?</code></td>
          <td>lazy Suche. Möglichst viel, aber auch möglichst wenig. Quasi beim ersten Treffer aufhören. Gegenteil von greedy</td>
      </tr>
      <tr>
          <td><code>$</code></td>
          <td>Am Ende einer Zeile</td>
      </tr>
      <tr>
          <td><code>^</code></td>
          <td>Am Anfang einer Zeile</td>
      </tr>
      <tr>
          <td><code>(...)</code></td>
          <td>Gruppe von Zeichen</td>
      </tr>
      <tr>
          <td><code>\</code></td>
          <td>Schutzzeichen für Jokers (wird vorangestellt, wenn z.B. nach . oder * gesucht wird)</td>
      </tr>
  </tbody>
</table>
<p>Reguläre Ausdrücke sind eine (mathematische) Wissenschaft für sich, und
es gibt ganze Bücher darüber. Die Anwendungen sind sehr vielfältig.</p>

<h2 id="strom-sparen" data-numberify>Strom sparen<a class="anchor ms-1" href="#strom-sparen"></a></h2>
<p>Bildschirmschoner sollte man deaktivieren. Sie verbrauchen nur CPU-Zeit
(damit Strom) und der Monitor nicht auch noch Strom verbraucht. Der
VESA-DPMS-Standard schaltet nämlich den Bildschirm selbstständig ab.</p>
<p>Ob der VESA-DPMS-Standard aktiviert ist, bekommt man durch die Eingabe
von:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">xset -q
</span></span></code></pre></div><p>auf der Kommandozeile zu sehen.</p>
<p>Neben verschiedenen Ausgaben sollte die aktuelle DPMS-Konfiguration eine
Antwort geben.</p>
<p>Die Zahlen geben wieder nach welchen Zeitabständen der Monitor die
nächste Stufe des DPMS-Standards annimmt.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">xset
</span></span></code></pre></div><p>mit &quot;DPMS is disabled&quot; sollten Sie:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">xset dpms
</span></span></code></pre></div><p>oder</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">xset dpms <span class="m">60</span> <span class="m">120</span> <span class="m">180</span>
</span></span></code></pre></div><p>DPMS aktivieren (mit 1, 2 und 3 Minuten).</p>
<p>Wird der xdm verwendet hilft zudem ein Eintrag in: <code>/etc/X11/xdm/Xsetup</code></p>
<p>Ein Ändern der Zeile von von <code>no</code> in <code>yes</code>.</p>
<p>Unter <em>KDE</em> im Kontroll-Zentrum beim Unterpunkt Energie-Kontrolle.</p>
<p>Unter <em>GNOME</em> ebenfalls im Kontroll-Zentrum.</p>
<p><code>CONFIG_APM_CPU_IDLE=y</code> in der Kernel-Konfiguration sorgt für einen
Stromsparmodus der CPU auf Kernelebene.</p>

<h2 id="letzte-zugriffszeit" data-numberify>letzte Zugriffszeit<a class="anchor ms-1" href="#letzte-zugriffszeit"></a></h2>
<p>Wer die letzte Zugriffszeit von seinen Dateien nicht braucht, kann zudem
seine Partitionen mit dem Parameter:</p>
<pre><code>noatime
</code></pre>
<p>mounten. Bei Dateien, die nur häufig gelesen werden, und sich eh im RAM
befinden, spart man somit einen Schreibzugriff. Bei Laptops mit fast
leerem Akku lebenswichtig.</p>

<h2 id="java-applets-unter-firefox" data-numberify>Java(-Applets) unter Firefox<a class="anchor ms-1" href="#java-applets-unter-firefox"></a></h2>
<p>Wenn es noch nicht existiert, <code>plugins</code>-Verzeichnis im Homeverzeichnis
des Firefox anlegen. Z.B.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">mkdir ~/.mozilla/plugins
</span></span></code></pre></div><p>Jetzt nur noch ein Symlink auf die Libary <code>libjavaplugin_oji.so</code> aus dem
JRE oder SDK in das <code>plugins</code>-Verzeichnis anlegen.</p>
<p>Ist etwas Sucharbeit, müsste sich aber finden lassen. Die besten
Erfahrungen habe ich mit dem JRE von Sun selbst gemacht. Bei vielen
Distributionen lässt sich das Java aber inzwischen auch per
Paketverwaltung als Plugin systemweit nachinstallieren. Der Ort der
Java-Installation lässt sich aus der Umgebungsvariablen JAVA_HOME
ablesen.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">echo</span> <span class="nv">$JAVA_HOME</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">/opt/java/jre
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">cd</span> ~/.mozilla/plugins
</span></span><span class="line"><span class="ln">4</span><span class="cl">ln -s /opt/java/jre/plugin/i386/ns610-gcc32/libjavaplugin_oji.so libjavaplugin_oji.so
</span></span></code></pre></div><p>&lt;note tip&gt;Inzwischen nutze ich OpenJDK und das ist genauso
gut&lt;/note&gt;</p>
<p>Jetzt noch den Firefox neu starten und das Plugin sollte benutzbar sein
sowie unter <code>about:plugins</code> auftauchen.</p>

<h2 id="mime-type--encoding-einer-datei-identifizieren" data-numberify>MIME-Type / Encoding einer Datei identifizieren<a class="anchor ms-1" href="#mime-type--encoding-einer-datei-identifizieren"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">file –bi &lt;dateiname&gt;
</span></span></code></pre></div>
<h2 id="avidemux-meldet-defekte-avi-datei" data-numberify>avidemux meldet defekte avi-Datei<a class="anchor ms-1" href="#avidemux-meldet-defekte-avi-datei"></a></h2>
<p>Reparatur mit:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">avconv -i defekt.avi -codec copy reparatiert.avi
</span></span></code></pre></div>
<h2 id="ip-adresse" data-numberify>IP-Adresse<a class="anchor ms-1" href="#ip-adresse"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hostname -i
</span></span></code></pre></div>
<h2 id="md5" data-numberify>md5<a class="anchor ms-1" href="#md5"></a></h2>
<p>md5-Summe in Text-Datei mit Dateinamen reinschreiben</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;2317a049f2c83b735e75cad08022247b foo.sh&#34;</span> &gt; foo.md5.txt
</span></span></code></pre></div><p>Checken mit Download, der dann <code>foo.sh</code> im Dateinamen haben muss.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">md5sum -c foo.md5.txt
</span></span></code></pre></div>
<h2 id="einstellungen-von-putty-exportieren--importieren" data-numberify>Einstellungen von PuTTY exportieren / importieren<a class="anchor ms-1" href="#einstellungen-von-putty-exportieren--importieren"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln">1</span><span class="cl">regedit /e &#34;%userprofile%\Desktop\PuttyEinstellungen.reg&#34; HKEY_CURRENT_USER\Software\Simontatham
</span></span></code></pre></div><p>legt reg-Datei auf den Desktop. Per Doppelklick $IRGENDWO wieder
importieren, fertig.</p>

<h2 id="patch-files" data-numberify>Patch-Files<a class="anchor ms-1" href="#patch-files"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">diff -u original.txt modifiziert.txt &gt; original.patch
</span></span></code></pre></div><p>patch -u working.slang.c -i slang.patch</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">patch -b -u original.txt -i original.patch
</span></span></code></pre></div><p><code>-b</code> für Backup</p>

<h2 id="changelog" data-numberify>Changelog<a class="anchor ms-1" href="#changelog"></a></h2>
<table>
  <thead>
      <tr>
          <th>Datum</th>
          <th>Änderung</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>30.10.2023</td>
          <td>Xubuntu-Distro-Upgrade Tipp</td>
      </tr>
      <tr>
          <td>14.11.2023</td>
          <td>Magic Sys Key</td>
      </tr>
      <tr>
          <td>28.06.2024</td>
          <td>curl mit IPv6</td>
      </tr>
      <tr>
          <td>28.12.2024</td>
          <td>Systemd-Timer umgelagert auf <a href="../systemd">Systemd</a>.</td>
      </tr>
      <tr>
          <td>29.09.2025</td>
          <td>root passwort wieder löschen</td>
      </tr>
  </tbody>
</table>]]></content:encoded>
    </item>
    
    <item>
      <title>Docker</title>
      <link>https://www.rainerrose.de/docs/linux/docker/</link>
      <pubDate>Sat, 01 Jun 2024 16:28:13 +0200</pubDate>
      <guid>https://www.rainerrose.de/docs/linux/docker/</guid>
      <description><![CDATA[<!-- Anreißer -->
<p>Ein paar kleine Tricks und Kniffe zum Thema Docker.</p>]]></description>
      <content:encoded><![CDATA[<!-- Anreißer -->
<p>Ein paar kleine Tricks und Kniffe zum Thema Docker.</p>

<h2 id="mysqldump-ohne-passwort-in-prozessliste" data-numberify>mysqldump ohne Passwort in Prozessliste<a class="anchor ms-1" href="#mysqldump-ohne-passwort-in-prozessliste"></a></h2>
<p>Unter docker werden die Zugangsdaten meist über Umgebungsvariablen
weitergegeben.</p>
<p>Arbeitet man jedoch bei <code>mysqldump</code> mit dem Parameter <code>-p</code> gibt es
folgende Warnung</p>
<pre><code>mysqldump: [Warning] Using a password on the command line interface can be insecure.
</code></pre>
<p>Um jetzt nicht alles nach <code>/dev/null</code> umzuleiten, um noch echte Fehler
mitzubekommen, kann man mittels des Parameters <code>--defaults-file</code> das
Passwort in eine Datei kopieren. Da sich Zugangsdaten ändern können,
empfiehlt es sich, das dynamisch per Script zu erzeugen und das Passwort
aus der Umgebungsvariable des Containers auszulesen.</p>
<p>Das Script legt man entweder in ein lokales Volume oder kopiert es via
<code>docker cp</code> in den Container.</p>
<p>Das Beispiel-Script zum dynamischen Erzeugen der Credentials-Datei:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="cp"></span><span class="nv">CRED_FILE</span><span class="o">=</span><span class="s2">&#34;/docker-entrypoint-initdb.d/credentials-root.conf&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1">#loeschen</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">&gt; <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CRED_FILE</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">chmod <span class="m">600</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CRED_FILE</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;[client]&#34;</span> &gt;&gt;  <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CRED_FILE</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;password=</span><span class="si">${</span><span class="nv">MYSQL_ROOT_PASSWORD</span><span class="si">}</span><span class="s2">&#34;</span> &gt;&gt; <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CRED_FILE</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span></code></pre></div><p>Und noch ein Auszug aus einem Backup-Script:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker <span class="nb">exec</span> -i  onlyoffice-mysql-server  /bin/bash /docker-entrypoint-initdb.d/gen_cred_config.sh
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="o">(</span>docker <span class="nb">exec</span> -i onlyoffice-mysql-server mysqldump  --defaults-file<span class="o">=</span>/docker-entrypoint-initdb.d/credentials-root.conf &lt;weitere Dump-Parameter&gt;  -u root -h&lt;hostname&gt;  <span class="p">|</span> xz -c &gt; <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUPDIR</span><span class="si">}</span><span class="s2">/dump.sql.xz&#34;</span>
</span></span></code></pre></div>
<h2 id="umgebungsvariable-aus-docker-container-auslesen" data-numberify>Umgebungsvariable aus Docker-Container auslesen<a class="anchor ms-1" href="#umgebungsvariable-aus-docker-container-auslesen"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker <span class="nb">exec</span> -i onlyoffice-community-server /bin/bash -c <span class="s1">&#39;/bin/echo ${MYSQL_SERVER_PASS}&#39;</span>
</span></span></code></pre></div>
<h2 id="unterordner-in-docker-volume-ignorieren" data-numberify>Unterordner in Docker-Volume ignorieren<a class="anchor ms-1" href="#unterordner-in-docker-volume-ignorieren"></a></h2>
<p>Dem <code>docker-compose</code> ein Verzeichnis der lokalen Maschine übergeben,
aber einzelne Unterverszeichnisse davon ausnehmen:</p>
<p>Das funktioniert, indem für die auszunehmenden Unterordner ein zweites
Volume angeben wird. Volume darf keine Zuordnung mit einem Doppelpunkt
enhalten:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w"></span>- <span class="l">./webseite/html:/var/www/html</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w"></span>- <span class="l">/var/www/html/static/</span><span class="w">
</span></span></span></code></pre></div><p>Im Beispiel bekommt ein Webserver die ganze Webseite übergeben, der
Ordner <code>static</code> wird aber aus dem Container benutzt.</p>

<h2 id="backups--recover-via-volume-mounten" data-numberify>Backups & Recover via Volume mounten<a class="anchor ms-1" href="#backups--recover-via-volume-mounten"></a></h2>

<h3 id="reingucken" data-numberify>reingucken<a class="anchor ms-1" href="#reingucken"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker run -it --rm -v portainer_data:/data:ro -v <span class="k">$(</span><span class="nb">pwd</span><span class="k">)</span>:/backup alpine /bin/sh
</span></span></code></pre></div>
<h3 id="sichern" data-numberify>sichern<a class="anchor ms-1" href="#sichern"></a></h3>

<h4 id="variante-1" data-numberify>Variante 1<a class="anchor ms-1" href="#variante-1"></a></h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker run --rm -v portainer_data:/data:ro -v <span class="k">$(</span><span class="nb">pwd</span><span class="k">)</span>:/backup alpine tar cjvf /backup/data.tbz2 -C /data ./
</span></span></code></pre></div>
<h4 id="variante-2" data-numberify>Variante 2<a class="anchor ms-1" href="#variante-2"></a></h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker run --rm -v portainer_data:/data alpine tar cf - -C /data ./ <span class="p">|</span> xz &gt; ./portainer_data_volume.txz
</span></span></code></pre></div>
<h3 id="recover" data-numberify>Recover<a class="anchor ms-1" href="#recover"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker run --rm -v portainer_data:/data -v ./portainer_data_volume.txz:/backup.tgz alpine tar tJf -C /data /backup.tgz
</span></span></code></pre></div>
<h2 id="volumes" data-numberify>Volumes<a class="anchor ms-1" href="#volumes"></a></h2>
<p>Wie unterscheiden sich nochmal die Bezeichnungen bei den Volumes?</p>
<ul>
<li>bind volume</li>
<li>named volume</li>
<li>volume</li>
</ul>

<h2 id="logfiles-auf-die-konsole" data-numberify>Logfiles auf die Konsole<a class="anchor ms-1" href="#logfiles-auf-die-konsole"></a></h2>
<p>Logfile-Ausgaben können über STDOUT einfach an das &quot;Terminal&quot; geblasen
werden, der dann via <code>docker log &lt;container-name&gt;</code> bzw. Portainer
auslesbar ist.</p>
<p>Eine Apache-Konfig <code>conf-enabled/other-vhosts-access-log.conf</code> kann z.B. so aussehen:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-apache" data-lang="apache"><span class="line"><span class="ln">1</span><span class="cl"><span class="c"># Define an access log for VirtualHosts that don&#39;t define their own logfile</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">CustomLog</span> <span class="sx">/proc/self/fd/1</span> vhost_combined
</span></span></code></pre></div><p>Im Container selbst ist dann der Grund zu sehen, warum das funktioniert:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># ls -l /proc/self/fd/1</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">lrwx------. <span class="m">1</span> root root <span class="m">64</span> Jul  <span class="m">8</span> 16:19 /proc/self/fd/1 -&gt; /dev/pts/0
</span></span></code></pre></div><p>Habe ich mal in einem ubuntu-basierten Container gesehen, ziemlich
genial.</p>

<h2 id="docker-entrypoint" data-numberify>docker ENTRYPOINT<a class="anchor ms-1" href="#docker-entrypoint"></a></h2>
<p>Weil ich mir nie merken kann, wie wann was gestartet wird, hier mal eine Tabelle:</p>
<table>
  <thead>
      <tr>
          <th>ENTRYPOINT</th>
          <th>CMD</th>
          <th>run-Parameter</th>
          <th>ausgeführt wird</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>[&quot;script.sh&quot;]</code></td>
          <td></td>
          <td></td>
          <td><code>script.sh</code></td>
      </tr>
      <tr>
          <td><code>[&quot;script.sh&quot;]</code></td>
          <td></td>
          <td><code>/bin/bash</code></td>
          <td><code>script.sh /bin/bash</code></td>
      </tr>
      <tr>
          <td><code>[&quot;script.sh&quot;]</code></td>
          <td><code>[&quot;mysqld&quot;]</code></td>
          <td></td>
          <td><code>script.sh mysqld</code></td>
      </tr>
      <tr>
          <td><code>[&quot;script.sh&quot;]</code></td>
          <td><code>[&quot;mysqld&quot;]</code></td>
          <td><code>/bin/bash</code></td>
          <td><code>script.sh /bin/bash</code></td>
      </tr>
      <tr>
          <td></td>
          <td><code>[&quot;/bin/sh&quot;]</code></td>
          <td></td>
          <td><code>/bin/sh</code></td>
      </tr>
      <tr>
          <td></td>
          <td><code>[&quot;/bin/sh&quot;]</code></td>
          <td><code>/bin/bash</code></td>
          <td><code>/bin/bash</code></td>
      </tr>
  </tbody>
</table>

<h2 id="zeitzonen" data-numberify>Zeitzonen<a class="anchor ms-1" href="#zeitzonen"></a></h2>
<p>Die lokale Zeitzone lässt sich per Volume-Mount an den Container durchreichen, sofern die Applikation das unterstützt bzw. beachtet.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">      </span>- <span class="l">/etc/timezone:/etc/timezone:ro</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">      </span>- <span class="l">/etc/localtime:/etc/localtime:ro</span><span class="w">
</span></span></span></code></pre></div>
<h2 id="pull-und-restart" data-numberify>Pull und Restart<a class="anchor ms-1" href="#pull-und-restart"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker compose up -d --pull always
</span></span></code></pre></div><p>bzw.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker compose up -d --build --pull always
</span></span></code></pre></div>
<h2 id="erstellungsdatum-created-eines-images-abfragen" data-numberify>Erstellungsdatum (Created) eines Images abfragen<a class="anchor ms-1" href="#erstellungsdatum-created-eines-images-abfragen"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker inspect docker.io/photoprism/photoprism:latest -f <span class="s2">&#34;{{ .Created}}&#34;</span>
</span></span></code></pre></div>
<h2 id="changelog" data-numberify>Changelog<a class="anchor ms-1" href="#changelog"></a></h2>
<table>
  <thead>
      <tr>
          <th>Datum</th>
          <th>Änderung</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>08.11.2023</td>
          <td>Backup via Volume weitere Variante sowie Recover-Möglichkeit.</td>
      </tr>
      <tr>
          <td>01.06.2024</td>
          <td>docker ENTRYPOINT</td>
      </tr>
      <tr>
          <td>25.11.2024</td>
          <td>Zeitzonen-Volumes</td>
      </tr>
      <tr>
          <td>02.05.2025</td>
          <td>Pull und Restart</td>
      </tr>
      <tr>
          <td>24.03.2026</td>
          <td>Erstellungsdatum (Created) eines Images abfragen</td>
      </tr>
  </tbody>
</table>]]></content:encoded>
    </item>
    
    <item>
      <title>Monitoring Docker-Images</title>
      <link>https://www.rainerrose.de/posts/check_last_docker_pull/</link>
      <pubDate>Tue, 19 Dec 2023 17:52:17 +0200</pubDate>
      <guid>https://www.rainerrose.de/posts/check_last_docker_pull/</guid>
      <description><![CDATA[<!-- Anreißer --> 
<p>Ich stand vor der Herausforderung, dass ich wissen wollte, ob es für Docker-Images, die ich verwende, Updates bzw. eine neue Image-Version gibt. Der Klassiker ist <code>latest</code> wie z.B. bei <code>jellyfin/jellyfin:latest</code>. Aber auch Haupt-Versionen werden zum Teil benannt: <code>postgres:13</code> .</p>
<p>Bei der Verwendung von <code>docker compose</code> sind die Docker-Images sind z.B. in einer <code>docker-compose.yml</code>-Datei hinterlegt, wo ich das selbstgeschrieben Script <code>update_docker_images.sh</code> verwende, um die Container zu aktualisieren.</p>]]></description>
      <content:encoded><![CDATA[<!-- Anreißer --> 
<p>Ich stand vor der Herausforderung, dass ich wissen wollte, ob es für Docker-Images, die ich verwende, Updates bzw. eine neue Image-Version gibt. Der Klassiker ist <code>latest</code> wie z.B. bei <code>jellyfin/jellyfin:latest</code>. Aber auch Haupt-Versionen werden zum Teil benannt: <code>postgres:13</code> .</p>
<p>Bei der Verwendung von <code>docker compose</code> sind die Docker-Images sind z.B. in einer <code>docker-compose.yml</code>-Datei hinterlegt, wo ich das selbstgeschrieben Script <code>update_docker_images.sh</code> verwende, um die Container zu aktualisieren.</p>
<p>Mit dem Tool <a href="https://tools.rainerrose.de/redirect.php?id=34" target="_blank" rel="noopener noreferrer">watchtower<i class="fas fa-external-link-square-alt ms-1"></i></a> bin ich nicht zurecht gekommen bzw. es hat meine Anforderungen nicht erfüllt oder ich sie nicht umsetzen konnte.
Eine Hürde war, dass ein Teil der Server, die ich betreue, keinen Zugriff auf das Internet haben.
Ebenso baue ich durchaus eigene Images und Watchtower &ldquo;sieht&rdquo; meines Wissens nicht das <code>Dockerfile</code> was im Build-Prozess benötigt wird. Updates des verwendeten Basis-Images bekomme ich also nicht mit.</p>
<p>Somit musste eine eigene Lösung her. Zeitgleich hatte ich das Tool <code>jq</code> entdeckt und sah es als Möglichkeit, mich an einem konkreten Beispiel mit diesem auseinanderzusetzen.</p>

<h2 id="konfigurationsdatei" data-numberify>Konfigurationsdatei<a class="anchor ms-1" href="#konfigurationsdatei"></a></h2>
<p>Damit ich mir (bzw. das Script) merken kann, wann der letzte pull eines Docker-Images stattfand, brauche ich eine Konfigurationsdatei.</p>
<p>Der Aufbau der Konfigurationsdatei ist eine Datei im <code>json</code>-Format. Jeder Unterelement hat genau einen Wert.</p>
<p>Es gibt folgende Elemente</p>
<ul>
<li><code>imagename</code></li>
<li><code>tag</code></li>
<li><code>info</code></li>
<li><code>date</code></li>
</ul>
<p>Diese werden im Folgenden erläutert.</p>

<h3 id="imagename" data-numberify>imagename<a class="anchor ms-1" href="#imagename"></a></h3>
<p>Zum Herunterladen sollen zwei Docker-Images als Beispiel dienen</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker pull jellyfin/jellyfin:latest
</span></span><span class="line"><span class="ln">2</span><span class="cl">docker pull postgres:13
</span></span></code></pre></div><p>Der einfache Fall ist die Angabe des Names des Docker-Images, also:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="nt">&#34;imagename&#34;: </span><span class="s2">&#34;jellyfin/jellyfin&#34;</span><span class="w">
</span></span></span></code></pre></div><p>Alle Docker-Images, die das Badge <em>Docker Official Image</em> haben, muss noch ein <code>library</code> davor gestellt bekommen. Das ist später für das Script wichtig.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="nt">&#34;imagename&#34;: </span><span class="s2">&#34;library/postgres&#34;</span><span class="w">
</span></span></span></code></pre></div>
<h3 id="tag" data-numberify>tag<a class="anchor ms-1" href="#tag"></a></h3>
<p>Aus dem obigen <code>docker pull</code> Befehl kann jetzt hier der Tag angeben werden. Durch die Trennung vom Image-Namen und Tag, lassen sich auch unterschiedliche Versionen beobachten.</p>

<h3 id="info" data-numberify>info<a class="anchor ms-1" href="#info"></a></h3>
<p>Dies ist reines Prosa-Feld und dient zur eigenen Information bzw. Dokumentation. Ich schreibe hier z.B. die URL zum Changelog auf.</p>
<p>Ein anderer Einsatzzweck ist die Dokumentation, in welchem <code>docker-compose</code>-File ich das Image verwendet. In unten genannten Fall, z.B. im Dunstkreis von <em>paperless-ngx</em> .</p>

<h3 id="date" data-numberify>date<a class="anchor ms-1" href="#date"></a></h3>
<p>Hier steht der Zeitstempel drin, wann das jeweilige Image zuletzt auf docker-Hub hochgeladen wurde. Die Information stammt aus der <code>json</code>-Antwort vom Docker-Hub; dort steht es im Element <code>last_updated</code> und genau dieser Wert wird mit dem Wert der Konfigurations-Datei verglichen.</p>

<h3 id="komplette-beispieldatei" data-numberify>Komplette Beispieldatei<a class="anchor ms-1" href="#komplette-beispieldatei"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">[</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="nt">&#34;imagename&#34;</span><span class="p">:</span> <span class="s2">&#34;library/postgres&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="nt">&#34;tag&#34;</span><span class="p">:</span> <span class="s2">&#34;13&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="nt">&#34;info&#34;</span><span class="p">:</span> <span class="s2">&#34;paperless-ngx&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="nt">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;2023-11-03T05:09:17.243391Z&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="nt">&#34;imagename&#34;</span><span class="p">:</span> <span class="s2">&#34;library/redis&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="nt">&#34;tag&#34;</span><span class="p">:</span> <span class="s2">&#34;7.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="nt">&#34;info&#34;</span><span class="p">:</span> <span class="s2">&#34;paperless-ngx&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="nt">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;2023-11-04T04:12:52.019118Z&#34;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">  
</span></span><span class="line"><span class="ln">15</span><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="nt">&#34;imagename&#34;</span><span class="p">:</span> <span class="s2">&#34;jellyfin/jellyfin&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="nt">&#34;tag&#34;</span><span class="p">:</span> <span class="s2">&#34;latest&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="nt">&#34;info&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="nt">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;2023-11-05T18:28:02.143505Z&#34;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="p">]</span>
</span></span></code></pre></div>
<h2 id="das-script" data-numberify>Das Script<a class="anchor ms-1" href="#das-script"></a></h2>

<h2 id="voraussetzungen" data-numberify>Voraussetzungen<a class="anchor ms-1" href="#voraussetzungen"></a></h2>
<p>Das Script benötigte folgende installierte Tools</p>
<ul>
<li><code>jq</code></li>
<li><code>curl</code></li>
<li><code>bash</code></li>
</ul>
<p>Die Konfigurationsdatei muss im selben Verzeichnis sein, wie das Script.</p>

<h2 id="script-aufruf" data-numberify>Script-Aufruf<a class="anchor ms-1" href="#script-aufruf"></a></h2>
<p>Das Script kann ohne Parameter aufgerufen werden. Es arbeitet die Konfigurationsdatei ab und sucht sich alle Elemente des Typs <code>imagename</code> heraus.</p>
<p>In einer <code>while</code>-Schleife pickt es sich dann das zugehörige <em>Tag</em> und den letzten Zeitstempel heraus.</p>
<p>Diese Angaben werden zu einer URL zusammengesetzt und das Ergebnis ausgewertet.
Der Datenstrom besteht aus einer <em>json</em>-Antwort, wo wiederum ein Zeitstempel <code>last_updated</code> aufgeführt ist. Dieser Zeitstempel wird auf Docker-Hub aktualisiert, wenn von der Image-Maintainer*in ein neues Image hochgeladen (gepushed) wurde. Der Zeitstempel wird mit einem simplen String-Vergleich mit der Datumsangabe aus der Konfigurationsdatei verglichen.
Sind beide gleich, wird eine &ldquo;OK&rdquo;-Meldung herausgegeben und das nächste Image wird abgearbeitet.
Unterscheiden sich die Zeitstempel, wird eine Warnmeldung herausgegeben. Zusätzlich wird der Return-Codes des Scriptes auf <code>1</code> gesetzt, um diesen potentiell später auswerten zu können.</p>
<p>In beiden Fällen, wird der Inhalt der Elements <code>info</code> ausgeben. Dies ist z.B. im Rahmen eines Cronjobs hilfreich. Hier trage ich z.B. eine URL zu den Release-Infos ein, um mich über Änderungen vor einem Update zu informieren oder bekomme einen Hinweis, in welchen <code>docker-compose</code>-Dateien das Image verwendet wird.</p>

<h3 id="parameter--q" data-numberify>Parameter “-q”<a class="anchor ms-1" href="#parameter--q"></a></h3>
<p>Der Parameter <code>-q</code> reduziert die Ausgabe des Scriptes. Images, die aktuell sind und wo es kein neues auf Docker-Hub gibt, werden nicht mehr ausgegeben. Das ist für cronjobs praktisch, weil ich da nur eine E-Mail bekommen möchte, wenn es neue Images gibt. Das reduziert das Mail-Aufkommen.</p>

<h3 id="parameter--u" data-numberify>Parameter “-u”<a class="anchor ms-1" href="#parameter--u"></a></h3>
<p>Der Parameter <code>-u</code> erzeugt noch eine weitere Ausgabe am Ende des Scriptes.</p>
<pre><code>WARNING: Neues Docker-Image verfuegbar library/postgres:13 seit 2023-11-23 13:08 (&quot;2023-11-23T12:08:41.624052Z&quot;) Info: paperless-ngx
./update_rc.sh library/postgres:13 2023-11-23T12:08:41.624052Z # paperless-ngx
</code></pre>
<p>Um sich das händische Aktualisieren des neuen Zeitstempels zu erleichtern, gibt es das Script <code>update_rc.sh</code>.
Die benötigten Parameter mit dem jeweiligen Zeitstempel werden benutzungsfertig für Copy und Paste auf STDOUT mit ausgeben.</p>

<h3 id="beispiel-ausgabe" data-numberify>Beispiel-Ausgabe<a class="anchor ms-1" href="#beispiel-ausgabe"></a></h3>
<pre><code>$ ./check_last_docker_pull.sh -u
WARNING: Neues Docker-Image verfuegbar jellyfin/jellyfin:latest seit 2023-11-29 22:57 (&quot;2023-11-29T21:57:57.203009Z&quot;) Info: 
WARNING: Neues Docker-Image verfuegbar library/postgres:13 seit 2023-12-16 04:10 (&quot;2023-12-16T03:10:26.057478Z&quot;) Info: paperless-ngx
WARNING: Neues Docker-Image verfuegbar library/redis:7.0 seit 2023-12-16 03:08 (&quot;2023-12-16T02:08:55.087065Z&quot;) Info: paperless-ngx
./update_rc.sh jellyfin/jellyfin:latest 2023-11-29T21:57:57.203009Z # Info:  
./update_rc.sh library/postgres:13 2023-12-16T03:10:26.057478Z # Info: paperless-ngx 
./update_rc.sh library/redis:7.0 2023-12-16T02:08:55.087065Z # Info: paperless-ngx
</code></pre>
<p>Sofern das Image dann auf dem entsprechenden Computer oder Server heruntergeladen wurde, kann die Konfigurationsdatei mit dem oben ausgegeben Kommando aktualisiert werden; also z.B.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">./update_rc.sh library/redis:7.0 2023-12-16T02:08:55.087065Z
</span></span></code></pre></div><p>Der <code>#</code> ist gleichzeitig Kommentar in der Shell, so dass es nicht stört, wenn aus Versehen zu viel markiert wird.</p>

<h2 id="check_last_github_releasesh" data-numberify>check_last_github_release.sh<a class="anchor ms-1" href="#check_last_github_releasesh"></a></h2>
<p>Allerdings gibt es inzwischen einige Images oder Tools, die auf <em>github</em> liegen bzw. in deren Docker-Registry.
Da <em>github</em> ebenfalls eine API anbietet, dessen Ausgabe in einem ähnlichen JSON-Format anbietet, habe ich das obige Script etwas umgeschrieben.</p>
<p>Hier wird eine weitere Konfigurationsdatei benötigt mit dem Namen <code>check_last_github_release.rc.json</code>.</p>
<p>Folgende Elemente werden verwendet</p>
<ul>
<li><code>repro</code></li>
<li><code>release</code></li>
<li><code>info</code></li>
</ul>

<h3 id="repro" data-numberify>repro<a class="anchor ms-1" href="#repro"></a></h3>
<p>Hier wird nach der selben Mimik wie weiter oben der Image-Name eingetragen.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln">1</span><span class="cl">    <span class="s2">&#34;repro&#34;</span><span class="err">:</span> <span class="s2">&#34;paperless-ngx/paperless-ngx&#34;</span><span class="err">,</span>
</span></span></code></pre></div>
<h3 id="release" data-numberify>release<a class="anchor ms-1" href="#release"></a></h3>
<p>Im Gegensatz zu oben verwende ich feste Versionsnummern:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln">1</span><span class="cl">    <span class="s2">&#34;release&#34;</span><span class="err">:</span> <span class="s2">&#34;1.17.4&#34;</span><span class="err">,</span>
</span></span></code></pre></div>
<h3 id="info-1" data-numberify>info<a class="anchor ms-1" href="#info-1"></a></h3>
<p>Hier gilt selbiges wie oben; eine kleine Stelle zur Dokumentation oder Verweis auf eine URL.</p>

<h3 id="check_last_github_releasercjson" data-numberify>check_last_github_release.rc.json<a class="anchor ms-1" href="#check_last_github_releasercjson"></a></h3>
<p>Hier jetzt ein vollständiges Beispiel einer Konfigurationsdatei.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">[</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="nt">&#34;repro&#34;</span><span class="p">:</span> <span class="s2">&#34;paperless-ngx/paperless-ngx&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="nt">&#34;release&#34;</span><span class="p">:</span> <span class="s2">&#34;1.17.4&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="nt">&#34;info&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="nt">&#34;repro&#34;</span><span class="p">:</span> <span class="s2">&#34;mar10/wsgidav&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="nt">&#34;release&#34;</span><span class="p">:</span> <span class="s2">&#34;4.3.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="nt">&#34;info&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="nt">&#34;repro&#34;</span><span class="p">:</span> <span class="s2">&#34;restic/restic&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="nt">&#34;release&#34;</span><span class="p">:</span> <span class="s2">&#34;0.16.2&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="nt">&#34;info&#34;</span><span class="p">:</span> <span class="s2">&#34;https://restic.net/blog/&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="nt">&#34;repro&#34;</span><span class="p">:</span> <span class="s2">&#34;go-gitea/gitea&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="nt">&#34;release&#34;</span><span class="p">:</span> <span class="s2">&#34;1.20.5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="nt">&#34;info&#34;</span><span class="p">:</span> <span class="s2">&#34;https://blog.gitea.com/&#34;</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="p">]</span>
</span></span></code></pre></div>
<h2 id="das-script-1" data-numberify>Das Script<a class="anchor ms-1" href="#das-script-1"></a></h2>

<h3 id="voraussetzungen-1" data-numberify>Voraussetzungen<a class="anchor ms-1" href="#voraussetzungen-1"></a></h3>
<p>Ähnlich wie oben das Script <code>check_last_docker_pull.sh</code> benötigt es dieselben Software-Tools:</p>
<ul>
<li><code>jq</code></li>
<li><code>curl</code></li>
<li><code>bash</code></li>
</ul>
<p>Derzeit wird zum Auswerten <strong>zusätzlich</strong> noch</p>
<ul>
<li><code>perl</code></li>
</ul>
<p>benötigt. Dies soll zukünftig durch <code>sed</code> ersetzt werden, was IMHO verbreiteter installiert ist.</p>

<h3 id="script-aufruf-1" data-numberify>Script-Aufruf<a class="anchor ms-1" href="#script-aufruf-1"></a></h3>
<p>Das Script selbst kann ohne Parameter aufgerufen werden. Ähnlich wie <code>check_last_docker_pull.sh</code> hangelt es sich durch die Konfigurationsdatei und prüft alle Repositorys auf neuere Versionen.
Da in der URL mit dem Keyword <code>latest</code> gearbeitet werden kann, muss nur ein String-Vergleich mit der Versionsnummer aus der Konfigurationsdatei stattfinden. Bei Differenzen gibt es eine entsprechende Warnung. Die neue Version steckt schon in der <em>json</em>-Antwort und wird ebenfalls mit ausgegeben. Der Exit-Code ist auch hier wiederum <code>1</code>.</p>
<p>Aktuell muss die neue Version nach einem erfolgten Update noch per Hand neu gesetzt werden. Perspektivisch soll es hier auch ein Update-Script geben, da ja alle Informationen vorliegen.</p>

<h3 id="parameter--q-1" data-numberify>Parameter “-q”<a class="anchor ms-1" href="#parameter--q-1"></a></h3>
<p>Auch hier kann das Script mit dem Parameter <code>-q</code> aufgerufen werden, um den Output des Scriptes zu reduzieren.</p>

<h3 id="beispiel-ausgabe-1" data-numberify>Beispiel-Ausgabe<a class="anchor ms-1" href="#beispiel-ausgabe-1"></a></h3>
<pre><code>$ ./check_last_github_release.sh 
WARNING: Neues Release verfuegbar go-gitea/gitea alt: 1.20.5 neue Version 1.21.2 Info: https://blog.gitea.com/
OK: Release mar10/wsgidav Info: 
WARNING: Neues Release verfuegbar paperless-ngx/paperless-ngx alt: 1.17.4 neue Version 2.1.3 Info: 
OK: Release restic/restic Info: https://restic.net/blog/
</code></pre>

<h2 id="baustellen" data-numberify>Baustellen<a class="anchor ms-1" href="#baustellen"></a></h2>
<p>Die oben erwähnten Baustellen sollen demnächst<sup>(tm)</sup> mal behoben werden. Wenn dem so ist, werde ich den Blog-Artikel aktualisieren und entsprechend kennzeichnen.</p>

<h2 id="die-scripte---der-code" data-numberify>Die Scripte - der Code<a class="anchor ms-1" href="#die-scripte---der-code"></a></h2>
<p>Alle Scripte liegen auf <em>GitLab</em> innerhalb des Projektes <a href="https://tools.rainerrose.de/redirect.php?id=35" target="_blank" rel="noopener noreferrer">cli-tools<i class="fas fa-external-link-square-alt ms-1"></i></a> unterhalb des Verzeichnisses <a href="https://tools.rainerrose.de/redirect.php?id=36" target="_blank" rel="noopener noreferrer">watch_docker_images<i class="fas fa-external-link-square-alt ms-1"></i></a> , wo ich mehrere solcher Tools sammle</p>]]></content:encoded>
    <enclosure url="https://www.rainerrose.de/wallpaper/posts/check_last_docker_pull.png" length="61070" type="image/.png" />
    </item>
    
    <item>
      <title>update_docker_images.sh</title>
      <link>https://www.rainerrose.de/posts/update_docker_images/</link>
      <pubDate>Thu, 30 Nov 2023 22:54:19 +0200</pubDate>
      <guid>https://www.rainerrose.de/posts/update_docker_images/</guid>
      <description><![CDATA[<!-- Anreißer -->
<p>Beim Arbeiten mit vielen <code>docker-compose.yml</code> Dateien habe ich öfter die Anforderung gehabt, <strong>einzelne</strong> Images neu zu pullen. In der Regel reicht ein <code>docker compose pull</code>, was aber heißt, dass er <strong>alle</strong> images zieht.</p>
<p>Es gibt jedoch bei mir durchaus öfters den Fall, dass ich dies nicht möchte. Zudem hatte ich einige Container, wo nur auf ein bestimmtes Versions-Tag (z.B. <code>mysql:8</code>) gepulled wird oder ich sogar mit <code>latest</code> arbeite. Dies bedeutete, dass ich mir jedes Image einzeln aus der docker-compose-datei rauspfriemeln musste.
Damit ich im Wiederherstellungsfall das alte Image schneller wiederfinde, wollte ich das speziell taggen.
In der Regel habe ich an den Namen des Tags ein <code>_backup</code> dran gehängt. Vorher musste das vorherige Image mit diesem Tag gelöscht werden. Diese manuelle Arbeit habe ich nun in ein Script gegossen.</p>
<p><strong>Update 30.11.2023:</strong> siehe unten Changelog</p>]]></description>
      <content:encoded><![CDATA[<!-- Anreißer -->
<p>Beim Arbeiten mit vielen <code>docker-compose.yml</code> Dateien habe ich öfter die Anforderung gehabt, <strong>einzelne</strong> Images neu zu pullen. In der Regel reicht ein <code>docker compose pull</code>, was aber heißt, dass er <strong>alle</strong> images zieht.</p>
<p>Es gibt jedoch bei mir durchaus öfters den Fall, dass ich dies nicht möchte. Zudem hatte ich einige Container, wo nur auf ein bestimmtes Versions-Tag (z.B. <code>mysql:8</code>) gepulled wird oder ich sogar mit <code>latest</code> arbeite. Dies bedeutete, dass ich mir jedes Image einzeln aus der docker-compose-datei rauspfriemeln musste.
Damit ich im Wiederherstellungsfall das alte Image schneller wiederfinde, wollte ich das speziell taggen.
In der Regel habe ich an den Namen des Tags ein <code>_backup</code> dran gehängt. Vorher musste das vorherige Image mit diesem Tag gelöscht werden. Diese manuelle Arbeit habe ich nun in ein Script gegossen.</p>
<p><strong>Update 30.11.2023:</strong> siehe unten Changelog</p>
<p>Das Script was auf <a href="https://gitlab.com/rainerrose/cli-tools/-/blob/main/docker/update_docker_images.sh" target="_blank" rel="noopener noreferrer">GitLab<i class="fas fa-external-link-square-alt ms-1"></i></a> liegt, durchpflügt die <code>docker-compose.yml</code>-Datei (parameterisierbar in der Datei) und fragt interaktiv nach, ob ein neues Image gepulled werden soll.</p>
<p>Wenn ja (default), dann legt das Script vorher ein <em>&ldquo;Backup&rdquo;</em> des Containers an, indem es an den Tag-Namen des aktuellen Containers ein <code>_backup</code> dran hängt.
Vorher wird das evtl. vorhandene und so benannte Image noch gelöscht, damit die Festplatte nicht platzt.
Das Suffix des Tags ist anpassbar im Script.</p>
<p>Bei jedem Durchlauf werden nochmal alle passenden Images angezeigt, damit alte Images nochmal aufgelistet werden. So fallen ungetaggte Images mit z.B. <code>&lt;none&gt;</code> leichter auf.</p>
<p>Die Ausgabe sieht dann z.B. so aus:</p>
<pre><code>Update docker image: mysql:8 [j]|n: 
Lösche evtl. Backups
docker images mysql:8_backup
LINES_MIT_HEADER=2
lösche altes Image
docker image rm mysql:8_backup
Untagged: mysql:8_backup
Untagged: mysql@sha256:566007208a3f1cc8f9df6b767665b5c9b800fc4fb5f863d17aa1df362880ed04
Deleted: sha256:b2013ac9910129ded1da4c96495142b2ed0638ddf7e86e65156400d9a8503777
Deleted: sha256:d24171674816d2cdb9a7cfaf9980f3ba574930efe226ca7fa840084072974e08
Deleted: sha256:046ec448aa8eaaa27e4118211c9f77da24d35b8a84b25f997334c3473d14a870
Deleted: sha256:ab05f09658d83ed8ff487d346fcc9fa4cecf5a23906a7e7feffaea83a1332a14
Deleted: sha256:96db44e22a968a3a16890685d95bd96d420d99a8880966056721c36842fa38af
Deleted: sha256:402981938079002ce0b77d9fe7a892608155b3866ad1967313b4934d0d8a6d3c
Deleted: sha256:e38cf6d3efcf0edd5d80758556fdafa43e9e3136edbc05928febf8771b1cba31
Deleted: sha256:0d197db846f4e62ab3d29cef5d359f5896ddd6869ba49608f276741da328ef29
Deleted: sha256:121010cc4276929c2ba287fe57dfd0c61483862809dfc884c2aa3d998d6cc292
Deleted: sha256:b72678d2fc4485cc1febd27ab3cc6fe2ddc9ef62b2f016aaa8620040a339677f
Deleted: sha256:b42107e741524c1f305a1a4649a4d96a5921c48c5b8c438ad871ab7cc5815231
Lege Backup an 
docker tag mysql:8 mysql:8_backup
8: Pulling from library/mysql
210eb976c4c7: Pull complete 
ebb4c64fd647: Pull complete 
cb8397d67a0f: Pull complete 
ff0e9bc8aa4e: Pull complete 
e6f52b272e7f: Pull complete 
e2d9e8e437ee: Pull complete 
e61517738248: Pull complete 
cfb2700e7252: Pull complete 
4044404847dd: Pull complete 
c142db3aeff8: Pull complete 
Digest: sha256:1ee299bf9eb8d2218fcb4fad666a090c92caef48ce524e6edce35f2e2d55170d
Status: Downloaded newer image for mysql:8
docker.io/library/mysql:8
REPOSITORY   TAG        IMAGE ID       CREATED        SIZE
mysql        8_backup   8da80fe49fcf   4 weeks ago    577MB
mysql        8          2d9aad1b5856   2 months ago   574MB
</code></pre>

<h2 id="besonderheit" data-numberify>Besonderheit<a class="anchor ms-1" href="#besonderheit"></a></h2>
<p>Bei einigen Containern arbeite ich mit konkreten Versionsnummern in den Tags.</p>
<p>Beispiel-Ausschnitt aus einer <code>docker-compose.yml</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln">1</span><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">onlyoffice/documentserver:7.5.1.1</span><span class="w">
</span></span></span></code></pre></div><p>In diesem Fall muss die obige Abfrage</p>
<pre><code>Update docker image: onlyoffice/documentserver:7.5.1.1 [j]|n: 
</code></pre>
<p>mit <code>n</code> für <em>nein</em> beantwortet werden. Hier findet ja gerade eine Versionierung bzw. Backup über den Namen des Tags statt. Zudem kann ich hier schlecht die nächste Versionsnummer erraten.
Weiterhin kann ja auch ein Überspringen einer Subversion gewünscht sein.
Da die Images sowieso anhand Ihres Tags schon als Image-Version vorliegen, muss die Version somit im  <code>docker-compose.yml</code> -File angepasst werden.</p>
<p>Dieses Script ist somit nur für die fixen Version-Strings wie oben bei <em>mysql</em> oder dem oben erwähnten <em>lastest</em> geeignet, erleichert aber meinen Alltag ungemein.</p>

<h2 id="changelog" data-numberify>Changelog<a class="anchor ms-1" href="#changelog"></a></h2>
<table>
  <thead>
      <tr>
          <th>Datum</th>
          <th>Änderung</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>30.11.2023</td>
          <td>Teaser erweitert, einige Sätze ausgebessert. Letzten Absatz &ldquo;Besonderheit&rdquo; hinzugefügt.</td>
      </tr>
  </tbody>
</table>]]></content:encoded>
    <enclosure url="https://www.rainerrose.de/wallpaper/posts/update_docker_images.png" length="33926" type="image/.png" />
    </item>
    
    <item>
      <title>Docker Registry</title>
      <link>https://www.rainerrose.de/docs/linux/docker-registry/</link>
      <pubDate>Sun, 05 Feb 2023 23:13:34 +0100</pubDate>
      <guid>https://www.rainerrose.de/docs/linux/docker-registry/</guid>
      <description><![CDATA[<!-- Anreißer -->
<p>Docker-Images lassen sich in verschiedene Registrys legen.</p>

<h2 id="beispiel-gitlab" data-numberify>Beispiel: GitLab<a class="anchor ms-1" href="#beispiel-gitlab"></a></h2>]]></description>
      <content:encoded><![CDATA[<!-- Anreißer -->
<p>Docker-Images lassen sich in verschiedene Registrys legen.</p>

<h2 id="beispiel-gitlab" data-numberify>Beispiel: GitLab<a class="anchor ms-1" href="#beispiel-gitlab"></a></h2>
<ol>
<li>Zuerst <a href="https://tools.rainerrose.de/redirect.php?id=16" target="_blank" rel="noopener noreferrer">Token erstellen<i class="fas fa-external-link-square-alt ms-1"></i></a> im Gitlab</li>
<li>Sinnvollen <em>token name</em> vergeben</li>
<li>Scopes ankreuzen
<ul>
<li><input checked="" disabled="" type="checkbox"> read_registry</li>
<li><input checked="" disabled="" type="checkbox"> write_registry</li>
</ul>
</li>
<li>Ablaufdatum wählen</li>
<li>Tocken erstellen</li>
<li>Eingabe-Box unterhalb <code>Your new personal access token</code> unbedingt kopieren und in einen Passwort-Manager ablegen</li>
</ol>

<h3 id="registry-login" data-numberify>Registry Login<a class="anchor ms-1" href="#registry-login"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker login registry.gitlab.com -u rainerrose
</span></span></code></pre></div><p>Das dann abgefrage Passwor entspricht dem generierte Tocken.</p>

<h2 id="image-bauen" data-numberify>Image bauen<a class="anchor ms-1" href="#image-bauen"></a></h2>

<h3 id="ohne-tag" data-numberify>Ohne Tag<a class="anchor ms-1" href="#ohne-tag"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker build -t registry.gitlab.com/rainerrose/&lt;projekt-name&gt; .
</span></span></code></pre></div>
<h3 id="mit-tag" data-numberify>Mit Tag<a class="anchor ms-1" href="#mit-tag"></a></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker build -t registry.gitlab.com/rainerrose/&lt;projekt-name&gt;:1.1 .
</span></span></code></pre></div>
<h2 id="hochladen" data-numberify>Hochladen<a class="anchor ms-1" href="#hochladen"></a></h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker push <span class="o">[</span>OPTIONS<span class="o">]</span> NAME<span class="o">[</span>:TAG<span class="o">]</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">docker push registry.gitlab.com/rainerrose/&lt;projekt-name&gt; --all-tags
</span></span></code></pre></div>]]></content:encoded>
    </item>
    
  </channel>
</rss>

