Skip to content

Docker Stacks

Every directory under docker-compose-apps/ is an independent Compose project. For the full machine-generated list of stacks, services, images and published ports, see the Stack catalog.

Small stacks are a single docker-compose.yml. Larger hosts assemble one project out of per-application files using compose’s include: directive:

include:
- host/arcane.yaml
- ../dozzle/dozzle-agent.yaml
- apps/gluetun/gluetun.yaml
- apps/qbittorrent/qbittorrent.yaml
# ...

That keeps one file per application while still giving compose a single project to manage. The UGREEN NAS stack is the fullest example, pulling in twelve applications.

Two agent sidecars ride along with nearly every stack and are filtered out of the catalog tables to keep them readable:

SidecarPurpose
arcane-agentContainer management via Arcane
dozzle-agentLog aggregation into the central Dozzle UI

Anything needing routing attaches to the external traefik-web Docker network. Traefik is the single entry point and holds both certificate resolvers:

  • Internal (*.toolsera.lan) — certificates from the Step CA at stepca.toolsera.lan
  • Public (*.toolsera.fr) — Let’s Encrypt via the Cloudflare DNS challenge, reached through a Cloudflare tunnel

Most routers are not defined by compose labels at all — they come from the Traefik Proxmox provider plugin, which derives routes from the Proxmox guest list. That is why the catalog deliberately does not print hostnames: scraping labels would produce a misleadingly partial list.

Traefik and Portainer do not mount the raw Docker socket. They go through docker-socket-proxy, which exposes a read-only slice of the API — CONTAINERS, SERVICES and TASKS enabled, POST disabled.

Always through bws run, so secrets are present:

Terminal window
bws run --access-token "$BWS_ACCESS_TOKEN" -- docker compose up -d <service>

Fleet-wide, use the Ansible playbook instead:

Terminal window
ansible-playbook -i inventory/proxmox.proxmox.yml playbooks/restart-docker-stacks.yml

A bare docker compose up -d leaves every BWS-only variable empty. See Architecture for why that matters, and Host access notes before running any of it on a live host.

Custom images are built and pushed to Harbor by tagging image/<name>-<version>. See Publishing images to Harbor.