# syntax=docker/dockerfile:1.7
#
# IRDB scheduler sidecar image (SEC_REVIEW F22).
#
# Replaces the previous `image: alpine:3` + `apk add curl tini` at
# container start: the floating tag pulled whatever Alpine shipped on
# any given restart, and the runtime apk fetch made every restart
# trust-on-first-use against the apk mirror.  A package-mirror compromise
# (or typosquat) would have given root in the scheduler — which holds
# INTERNAL_JOB_TOKEN and can call /internal/jobs/* — on every restart.
#
# Now: pinned digest, pinned apk versions, all dependency installation
# happens once at build time. Restart cost is just `docker run` of the
# already-built local image.

FROM alpine:3.21@sha256:48b0309ca019d89d40f670aa1bc06e426dc0931948452e8491e3d65087abc07d

# Pinned via `apk policy` against the same digest above (alpine 3.21
# main + community at build time of this Dockerfile). Bump these
# explicitly when the base image is bumped — the build will fail loudly
# if the version is no longer available, which is the desired signal.
RUN apk add --no-cache \
        curl=8.14.1-r2 \
        tini=0.19.0-r3 \
        ca-certificates=20260413-r0

# Bake the canonical schedule into the image. Operators who want a
# different cadence can still bind-mount their own crontab over
# /etc/crontabs/root in compose.
COPY scheduler.crontab /etc/crontabs/root

# crond runs as root by default in busybox; that is fine — the
# container has no persistent volume, no network exposure, and only
# the INTERNAL_JOB_TOKEN env var as state. Dropping privileges here
# would mean granting CAP_SETUID-or-similar so crond can read
# /etc/crontabs/root as a non-root user, which is a worse trade.
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["crond", "-f", "-L", "/dev/stdout"]
