1
0

compose.scheduler.yml 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. services:
  2. scheduler:
  3. image: irdb-scheduler:latest
  4. build: { context: ./scheduler }
  5. environment:
  6. INTERNAL_JOB_TOKEN: ${INTERNAL_JOB_TOKEN}
  7. # SEC_REVIEW F25: share the api container's network namespace so the
  8. # baked crontab can hit /internal/jobs/tick over loopback. The api's
  9. # /internal/* gate is restricted to 127.0.0.1/::1 (Caddy + PHP), so
  10. # the previous `api:8081` URL from a sibling docker-bridge peer
  11. # would now 404 — and that's the goal: a malicious neighbour on the
  12. # same bridge can no longer reach /internal/*. Side effect: this
  13. # service has no DNS / its own ports, but it needs neither.
  14. network_mode: "service:api"
  15. # SEC_REVIEW F22: dependencies (curl, tini, ca-certificates) are now
  16. # baked into the image at build time with pinned versions, against a
  17. # digest-pinned alpine base. The previous `image: alpine:3` +
  18. # `apk add` at container start trusted the apk mirror on every
  19. # restart and would have given a mirror compromise a foothold in the
  20. # container that holds INTERNAL_JOB_TOKEN.
  21. read_only: true
  22. # busybox crond writes a tiny tempfile when the schedule fires; /run
  23. # has to be writable for that. Everything else stays read-only.
  24. tmpfs:
  25. - /run:mode=0755
  26. - /tmp:mode=1777
  27. # busybox crond calls initgroups() before each exec, which needs
  28. # CAP_SETGID even when the target user is the same root it is
  29. # already running as — full cap_drop crashes it with
  30. # "can't set groups: Operation not permitted". Hardening the
  31. # process to non-root would mean shipping a custom cron binary;
  32. # not worth the maintenance cost given the container has no
  33. # persistent volume, no exposed port, and only INTERNAL_JOB_TOKEN
  34. # in env. `no-new-privileges` is still useful: there is no setuid
  35. # binary in the image and we want to keep it that way.
  36. security_opt:
  37. - no-new-privileges:true
  38. depends_on:
  39. api:
  40. condition: service_healthy
  41. restart: unless-stopped