Run changedetection.io for Website Change Alerts With Docker Compose

Watch a page for meaningful changes without hand-refreshing it all day, then keep the first deployment private and modest instead of promising that every JavaScript-heavy site will work out of the box.

changedetection.io Docker Compose Alerts
Illustrated guide cover for Run changedetection.io for Website Change Alerts With Docker Compose
changedetection.io • Docker Compose • Alerts
What you learn

How to run changedetection.io locally, store watches persistently, and test notifications before you trust the service.

Best for

Operators who need simple page-change alerts for status pages, product docs, pricing pages, or lightweight monitoring tasks.

Risk to watch

If you overcomplicate the first install with browser automation and too many watches, you create noise before you create value.

Before you begin

  • A Docker host with Compose v2.
  • A private admin path or reverse proxy plan.
  • One or two specific pages you genuinely want to monitor.
  • A notification destination you can test, such as email, ntfy, or another supported webhook target.

changedetection.io's current docs still treat Docker as the easiest deployment path and keep the application state inside /datastore. That makes it a good fit for a small self-hosting stack as long as you keep the first rollout focused.

Expected outcome: you will finish with a private changedetection.io instance, at least one working watch, and a tested notification path.

Step 1: Create the Compose stack

Create a working directory and save this as compose.yaml:

mkdir -p /opt/stacks/changedetection
cd /opt/stacks/changedetection
services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io:latest
    container_name: changedetection
    restart: unless-stopped
    ports:
      - 127.0.0.1:5000:5000
    volumes:
      - changedetection_data:/datastore

volumes:
  changedetection_data:

Binding to localhost only is the safer default. You can always put it behind a private reverse proxy later. Starting with a simple container also keeps the first troubleshooting loop short.

Step 2: Start and secure the service

Bring up the stack and check the logs:

docker compose up -d
docker compose ps
docker compose logs --tail 50 changedetection

Reach the app privately by SSH port forwarding or a protected reverse proxy. changedetection.io supports authentication and access-control features, but private network reachability is still the cleaner baseline than exposing another unauthenticated web UI to the public internet.

Step 3: Add the first watch and notification

Add one stable URL first. A documentation page, status page, or product page is a better first candidate than a chaotic home page with ads, rotating timestamps, or personalized content.

Then configure one notification destination and test it immediately. changedetection.io supports many notification backends, but the valuable part is proving one real end-to-end alert instead of collecting ten half-configured outputs.

Warning: if a page includes timestamps, tracking fragments, or randomized sections, tighten the watch filters before you trust the alert volume. Noise is the fastest way to stop respecting the system.

Step 4: Add browser fetching only if needed

Some modern pages render important content only in the browser. changedetection.io can work with a browser-fetching sidecar, but you should add that only when the basic fetch path fails on a specific site.

A common pattern is to add a Playwright-based sidecar and point only the affected watches at it. Keep that as an exception path. Do not assume every site needs headless browser rendering.

services:
  browserless:
    image: browserless/chrome:latest
    restart: unless-stopped

Exact sidecar settings evolve upstream. When you add this layer, recheck the current changedetection.io documentation and test one difficult page intentionally before widening the rollout.

Step 5: Operate and update safely

Routine checks:

docker compose ps
docker compose logs --tail 50 changedetection
docker volume ls | grep changedetection

Update the stack:

cd /opt/stacks/changedetection
docker compose pull
docker compose up -d

Review the first few alert cycles after any upgrade. A watcher that silently breaks is worse than one that fails loudly during testing.

Rollback notes

The persistent state lives in /datastore, so protect that volume before major changes. If an update misbehaves, revert the image tag, recreate the container, and confirm that your watches and notifications still exist.

If browser-side rendering caused the trouble, remove that extra layer first and prove the base watcher still works on simpler URLs.

Troubleshooting

The watch fires constantly on a mostly unchanged page.
Filter noisy sections, remove timestamps or rotating fragments, and validate the watch preview before blaming the app.

The page shows blank or incomplete content.
That usually means the site depends on client-side rendering. Test a browser-fetcher path for that specific watch instead of converting the whole stack immediately.

You never receive notifications.
Test the notification target directly, then send a watch test event before waiting for a real page change.

The UI is reachable publicly.
Move the bind address back to localhost or put the service behind an authenticated private path right away.

What to do next: continue with Send Self-Hosting Alerts with ntfy if you want a lightweight push destination, or Set Up Healthchecks for Backups and Cron Jobs for a complementary failure-alert surface.