Skip to content

Images & networking

ServiceImageNotes
botghcr.io/batazor/autopilot/bot:latestHeadless worker + scheduler + local Tesseract OCR. Multi-arch (amd64+arm64).
apisame bot image, command: apiFastAPI for the Web UI (:8765).
webghcr.io/batazor/autopilot/web:latestNext.js operator dashboard (:3000). Multi-arch.
redisredis:alpineQueue + state.
inferenceroboflow/roboflow-inference-server-cpuOptional — only with the full profile. Fishing Tournament fish detector (Fish detection).

The source repo is mirrored to gitlab.com/batazor/autopilot, and its pipeline (.gitlab-ci.yml) publishes the same multi-arch (amd64+arm64) bot and web images to the GitLab Container Registry. If GHCR is slow or blocked for you, point the stack at the mirror with WOS_REGISTRY — nothing else changes:

Terminal window
WOS_REGISTRY=registry.gitlab.com/batazor/autopilot \
docker compose -f docker-compose.prod.yml up -d --pull always
ServiceGitHub Container Registry (default)GitLab Container Registry (mirror)
botghcr.io/batazor/autopilot/bot:latestregistry.gitlab.com/batazor/autopilot/bot:latest
webghcr.io/batazor/autopilot/web:latestregistry.gitlab.com/batazor/autopilot/web:latest

The inference image is not pulled by default — it sits behind a Compose profile, so a plain up runs only the core services:

Terminal window
docker compose -f docker-compose.prod.yml up -d --pull always # default: redis, bot, api, web
docker compose -f docker-compose.prod.yml --profile full up -d --pull always # + inference (needs ROBOFLOW_API_KEY)

Public images are published as latest only — keep your install on latest. Updating is more than --pull always (you also refresh the compose file, and a stuck container needs a down first) — see Updating.

bot, api, and web run in network_mode: host so the app shares the host’s loopback. On boot the bot starts its own adb server (bundled in the image) on 127.0.0.1:5037; because that port is the shared host loopback, the workers, the dashboard ADB scan, and any emulator on loopback all reach it. You don’t install adb on the host or run adb start-server yourself — the container does it (adb.ensure_adb_server, idempotent). The server stays bound to loopback only (safe, no LAN exposure).

No host adb, no adb -a, no socat sidecar, no host.docker.internal indirection.

Side effect: app containers do not use Compose-internal DNS for redis. Instead, bot and api connect to Redis over a shared Unix socket volume (redis_socket/var/run/redis/redis.sock), and web proxies /api to 127.0.0.1:8765.

The compose file also shares wos_temporal between bot and api; that is where the worker writes rolling screenshots used by the dashboard preview and Click approvals page.

  • Linux — fully supported out of the box.
  • Docker Desktop (macOS / Windows) — works only with the Host networking beta enabled (Settings → Resources → Network → Enable host networking). Without it, the app containers can mount the Redis socket but not reliably reach the emulator over the shared loopback.