docker-compose.yml runs HODA on the main host, published on one address (10.20.30.10:10040 in .env.example) for the Pangolin resource. The agent settings are optional, so a single host needs nothing else. docker-compose.agent.yml is for a second Docker host. Both follow FiMa's layout: required values fail with a clear message, pull_policy always, memory limits, capped logs, a read-only root filesystem. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
2.7 KiB
YAML
76 lines
2.7 KiB
YAML
# HODA — the main host: serves the dashboard of every labeled app on this host's Docker.
|
|
#
|
|
# Usage:
|
|
# cp .env.example .env # the defaults fit the main host
|
|
# docker compose pull # grab the latest image from the Gitea registry
|
|
# docker compose up -d
|
|
#
|
|
# Point the Pangolin resource for apps.mariosem.es at http://HODA_BIND_IP:HODA_PORT
|
|
# (http://10.20.30.10:10040 with .env.example) and turn SSO on: HODA has no login of its own.
|
|
#
|
|
# One host needs nothing else. A second Docker host runs docker-compose.agent.yml, and this
|
|
# host then gets HODA_AGENT_URL and HODA_PEER_TOKEN in .env to pull that host's apps.
|
|
#
|
|
# The image is built and published by .gitea/workflows/ci.yml.
|
|
|
|
name: hoda
|
|
|
|
x-logging: &logging
|
|
driver: json-file
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
services:
|
|
hoda:
|
|
image: git.mariosem.es/msemes/hoda:${HODA_TAG:-latest}
|
|
container_name: hoda
|
|
restart: unless-stopped
|
|
# `:latest` is mutable; `always` makes `docker compose up -d` check the registry for a newer
|
|
# image. If you pin HODA_TAG to a fixed tag, `missing` is enough.
|
|
pull_policy: always
|
|
depends_on:
|
|
- socket-proxy
|
|
environment:
|
|
MODE: primary
|
|
DOCKER_HOST: tcp://socket-proxy:2375
|
|
NODE_NAME: ${HODA_NODE_NAME:-host-1}
|
|
DASHBOARD_TITLE: ${HODA_TITLE:-apps.mariosem.es}
|
|
# Only with a second host: its agent's URL and the token both hosts share. HODA refuses to
|
|
# start with an agent URL but no token.
|
|
PEERS: ${HODA_AGENT_URL:-}
|
|
PEER_TOKEN: ${HODA_PEER_TOKEN:-}
|
|
LOG_LEVEL: ${HODA_LOG_LEVEL:-info}
|
|
ports:
|
|
# Published on one address only: loopback by default, or the LAN IP Pangolin reaches.
|
|
- "${HODA_BIND_IP:-127.0.0.1}:${HODA_PORT:-8090}:8080"
|
|
volumes:
|
|
# Icon cache. Set HODA_DATA_DIR to bind-mount a host directory instead of the named volume;
|
|
# it must be owned by the image's user first: sudo chown -R 65532:65532 /path/to/dir
|
|
- ${HODA_DATA_DIR:-hoda_data}:/data
|
|
# The binary only writes to /data, and needs no privileges.
|
|
read_only: true
|
|
cap_drop: [ALL]
|
|
security_opt: ["no-new-privileges:true"]
|
|
mem_limit: 128m
|
|
cpus: 0.5
|
|
logging: *logging
|
|
|
|
# Read-only Docker API for HODA: container lists and events, nothing else. No published port.
|
|
socket-proxy:
|
|
image: tecnativa/docker-socket-proxy:latest
|
|
container_name: hoda-socket-proxy
|
|
restart: unless-stopped
|
|
environment:
|
|
CONTAINERS: 1
|
|
EVENTS: 1
|
|
POST: 0
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
mem_limit: 64m
|
|
logging: *logging
|
|
|
|
volumes:
|
|
# Fallback when HODA_DATA_DIR is unset; a no-op if /data is bind-mounted to a host path.
|
|
hoda_data:
|