<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Saurav</title>
    <description>The latest articles on DEV Community by Saurav (@saurav_saini).</description>
    <link>https://dev.to/saurav_saini</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3980759%2F73283dad-9822-4c1b-8ad4-9d30ae0861fe.webp</url>
      <title>DEV Community: Saurav</title>
      <link>https://dev.to/saurav_saini</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/saurav_saini"/>
    <language>en</language>
    <item>
      <title>I got tired of SSH and Loki for four containers, so I built DockLog</title>
      <dc:creator>Saurav</dc:creator>
      <pubDate>Fri, 12 Jun 2026 07:39:44 +0000</pubDate>
      <link>https://dev.to/saurav_saini/i-got-tired-of-ssh-and-loki-for-four-containers-so-i-built-docklog-1e94</link>
      <guid>https://dev.to/saurav_saini/i-got-tired-of-ssh-and-loki-for-four-containers-so-i-built-docklog-1e94</guid>
      <description>&lt;p&gt;If you run a few containers on one VPS or homelab box, you've probably lived this loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SSH in&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker logs -f something&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Realize someone else on your team needs the same thing&lt;/li&gt;
&lt;li&gt;Either hand out SSH keys or start designing an observability stack you don't actually need yet&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hit that wall with staging and random homelab services on the same machine. I didn't want Elasticsearch or Loki for four containers. I also didn't want everyone having shell access just to read stdout.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;DockLog&lt;/strong&gt; — a self-hosted Docker log viewer and light admin UI. One container on the socket. No agents. No external telemetry.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live logs&lt;/strong&gt; over WebSockets (stdout/stderr, not polling)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Host + container CPU/memory&lt;/strong&gt;, with about 30 days of samples in SQLite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-user auth&lt;/strong&gt; with per-user container patterns (wildcards and regex)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional actions&lt;/strong&gt; — start, stop, restart, delete, shell — gated by server env flags &lt;em&gt;and&lt;/em&gt; per-user permissions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit log&lt;/strong&gt; when auth mode uses a persistent database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native apps&lt;/strong&gt; (Android, Windows, Linux) that connect to DockLog servers &lt;em&gt;you&lt;/em&gt; host — save multiple servers and switch between them in the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typical RAM use for me is around 30–40 MB. Image is &lt;code&gt;aimldev/docklog:latest&lt;/code&gt; on Docker Hub (amd64 and arm64). MIT licensed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it doesn't try to be
&lt;/h2&gt;

&lt;p&gt;Being upfront about scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One Docker engine per DockLog instance&lt;/strong&gt; — not fleet-wide aggregation in a single dashboard (that's on the roadmap)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a replacement for Loki/ELK/Grafana&lt;/strong&gt; at cluster scale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a hosted SaaS&lt;/strong&gt; — you run it, you own the data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;docker.sock is still privileged&lt;/strong&gt; — treat it like any admin tool&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;docklog&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aimldev/docklog:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docklog&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8888:8000"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./data:/app/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SECRET_KEY=change-me-use-openssl-rand-base64-32&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_PATH=/app/data/docklog.db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CLIENT_ACCESS=strict&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ENV=production&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:8888&lt;/code&gt;. A fresh install seeds &lt;code&gt;admin&lt;/code&gt; / &lt;code&gt;admin123&lt;/code&gt; and prompts you to change the password on first login.&lt;/p&gt;

&lt;p&gt;Or with &lt;code&gt;docker run&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull aimldev/docklog:latest

docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; docklog &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:8000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /var/run/docker.sock:/var/run/docker.sock &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/data:/app/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-secure-key-here &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;DB_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app/data/docklog.db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;CLIENT_ACCESS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;strict &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--restart&lt;/span&gt; unless-stopped &lt;span class="se"&gt;\&lt;/span&gt;
  aimldev/docklog:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  RBAC that isn't just UI theater
&lt;/h2&gt;

&lt;p&gt;A question I got early on (fair one): if you restrict containers per user, is that only hidden in the UI?&lt;/p&gt;

&lt;p&gt;No. &lt;code&gt;allowed_containers&lt;/code&gt; patterns are checked &lt;strong&gt;server-side&lt;/strong&gt; before container lists, log WebSocket streams, stats, and actions. Action rights use two layers: server &lt;code&gt;ALLOW_*&lt;/code&gt; flags and per-user &lt;code&gt;can_*&lt;/code&gt; flags in the database — both have to pass, including for admin accounts.&lt;/p&gt;

&lt;p&gt;In no-auth mode (fine for a local laptop, not for the public internet), the &lt;code&gt;ALLOW_*&lt;/code&gt; env vars are the only gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Go&lt;/strong&gt; backend talking to the Docker API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vue 3&lt;/strong&gt; UI embedded in the same image&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; for users, RBAC, audits, and short metric history&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebSockets&lt;/strong&gt; for logs, events, and optional shell sessions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flutter&lt;/strong&gt; for the mobile/desktop companion apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The image also ships a &lt;code&gt;docklog&lt;/code&gt; CLI on PATH (&lt;code&gt;reset-password&lt;/code&gt;, &lt;code&gt;config&lt;/code&gt;, &lt;code&gt;version&lt;/code&gt;, and agent subcommands for future fleet work).&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it without installing
&lt;/h2&gt;

&lt;p&gt;There's a public demo if you want to click around first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://demo.docklog.dev" rel="noopener noreferrer"&gt;https://demo.docklog.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;login: &lt;code&gt;demo&lt;/code&gt; / &lt;code&gt;Demo@1106&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shared sandbox don't put real secrets there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mobile / desktop clients
&lt;/h2&gt;

&lt;p&gt;The apps are clients for servers you already run. Add your URL, sign in, tail logs without keeping a browser tab open. You can store prod, staging, and homelab instances in one app and flip between them.&lt;/p&gt;

&lt;p&gt;Each host still runs its own DockLog container. The app is multi-server management, not one merged view of every container across every machine yet.&lt;/p&gt;

&lt;p&gt;Downloads: &lt;a href="https://www.docklog.dev/app" rel="noopener noreferrer"&gt;https://www.docklog.dev/app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I reached for something heavier when multiple people needed access with different container visibility without giving everyone the Docker socket through SSH.&lt;/p&gt;

&lt;p&gt;DockLog is aimed at that middle ground: faster than standing up a full logging stack, more structured than shared SSH access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Site: &lt;a href="https://www.docklog.dev" rel="noopener noreferrer"&gt;https://www.docklog.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://www.docklog.dev/docs" rel="noopener noreferrer"&gt;https://www.docklog.dev/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/dockloghq/docklog" rel="noopener noreferrer"&gt;https://github.com/dockloghq/docklog&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docker Hub: &lt;a href="https://hub.docker.com/r/aimldev/docklog" rel="noopener noreferrer"&gt;https://hub.docker.com/r/aimldev/docklog&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you try it, I'd genuinely like to know what you use today for single-host Docker logs and what's still missing. Issues and feedback welcome on GitHub.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>opensource</category>
      <category>selfhosted</category>
    </item>
  </channel>
</rss>
