Real-time Docker log viewer. Streams container logs to a browser UI via the Docker socket — stateless, no log storage.
| Service | Port | Description |
|---|---|---|
| dozzle | 8087 | Web UI (proxied via Traefik) |
No persistent storage directory needed — Dozzle is stateless. The /data volume only stores user settings and alert configs. It is created automatically by Docker as a named volume bound to:
/mnt/SSD/Containers/dozzle
Create it before deploying:
mkdir -p /mnt/SSD/Containers/dozzlecp .env.example .env
# Edit .env — set DOZZLE_DOMAIN at minimum
docker compose up -ddocker compose ps
docker compose logs -fNavigate to https://<DOZZLE_DOMAIN> to access the web UI.
.env variables:
| Variable | Default | Description |
|---|---|---|
TZ |
America/New_York |
Timezone |
DOZZLE_HOSTNAME |
homelab |
Display name for this host in the UI |
DOZZLE_AUTH_PROVIDER |
none |
Auth mode: none, simple, forward-proxy |
DOZZLE_ENABLE_MCP |
true |
Enable the read-only MCP endpoint at /api/mcp |
DOZZLE_DOMAIN |
dozzle.localhost |
Hostname Traefik routes to Dozzle |
DOZZLE_PORT |
8087 |
Host port (direct access only — Traefik ignores this) |
Commented-out options in compose.yaml:
| Variable | Description |
|---|---|
DOZZLE_AUTH_TTL |
Persist auth sessions (e.g. 48h) — requires DOZZLE_AUTH_PROVIDER=simple |
DOZZLE_ENABLE_ACTIONS |
Allow start/stop/restart from UI — requires removing :ro from socket mount |
DOZZLE_ENABLE_SHELL |
Allow shell access to containers — requires removing :ro from socket mount |
DOZZLE_REMOTE_AGENT |
Connect to remote Dozzle agents (e.g. host1:7007,host2:7007) |
DOZZLE_FILTER |
Limit visible containers by name or label (e.g. name=myapp*) |
DOZZLE_LEVEL |
Log verbosity: debug, info, warn, error |
| Data | Path |
|---|---|
| User settings and alert configs | /mnt/SSD/Containers/dozzle |
Dozzle exposes a Streamable HTTP MCP endpoint from the same container when DOZZLE_ENABLE_MCP=true.
Use one of these URLs in MCP clients:
https://<DOZZLE_DOMAIN>/api/mcp
http://<DOCKER_HOST>:8087/api/mcp
For this Homelab's Codex config, use the direct LAN endpoint:
http://10.0.5.10:8087/api/mcp
The MCP tools are read-only and can list containers, list hosts, fetch container logs, and read container CPU/memory history.
Codex config.toml:
[mcp_servers.dozzle]
url = "http://10.0.5.10:8087/api/mcp"VS Code MCP settings:
{
"servers": {
"dozzle": {
"type": "http",
"url": "https://<DOZZLE_DOMAIN>/api/mcp"
}
}
}Claude Desktop:
{
"mcpServers": {
"dozzle": {
"type": "streamable-http",
"url": "https://<DOZZLE_DOMAIN>/api/mcp"
}
}
}- With
DOZZLE_AUTH_PROVIDER=none, clients do not need extra credentials. - With
DOZZLE_AUTH_PROVIDER=simple, get a JWT from/api/tokenand send it asAuthorization: Bearer <token>. - With
DOZZLE_AUTH_PROVIDER=forward-proxy, connect through the same proxy path so the proxy can inject the expected auth headers.
By default Dozzle only sees containers on the TrueNAS host it runs on (via the local Docker socket). To also monitor containers on remote hosts — such as Proxmox nodes — deploy a Dozzle agent on each remote host and point the central Dozzle instance at them.
Run this on each Proxmox node (or any remote Docker host):
docker run -d \
--name dozzle-agent \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-p 7007:7007 \
amir20/dozzle:latest agentOr as a compose service if you prefer:
services:
dozzle-agent:
image: amir20/dozzle:latest
container_name: dozzle-agent
command: agent
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- 7007:7007
healthcheck:
test: ["CMD", "/dozzle", "healthcheck"]
interval: 30s
timeout: 10s
retries: 3Uncomment and populate DOZZLE_REMOTE_AGENT in .env:
DOZZLE_REMOTE_AGENT=<PROXMOX_IP1>:7007,<PROXMOX_IP2>:7007,<PROXMOX_IP3>:7007Then restart Dozzle:
docker compose up -dAll three Proxmox nodes will appear as selectable hosts in the Dozzle UI alongside the TrueNAS host.
- Agent traffic on port
7007is TLS-encrypted — no additional setup required. - Restrict port
7007to your LAN (10.0.5.0/24) on each Proxmox node's firewall so agents aren't reachable externally. - Each agent only exposes its own host's containers — the central Dozzle instance aggregates the views.
- Set a
DOZZLE_HOSTNAMEon each remote agent by passing-e DOZZLE_HOSTNAME=node1to thedocker runcommand (or the equivalent env var in compose) so hosts are clearly labeled in the UI.
Alerts are configured in the Dozzle UI under Alerts and persist in the /data volume. Each alert has a Container Expression (which containers to watch) and a Trigger Expression (what to match). When no container expression is needed for all containers, use name != "".
Fire on Docker engine events — most reliable signal for container health, independent of log format.
| Name | Container Expression | Trigger Expression |
|---|---|---|
| Container OOM killed | name != "" |
name == "oom" |
| Container died | name != "" |
name == "die" |
| Container restarting | name != "" |
name == "restart" |
| Name | Container Expression | Trigger Expression |
|---|---|---|
| Traefik backend errors | name == "traefik" |
message contains "level=error" |
| Traefik DNS failure | name == "traefik" |
message contains "no such host" |
| Database errors | name contains "db" |
message contains "ERROR" && message contains "Table" |
| Semaphore task failed | name == "semaphore" |
message contains "Task failed" |
| Name | Container Expression | Trigger Expression | Notes |
|---|---|---|---|
| High CPU | name != "" |
cpu > 85 |
Set cooldown 10+ min |
| High memory | name != "" |
memory > 90 |
Set cooldown 10+ min |
- Set a 10+ minute cooldown on metric alerts to avoid Discord spam during backups or scans
- Alert configs are stored in
/mnt/SSD/Containers/dozzleand survive container restarts
Portainer and Dozzle complement each other naturally — Portainer handles container management (deploy, start/stop, inspect) while Dozzle handles real-time log streaming. Both mount the Docker socket read-only and coexist without conflict.
Portainer CE/BE supports an External Log Viewer setting that adds a link on each container's log page, opening that container directly in Dozzle.
- In Portainer, go to Settings → General.
- Scroll to Log Viewer and enable External Log Viewer.
- Set the URL to:
Replace
https://<DOZZLE_DOMAIN>/show?name={containerName}<DOZZLE_DOMAIN>with your actual Dozzle domain (e.g.dozzle.example.com). The{containerName}placeholder is filled in by Portainer at click time. - Save settings.
Once configured, container log pages in Portainer will show an Open in external log viewer link that jumps directly to that container's live log stream in Dozzle.
- The redirect happens in the browser — Portainer and Dozzle do not need to be on the same Docker network for this to work.
- If Dozzle has authentication enabled (
DOZZLE_AUTH_PROVIDER=simpleorforward-proxy), the browser will be prompted to log in before the log view loads. - Dozzle resolves container names to IDs at request time. If a container was recently recreated, the link still works as long as the name is unchanged.
docker compose pull
docker compose up -d- Generate a user entry:
docker run -it --rm amir20/dozzle generate admin --password yourpassword --email you@example.com
- Paste the output into
/mnt/SSD/Containers/dozzle/users.yml - Set
DOZZLE_AUTH_PROVIDER=simplein.envand restart:docker compose up -d