Files
app/docker/compose.dev.yml
stroblmeandClaude Opus 5 775d151307 Mount the worker source in dev so it cannot fall behind the engine
The engine and the worker speak a version-matched protocol, but compose.dev.yml
mounted only backend/fluksio: a reloaded engine talked to the worker baked into
the image. Adding the request id to that protocol therefore left every python
node failing with "the worker answered request None", because the old worker
echoed no id at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01StpRc2C6au1WJ1EUU7fsfu
2026-08-23 19:15:06 +02:00

182 lines
5.7 KiB
YAML

# Local development overrides: a self-contained stack with its own Traefik,
# published host ports, hot reload and the mail/browser test helpers.
# Never used in production — the Makefile only layers it for `make dev*`.
services:
# Local Traefik. Services stay reachable both on their published ports and
# on http://api.localhost / http://app.localhost via the routers in
# compose.yml. Dashboard at http://localhost:8090.
proxy:
image: traefik:3.6
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "80:80"
- "8090:8080"
command:
- --providers.docker
- --providers.docker.constraints=Label(`traefik.constraint-label`, `proxy`)
- --providers.docker.exposedbydefault=false
- --entrypoints.http.address=:80
- --entrypoints.https.address=:443
- --accesslog
- --log
- --log.level=DEBUG
- --api
- --api.insecure=true
labels:
- traefik.enable=true
- traefik.constraint-label=proxy
# Dummy https-redirect middleware that doesn't really redirect, so the
# production routers' middleware reference still resolves locally.
- traefik.http.middlewares.https-redirect.contenttype.autodetect=false
networks:
- proxy
- default
# Both only start under the analytics profile now — the engine's own state
# is SQLite on the data volume.
db:
restart: "no"
ports:
- "5432:5432"
adminer:
restart: "no"
ports:
- "127.0.0.1:8080:8080"
redis:
restart: "no"
# A broker and a time-series database of the stack's own, so the mqtt and
# influx node types are testable without external hardware. Point a node at
# broker_host `mosquitto` or url `http://influxdb:8086`.
#
# Neither publishes a host port on purpose: nothing outside the stack needs
# them, and 1883 in particular tends to be taken by the real broker on a
# machine that runs this alongside anything else.
mosquitto:
image: eclipse-mosquitto:2
restart: "no"
# The config the image ships for exactly this: listener on 1883, anonymous
# clients allowed. Its default config accepts neither.
command: mosquitto -c /mosquitto-no-auth.conf
influxdb:
image: influxdb:2.7
restart: "no"
# Dev credentials, and no volume: the container comes up initialised and a
# `down -v` is all it takes to start over.
environment:
DOCKER_INFLUXDB_INIT_MODE: setup
DOCKER_INFLUXDB_INIT_USERNAME: fluksio
DOCKER_INFLUXDB_INIT_PASSWORD: fluksio-dev-password
DOCKER_INFLUXDB_INIT_ORG: fluksio
DOCKER_INFLUXDB_INIT_BUCKET: fluksio
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: fluksio-dev-token
backend:
restart: "no"
ports:
- "8000:8000"
# Not a startup requirement — listed so the two come up with the stack,
# which starts its services by name (`make dev-local`).
depends_on:
mosquitto:
condition: service_started
influxdb:
condition: service_started
build:
context: ..
dockerfile: backend/Dockerfile
command:
- fastapi
- run
- --reload
- "fluksio/main.py"
develop:
watch:
- path: ../backend
action: sync
target: /app/backend
ignore:
- ../backend/.venv
- .venv
- path: ../backend/pyproject.toml
action: rebuild
volumes:
# What makes --reload above mean anything in the detached flow (`make dev`,
# `make dev-local`): it starts the stack with `up -d`, which never runs the
# sync above — only `docker compose watch` does. Without the mount the
# container serves the source baked into the image until it is rebuilt.
- ../backend/fluksio:/app/backend/fluksio
# The worker speaks a protocol the engine version-matches, so mounting one
# without the other leaves a reloaded engine talking to the worker baked
# into the image — which is how every python node came to fail with
# "the worker answered request None" after a protocol change.
- ../worker/fluksio_worker:/app/worker/fluksio_worker
environment:
SMTP_HOST: "mailcatcher"
SMTP_PORT: "1025"
SMTP_TLS: "false"
EMAILS_FROM_EMAIL: "info@fluksio.com"
# Test-only user seeding, needed by the Playwright suite. Dev stack only.
PRIVATE_API_ENABLED: "true"
mailcatcher:
image: schickling/mailcatcher
ports:
- "1080:1080"
- "1025:1025"
frontend:
restart: "no"
ports:
- "5173:80"
build:
context: ..
dockerfile: frontend/Dockerfile
args:
- VITE_API_URL=http://localhost:8000
- NODE_ENV=development
# Reachable at http://docs.${DOMAIN}, but a container rebuild per edit is a
# poor authoring loop — use `make docs-serve` for that.
docs:
restart: "no"
playwright:
build:
context: ..
dockerfile: frontend/Dockerfile.playwright
args:
- VITE_API_URL=http://backend:8000
- NODE_ENV=production
ipc: host
depends_on:
- backend
- mailcatcher
env_file:
- ../.env
environment:
- VITE_API_URL=http://backend:8000
# The suite takes its own origins from these, never from VITE_API_URL —
# see frontend/tests/config.ts.
- PLAYWRIGHT_API_URL=http://backend:8000
- MAILCATCHER_HOST=http://mailcatcher:1080
- PLAYWRIGHT_HTML_HOST=0.0.0.0
- CI=${CI}
volumes:
- ../frontend/blob-report:/app/frontend/blob-report
- ../frontend/test-results:/app/frontend/test-results
ports:
- 9323:9323
networks:
# Self-contained dev: create a stack-local network instead of expecting the
# shared one. compose.local.yml flips this back for the integrated stack.
proxy:
external: false