Upgrading¶
How to move between Moodle versions safely.
Moving to Moodle 5.x? PHP 8.4 is available
Moodle 5.3+ uses PHP 8.4 by default. For 5.0–5.2, opt in using the -php84
tag (e.g. v5.2.1-php84). Moodle 4.5 retains PHP 8.3.
See PHP 8.4 (opt-in). Do not use -php84 tags on Moodle 4.x.
The basics¶
The image applies Moodle database upgrades automatically on startup unless you opt out:
Steps the container takes on start, when an existing installation is detected:
admin/cli/maintenance.php --enableadmin/cli/upgrade.php --non-interactive --allow-unstableadmin/cli/maintenance.php --disable
This covers database schema upgrades. Replacing the Moodle PHP code is handled separately by the version-aware code sync (SYNC_MOODLE_CODE, default auto) when you use a persistent moodlehtml volume (#103).
Upgrading the Moodle code¶
On start, if the volume's Moodle $version differs from the image, the container:
- Preserves
config.php, third-party plugins (any directory with aversion.phpthe image does not ship —SYNC_PRESERVE_PLUGINS=true, default) and anyEXTRA_PLUGIN_PATHS - Rsyncs
/usr/src/moodle/→/var/www/html/(--deleteremoves leftover core files) - Restores the preserved paths — relocating them into
public/when upgrading across the Moodle 5.1 layout change - Writes
.alpine-moodle-release - Continues with the usual
AUTO_UPDATE_MOODLE/upgrade.phpflow
This mirrors Moodle's official upgrade procedure: replace the code, keep config.php, carry custom plugins over, then run the upgrade. Moodle itself decides afterwards whether each carried-over plugin needs a DB upgrade or is incompatible.
Operator steps:
- Back up the database and
moodledata(see Persistence & Volumes). -
Change the image tag:
-
Pull and recreate:
Look for a log line like
Moodle code sync: 2025041401.00 → 2025041402.00.
Third-party plugins that live only on the volume are kept automatically (SYNC_PRESERVE_PLUGINS=true, default). Custom paths without a version.php should either be listed in EXTRA_PLUGIN_PATHS or reinstalled declaratively via PLUGINS / Moosh after each sync. Set SYNC_PRESERVE_PLUGINS=false if you want the sync to produce a pristine image tree instead (third-party plugin code is then deleted).
To keep today's "volume always wins" behaviour (no automatic core refresh):
The container filesystem is the code. Upgrading is just:
Re-install plugins on every recreate with PLUGINS or POST_CONFIGURE_COMMANDS + Moosh.
Always back up first
Take a database dump and a tarball of moodledata before major upgrades. Code sync replaces files under /var/www/html (except config.php, preserved third-party plugins and EXTRA_PLUGIN_PATHS).
Upgrading from Moodle < 5.1 to ≥ 5.1¶
Moodle 5.1 introduces a public/ subdirectory for all web-exposed files (MDL-83424). The container handles this automatically: when it detects /var/www/html/public, it rewrites the Nginx root and runs composer install --no-dev --classmap-authoritative.
Recommended upgrade flow:
- Back up:
config.php- the
moodledatavolume - the database
- Stop the stack and remove the
moodlehtmlvolume (as above) — this is essential because the old 5.0 layout will otherwise confuse the new server config. - Change the image tag to a
5.1.x(or newer) release. - Start the stack. The container installs the new code, serves it from
/public, and runscomposer install. - Reapply customisations (plugins, themes,
config.phptweaks).
If you see "/var/www/html/vendor/composer does not exist" (#117), the container has not finished bootstrapping yet. Watch docker compose logs -f moodle — the error is transient unless it recurs after 30+ seconds.
Upgrading moodledata mounted from an older installation¶
Mounting an existing populated moodledata from a different image (for example migrating from Bitnami) can hit permission or layout mismatches (#114, #105):
Checklist:
- The volume must be writable by UID
65534(nobody). Fix withsudo chown -R 65534:65534 moodledata. config.phpon the new container must match the database — mount it alongside or inject it viaPOST_CONFIGURE_COMMANDS.- The target Moodle version must be equal to or newer than the version that created the data.
For a full Bitnami migration see #105. In short: restore the database first, mount moodledata second, ensure the admin credentials in config.php match the database, then start the container.
Disabling automatic upgrades¶
Set AUTO_UPDATE_MOODLE=false if you prefer to run admin/cli/upgrade.php manually:
Manual upgrade:
docker compose exec moodle php admin/cli/maintenance.php --enable
docker compose exec moodle php admin/cli/upgrade.php --non-interactive
docker compose exec moodle php admin/cli/maintenance.php --disable
Skipping versions¶
Follow the target release's minimum supported source version. Moodle 5.3 supports upgrading directly from 4.5; intermediate 5.0/5.1/5.2 upgrades are not required. Test the database requirements and actual plugins on a restored staging copy, and back up both the database and files. See the 5.3 migration plan.