docker-compose.yml
Rama main · réplica de lectura del repositorio original.
# UnifiOptimizer daemon, one command: `docker compose up -d`.
#
# Builds Dockerfile.netadmin from this checkout and runs the single daemon
# process (collector, detectors, issue engine, SLE, FastAPI + WebSocket).
# Controller access is read-only. See docs/CONTAINER.md for the full walkthrough
# and for the bind-mount variant.
#
# THREE THINGS THIS FILE GETS RIGHT ON PURPOSE, do not "simplify" them away:
#
# 1. The published port is `127.0.0.1:8765:8765`, not `8765:8765`. GET reads on
# the API are open by design once configured (docs/ARCHITECTURE.md 18.1), so
# the bare form, which binds 0.0.0.0 on the host, would hand your whole
# network inventory to anyone on the LAN. State-changing routes already fail
# closed without `NETADMIN_API_TOKEN`, and `/mcp` (18.3) is separately gated
# by `NETADMIN_MCP_TOKEN` below — 404 when unset, 401 on a wrong or missing
# bearer — but neither of those makes a LAN publish free, since the read
# surface above is still exposed. Put a reverse proxy with auth in front, or
# widen the port deliberately, if you want LAN or remote access.
#
# 2. Storage is a named volume, not a `./data` bind mount. The image runs as a
# non-root user (uid 501 by default, see Dockerfile.netadmin) and Docker
# seeds a fresh named volume from the image with that ownership already
# correct, on any host, with no uid bookkeeping from you. A bind mount only
# works when the host directory happens to be writable by the container's
# uid; docs/CONTAINER.md shows how to do that deliberately if you want the
# files on the host.
#
# 3. NETADMIN_DATA_DIR is set explicitly even though /app/data is also where the
# default cwd-relative lookup lands. It pins secrets.env, config.yaml, the
# SQLite database, and the logs to the volume regardless of the working
# directory, so an upgrade cannot silently start writing somewhere else.
services:
netadmin:
build:
context: .
dockerfile: Dockerfile.netadmin
image: unifioptimizer:local
container_name: unifioptimizer
restart: unless-stopped
# Loopback only. See note 1 above.
ports:
- "127.0.0.1:8765:8765"
environment:
NETADMIN_DATA_DIR: /app/data
# Tells self-update (docs/ARCHITECTURE.md section 23) which host command
# to show: `git pull && docker compose up -d --build`. The image already
# sets NETADMIN_INSTALL_METHOD=container; this just picks the variant.
NETADMIN_UPDATE_VARIANT: compose
# Uncomment to gate fix apply/revert over HTTP. Reads stay open; without a
# token every mutating endpoint is refused, which is the safe default.
# NETADMIN_API_TOKEN: ${NETADMIN_API_TOKEN:-}
# Uncomment to enable the remote MCP mount at /mcp (docs/MCP_SERVER.md).
# A SEPARATE credential from NETADMIN_API_TOKEN, with no fallback either
# direction: the API token authorizes controller mutations, this one only
# gates read-only MCP tool calls. Unset (the default) means /mcp answers
# 404 -- the feature is simply absent, not merely unauthenticated.
# NETADMIN_MCP_TOKEN: ${NETADMIN_MCP_TOKEN:-}
volumes:
- netadmin-data:/app/data
# No curl in the python:3.12-slim base, so probe with the interpreter that
# is already there.
healthcheck:
test:
- CMD
- python
- -c
- |
import sys, urllib.request
with urllib.request.urlopen("http://127.0.0.1:8765/api/health", timeout=5) as r:
sys.exit(0 if r.status == 200 else 1)
interval: 30s
timeout: 10s
start_period: 30s
retries: 3
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
netadmin-data: