thermograph/infra/docker-compose.openmeteo.yml
Emi Griffith ae1d9bb534 Subtree-merge thermograph-infra (origin/main) into infra/
git-subtree-dir: infra
git-subtree-mainline: d6df04eab2
git-subtree-split: 99b4b3f78d
2026-07-22 22:01:11 -07:00

72 lines
3.3 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Self-hosted Open-Meteo overlay — serves the ERA5 archive locally so the app is
# off the rate-limited public archive API. Enable it only on the self-hosting host:
#
# docker compose -f docker-compose.yml -f docker-compose.openmeteo.yml up -d
#
# The hourly .om data (copernicus_era5_land 0.1° + copernicus_era5 0.25°) lives in
# OBJECT STORAGE, surfaced on the host as a local directory by an rclone FUSE mount
# (a host systemd unit — see deploy/openmeteo/README.md). OM_DATA_DIR points the
# containers at that mount; it defaults to ./data/om-archive so a local smoke test
# works against a plain directory. Object storage is never bind-mounted into the app
# — only Open-Meteo reads it; the app just talks HTTP to open-meteo-api and keeps its
# own daily-per-cell climate record in the TimescaleDB `db` service.
#
# One-time backfill (writes ~11.5 TB of .om to object storage — run once before the
# app is flipped over): `make om-backfill`.
services:
# Serves /v1/archive on the compose network. No host port: only `backend`
# reaches it, as http://open-meteo-api:8080. Reads .om from the object-storage
# mount, on demand for any point, returning JSON byte-identical to the public
# archive API.
open-meteo-api:
image: ${OM_IMAGE:-ghcr.io/open-meteo/open-meteo}
command: ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]
volumes:
- ${OM_DATA_DIR:-./data/om-archive}:/app/data
restart: unless-stopped
# Rolling keep-current worker for ERA5-Land (0.1°): the surface variables it
# carries. --past-days 14 re-syncs the recent tail every day, appending new days and
# absorbing ERA5T→final corrections. dew_point_2m → relative_humidity and
# shortwave_radiation → apparent_temperature are derived server-side at query time.
open-meteo-sync-land:
image: ${OM_IMAGE:-ghcr.io/open-meteo/open-meteo}
command:
- "sync"
- "copernicus_era5_land"
- "temperature_2m,dew_point_2m,precipitation,shortwave_radiation,wind_u_component_10m,wind_v_component_10m"
- "--past-days"
- "${OM_SYNC_PAST_DAYS:-14}"
- "--repeat-interval"
- "1440"
volumes:
- ${OM_DATA_DIR:-./data/om-archive}:/app/data
restart: unless-stopped
# Rolling keep-current worker for ERA5 (0.25°): wind gusts — absent from ERA5-Land —
# plus the seamless-blend fallback over water/coastline where ERA5-Land has no data.
open-meteo-sync-era5:
image: ${OM_IMAGE:-ghcr.io/open-meteo/open-meteo}
command:
- "sync"
- "copernicus_era5"
- "wind_gusts_10m,temperature_2m,dew_point_2m,precipitation,shortwave_radiation,wind_u_component_10m,wind_v_component_10m"
- "--past-days"
- "${OM_SYNC_PAST_DAYS:-14}"
- "--repeat-interval"
- "1440"
volumes:
- ${OM_DATA_DIR:-./data/om-archive}:/app/data
restart: unless-stopped
# Point backend's historical fetches at the local instance (frontend never
# fetches climate data itself). Set here (not in the base file) so it
# applies only when this overlay is active — and so an unset var never
# reaches the app as an empty string, which would defeat climate.py's default.
backend:
depends_on:
open-meteo-api:
condition: service_started
environment:
THERMOGRAPH_ARCHIVE_URL: http://open-meteo-api:8080/v1/archive