A reproducible local Moodle development environment. Moodle core and the official Moodle Docker tooling are upstream inputs pinned by checksum; this repository owns only configuration, extensions, themes, course artefacts, tests and deployment documentation.
Requirements:
- Docker Desktop running;
- Git,
curl,unzipand a POSIX shell; - approximately 20 GB free disk space.
From this directory:
./scripts/bootstrap
./scripts/startOpen http://localhost:8000. The default local credentials are defined in
.env.example. Copy that file to .env to override them without committing
secrets.
Mail sent by Moodle is captured at http://localhost:8000/_/mail/.
./scripts/start # Start and upgrade the local site
./scripts/stop # Stop containers without deleting data
./scripts/logs # Follow PHP, PostgreSQL and mail logs
./scripts/purge-caches # Clear Moodle caches
./scripts/watch # Watch and rebuild Moodle JavaScript/SCSS
./scripts/test # Lint owned PHP and check the database schema
./scripts/cli admin/cli/cron.php
./scripts/reset --yes # Delete local DB/files and reinstallPHP changes are visible on refresh. Local configuration disables JavaScript,
language-string and theme caches. Moodle JavaScript still needs its build step,
so run ./scripts/watch while changing ESM, TypeScript or SCSS sources.
| Path | Purpose | Tracked here? |
|---|---|---|
core/ |
Official Moodle release | No |
vendor/moodle-docker/ |
Official developer runtime | No |
docker/ |
Local runtime overlays and dev configuration | Yes |
plugins/ |
Institution-owned Moodle plugins | Yes |
themes/ |
Institution-owned Moodle themes | Yes |
course-backups/ |
Deliberate, reviewed course exports | Normally no |
scripts/ |
Reproducible developer workflow | Yes |
Never patch Moodle core to add local behaviour. Configure Moodle first, then add the smallest appropriate plugin only for a validated gap.
scripts/bootstrap and scripts/start copy the tracked development
configuration into ignored core/config.php. This avoids Docker Desktop's
unsupported nested file mount while keeping docker/config.php authoritative.
Each owned plugin needs its own bind mount in both docker/local.yml and
scripts/watch — creating a directory under plugins/ is not enough on its own,
and nothing will appear in Moodle until the mount exists. Directory-wide mounts
are deliberately avoided because they would shadow core modules and question
types.
Do not develop inside core/: it is git-ignored and ./scripts/reset destroys
and reinstalls it, so work placed there is lost silently. See
docs/architecture.md for the path mapping table and the
full rationale.
.moodle-release pins the Moodle release, release archive checksum and official
Moodle Docker commit. bootstrap verifies the release checksum before using a
download. An upgrade is a reviewed change to this pin followed by a clean-core
test and database backup; see docs/architecture.md.
The Docker setup in this folder is for development and automated testing, not production. Production can later target institution-managed infrastructure or a cloud provider without changing the ownership boundary: deploy a supported Moodle core, add the tracked plugins/theme, inject production configuration and connect managed PostgreSQL plus durable object/file storage. See docs/deployment.md.
GPL-3.0-or-later, matching Moodle. See LICENSE.