A compose file you can leave running
DockLog on Docker Compose, smoke test, auth, proxy settings, backups. The file we actually deploy.
Most DockLog installs I've seen are a single compose file on a VPS or a NUC in a closet. The image is aimldev/docklog:latest (amd64 and arm64), API, Vue UI, SQLite for users, all in one container. No agent, no second service.
Need Docker and Compose first? See Install Docker Engine and Install Docker Compose (steps from official Docker documentation).
This post walks from "does it run?" to something you'd leave up for months.
Smoke test (private network only)
services:
docklog:
image: aimldev/docklog:latest
container_name: docklog
ports:
- "8888:8000"
environment:
- DISABLE_AUTH=true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: unless-stoppedhttp://your-host:8888, you should see containers within a few seconds.
Don't expose DISABLE_AUTH past a LAN you control. Anyone with the URL can touch the Docker socket through the UI.
Auth + persistence
mkdir -p ~/docklog/data
cd ~/docklogservices:
docklog:
image: aimldev/docklog:latest
container_name: docklog
ports:
- "8888:8000"
environment:
SECRET_KEY: ${SECRET_KEY}
DB_PATH: /app/data/docklog.db
CLIENT_ACCESS: strict
ENV: production
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
restart: unless-stopped.env:
SECRET_KEY=<output of openssl rand -hex 32>Generate the key:
openssl rand -hex 32Log in, change the default password immediately. Credentials are in the getting started guide.
DB_PATH is what makes users, RBAC, alert config, and audit survive restarts. Without it, you're back to defaults on every docker compose up.
Behind nginx or Caddy
Bind to loopback and tell DockLog about the proxy:
ports:
- "127.0.0.1:8888:8000"
environment:
TRUST_PROXY: "true"
ALLOWED_ORIGINS: https://docklog.example.comFull nginx block in the reverse proxy post.
Never skip ALLOWED_ORIGINS when using a public hostname. Login redirect loops are almost always origin mismatch plus missing TRUST_PROXY.
Restart buttons (optional)
Server gate first, user permission second:
ALLOW_RESTART: "true"Then tick can_restart per user in Admin. No ALLOW_RESTART on the server = no restart for anyone, admin or not.
Same pattern for stop, start, delete, shell. See RBAC post for the full two-layer model.
Docker and K8s on one host
Homelab classic: compose apps plus k3s:
environment:
RUNTIME_MODE: both
KUBECONFIG: /app/kube/config
K8S_NAMESPACES: default,staging,production
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
- ~/.kube/config:/app/kube/config:roRUNTIME_MODE=docker is default if you only have the socket.
UI gets a Docker/K8s toggle on the logs page. Permissions use the same allowed_containers field for both. More in K8s without Loki.
Production-shaped compose (copy-paste baseline)
Everything from above in one file:
services:
docklog:
image: aimldev/docklog:latest
container_name: docklog
ports:
- "127.0.0.1:8888:8000"
environment:
SECRET_KEY: ${SECRET_KEY}
DB_PATH: /app/data/docklog.db
CLIENT_ACCESS: strict
ENV: production
TRUST_PROXY: "true"
ALLOWED_ORIGINS: https://docklog.example.com
ALLOW_RESTART: "true"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
restart: unless-stopped
# Optional: cap memory on tiny VPS
mem_limit: 256mSwap ALLOWED_ORIGINS for your real URL. Add kubeconfig mount and RUNTIME_MODE if needed.
Environment reference (common vars)
| Variable | Purpose |
|---|---|
SECRET_KEY | Session signing; required with auth |
DB_PATH | SQLite path for users, RBAC, alerts |
CLIENT_ACCESS | strict for production browser clients |
ENV | production disables debug behaviors |
TRUST_PROXY | true behind nginx/Caddy |
ALLOWED_ORIGINS | Comma-separated browser origins |
ALLOW_RESTART etc. | Server-side action gates |
RUNTIME_MODE | docker, kubernetes, or both |
K8S_NAMESPACES | Namespace ceiling for K8s mode |
DISABLE_AUTH | Smoke test only; never on the internet |
Full list: getting started guide.
Files on disk
~/docklog/
├── docker-compose.yaml
├── .env
├── data/docklog.db
└── backups/ # optionalAdd .env to .gitignore. SECRET_KEY in git is a bad week.
Back up docklog.db: users, RBAC, alert config. Quick cold copy:
docker compose stop docklog
cp data/docklog.db backups/docklog-$(date +%F).db
docker compose start docklogFor zero-downtime-ish backup on a quiet host, SQLite copy while running usually works, but stop/start is safer before upgrades.
Upgrades
docker compose pull && docker compose up -dData survives in ./data. Glance at releases for anything breaking.
After upgrade: log in, spot-check container list, tail one log stream, hit Test on a notification channel if you use alerts.
Stuff that breaks
| Symptom | Likely cause |
|---|---|
| Empty container list | Socket not mounted; check ls -la /var/run/docker.sock |
| Login redirect loop | ALLOWED_ORIGINS doesn't match browser URL |
| Can't write database | Ownership on ./data vs container UID |
| K8s tab empty | Wrong KUBECONFIG path or namespace not in K8S_NAMESPACES |
| Logs freeze after 60s | Reverse proxy timeout; not compose |
| 403 on API | CLIENT_ACCESS=strict without proper client |
Logs freezing behind a proxy: see reverse proxy post for proxy_read_timeout.
What to do after compose works
- RBAC before adding users.
- Reverse proxy + TLS before sharing a URL.
- Alerts when you want Slack pings, not staging noise.
- Native app if you tail from a phone regularly.
Why bother with self-hosted at all: why self-hosted post.