Dockerfile 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. # syntax=docker/dockerfile:1.7
  2. #
  3. # IRDB scheduler sidecar image (SEC_REVIEW F22).
  4. #
  5. # Replaces the previous `image: alpine:3` + `apk add curl tini` at
  6. # container start: the floating tag pulled whatever Alpine shipped on
  7. # any given restart, and the runtime apk fetch made every restart
  8. # trust-on-first-use against the apk mirror. A package-mirror compromise
  9. # (or typosquat) would have given root in the scheduler — which holds
  10. # INTERNAL_JOB_TOKEN and can call /internal/jobs/* — on every restart.
  11. #
  12. # Now: pinned digest, pinned apk versions, all dependency installation
  13. # happens once at build time. Restart cost is just `docker run` of the
  14. # already-built local image.
  15. FROM alpine:3.21@sha256:48b0309ca019d89d40f670aa1bc06e426dc0931948452e8491e3d65087abc07d
  16. # Pinned via `apk policy` against the same digest above (alpine 3.21
  17. # main + community at build time of this Dockerfile). Bump these
  18. # explicitly when the base image is bumped — the build will fail loudly
  19. # if the version is no longer available, which is the desired signal.
  20. RUN apk add --no-cache \
  21. curl=8.14.1-r2 \
  22. tini=0.19.0-r3 \
  23. ca-certificates=20260413-r0
  24. # Bake the canonical schedule into the image. Operators who want a
  25. # different cadence can still bind-mount their own crontab over
  26. # /etc/crontabs/root in compose.
  27. COPY scheduler.crontab /etc/crontabs/root
  28. # crond runs as root by default in busybox; that is fine — the
  29. # container has no persistent volume, no network exposure, and only
  30. # the INTERNAL_JOB_TOKEN env var as state. Dropping privileges here
  31. # would mean granting CAP_SETUID-or-similar so crond can read
  32. # /etc/crontabs/root as a non-root user, which is a worse trade.
  33. ENTRYPOINT ["/sbin/tini", "--"]
  34. CMD ["crond", "-f", "-L", "/dev/stdout"]