Files
Microsoft-Rewards-Script/entrypoint.sh
Michael Cammarata f51daf06d6 Docker rewrite and optimizations (#321)
* Optimizations of dockerfile

Massive test optimizations with drop in image size to about 256mb from about 1.2 gb. Drawback is that I currently have to keep the dockerfile playwright version matched to the package.json version

* further optimizations

Removed redundant (hopefully) sessions directory creation during build

* Fix docker cron dependencies

Small fix that should make cron run properly

* Major docker update!

- **Dockerfile rewritten as a multi-stage build**
  - Split into a “builder” stage (`node:18-slim`) to install dependencies and compile TypeScript, and a “runtime” stage (official Playwright image) to run the script.
  - This keeps build tools and dependencies out of the final image, making it smaller, faster to pull, and more secure.

- **Entrypoint script (`entrypoint.sh`)**
  - Introduced an entrypoint that runs inside the container at startup to:
    1. Set the container’s timezone (`TZ`) correctly, based on the environment or defaulting to UTC.
    2. Validate that the user provided a `CRON_SCHEDULE` (exiting early with an error if missing).
    3. Optionally perform an initial run of the script immediately (when `RUN_ON_START=true`), without any random sleep.
  - Centralizing setup in an entrypoint keeps the Dockerfile simpler and ensures proper signal handling.

- **`run_daily.sh` improvements**
  - Removed custom browser-path override so Playwright uses bundled browsers in the official image.
  - Added a lock using `flock` to prevent overlapping runs if a previous run is still in progress.
  - Retained the random sleep between 5 and 50 minutes before each run.
  - Logs are timestamped and clearly report success or failure.

- **Cron template tweaks**
  - Updated `src/crontab.template` so that each job line redirects both stdout and stderr into Docker’s stdout (`>> /proc/1/fd/1 2>&1`), making it easy to view logs via `docker logs`.

- **Initial-run logic**
  - The entrypoint checks `RUN_ON_START=true` and, if set, invokes `npm start` immediately (without random sleep). This provides an immediate first execution on container startup.
  - Scheduled runs via cron still go through the normal `run_daily.sh` (with sleep and locking).

- **Cron logging and visibility**
  - By redirecting cron job output to the container’s stdout, all logs (initial run and scheduled runs) appear in `docker logs`, avoiding the need to tail log files manually.

- **Error handling and validation**
  - Entry point exits early if `CRON_SCHEDULE` is missing, preventing silent misconfiguration.
  - If the initial run fails, it logs a warning but still starts cron so future scheduled runs can proceed.
  - `run_daily.sh` will exit early if a previous run is still active (locking), avoiding overlapping executions.

* Docker (multi-stage) improvements

- added cron logging in entrypoint and fixed timezone support for cron-invoked script runs
- further optimized multi-stage dockerfile
- bumped playwright version to 1.52.0 in dockerfile and package.json
- added customization and enable/disable randomization for cron start times
- optionally add container health  monitor and resource limits in compose.yaml
2025-07-17 12:16:22 +02:00

50 lines
1.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Ensure Playwright uses preinstalled browsers
export PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
# 1. Timezone: default to UTC if not provided
: "${TZ:=UTC}"
ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime
echo "$TZ" > /etc/timezone
dpkg-reconfigure -f noninteractive tzdata
# 2. Validate CRON_SCHEDULE
if [ -z "${CRON_SCHEDULE:-}" ]; then
echo "ERROR: CRON_SCHEDULE environment variable is not set." >&2
echo "Please set CRON_SCHEDULE (e.g., \"0 2 * * *\")." >&2
exit 1
fi
# 3. Initial run without sleep if RUN_ON_START=true
if [ "${RUN_ON_START:-false}" = "true" ]; then
echo "[entrypoint] Starting initial run in background at $(date)"
(
cd /usr/src/microsoft-rewards-script || {
echo "[entrypoint-bg] ERROR: Unable to cd to /usr/src/microsoft-rewards-script" >&2
exit 1
}
# Skip random sleep for initial run, but preserve setting for cron jobs
SKIP_RANDOM_SLEEP=true src/run_daily.sh
echo "[entrypoint-bg] Initial run completed at $(date)"
) &
echo "[entrypoint] Background process started (PID: $!)"
fi
# 4. Template and register cron file with explicit timezone export
if [ ! -f /etc/cron.d/microsoft-rewards-cron.template ]; then
echo "ERROR: Cron template /etc/cron.d/microsoft-rewards-cron.template not found." >&2
exit 1
fi
# Export TZ for envsubst to use
export TZ
envsubst < /etc/cron.d/microsoft-rewards-cron.template > /etc/cron.d/microsoft-rewards-cron
chmod 0644 /etc/cron.d/microsoft-rewards-cron
crontab /etc/cron.d/microsoft-rewards-cron
echo "[entrypoint] Cron configured with schedule: $CRON_SCHEDULE and timezone: $TZ; starting cron at $(date)"
# 5. Start cron in foreground (PID 1)
exec cron -f