d552e289cb
Hardcoded crontab → render at container start from DIGEST_CRON_AM + DIGEST_CRON_PM. Defaults match the original 0800 / 2000 so existing deploys are no-ops. scripts/add-digest-user.sh learns --am and --pm flags so each teammate's stack can fire on their hours: scripts/add-digest-user.sh bob --am "0 6 * * *" --pm "0 17 * * *" scripts/add-digest-user.sh carol --pm "30 18 * * 1-5" # weekdays only Standard 5-field cron syntax; busybox crond honors the container's \$TZ. Removed the now-unused stacks/news-digest/crontab file and the matching COPY in the Dockerfile.
55 lines
2.2 KiB
Docker
55 lines
2.2 KiB
Docker
# news-digest — base image for two containers in this stack:
|
|
#
|
|
# news-digest-worker — runs alpine's busybox crond + the one-shot
|
|
# digest.py per fire (default ENTRYPOINT).
|
|
# news-digest-web — runs uvicorn web:app (overridden in compose)
|
|
# to serve /output as static + the tiny
|
|
# hidden-items API at /api/*.
|
|
#
|
|
# Single image, two roles selected via compose `command:`.
|
|
# Bind-mounted /output is the shared canvas: worker writes HTML, web
|
|
# serves it.
|
|
|
|
FROM python:3.12-alpine
|
|
|
|
ENV PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
PIP_DISABLE_PIP_VERSION_CHECK=1
|
|
|
|
# tzdata so $TZ works for cron + datetime; tini so signals propagate cleanly.
|
|
RUN apk add --no-cache tzdata tini bash curl
|
|
|
|
# fastapi + uvicorn[standard] for the web container; requests + jinja2
|
|
# for the worker. Both shipped in both containers — neither set is
|
|
# heavy enough to justify splitting the image.
|
|
# trafilatura: main-content extractor for the article-summary upgrade
|
|
# (worker only — it pulls lxml + a handful of HTML utils, ~80 MB total).
|
|
# libxml2-dev/libxslt-dev are for lxml's musl wheels. apk caches are
|
|
# cleaned in the same RUN to keep the layer small.
|
|
RUN apk add --no-cache --virtual .build-deps gcc musl-dev libxml2-dev libxslt-dev \
|
|
&& apk add --no-cache libxml2 libxslt \
|
|
&& pip install --no-cache-dir \
|
|
requests jinja2 trafilatura \
|
|
'fastapi>=0.115' 'uvicorn[standard]>=0.30' \
|
|
&& apk del .build-deps
|
|
|
|
WORKDIR /app
|
|
COPY digest.py /app/digest.py
|
|
COPY seed-headlines.py /app/seed-headlines.py
|
|
COPY web.py /app/web.py
|
|
COPY templates /app/templates
|
|
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
|
COPY run-digest.sh /usr/local/bin/run-digest.sh
|
|
# /etc/crontabs/root is written by entrypoint.sh from
|
|
# DIGEST_CRON_AM/DIGEST_CRON_PM env at container start, so each
|
|
# per-user instance gets its own schedule. Image no longer ships a
|
|
# baked-in crontab.
|
|
RUN chmod +x /usr/local/bin/entrypoint.sh /usr/local/bin/run-digest.sh
|
|
|
|
# Sentinel + first-run output dir
|
|
VOLUME /output
|
|
|
|
# Default ENTRYPOINT runs the worker (cron). The web container in
|
|
# compose overrides both entrypoint and command to launch uvicorn.
|
|
ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/entrypoint.sh"]
|