Moodle docker image based on Alpine Linux
10K+
A lightweight Moodle Docker image built on Alpine Linuxā ā ~100 MB, PHP 8.3 FPM, Nginx, multi-arch, configured entirely through environment variables.
š Full documentation: https://erseco.github.io/alpine-moodle/ā
The documentation site covers quick start, docker-compose recipes, reverse proxy setups (Traefik, Nginx, NPM, Apache, Caddy), every supported environment variable, persistence and upgrade workflows, and a troubleshooting section built from the most frequent support questions.
docker run -d \
-p 80:8080 \
-e MOODLE_DATABASE_TYPE=sqlite3 \
-e MOODLE_PASSWORD=ChangeMe123! \
-v moodledata:/var/www/moodledata \
erseco/alpine-moodle
Open http://localhostā and log in with moodleuser / ChangeMe123!.
services:
postgres:
image: postgres:alpine
restart: unless-stopped
environment:
POSTGRES_PASSWORD: moodle
POSTGRES_USER: moodle
POSTGRES_DB: moodle
volumes:
- postgres:/var/lib/postgresql
moodle:
image: erseco/alpine-moodle
restart: unless-stopped
environment:
MOODLE_USERNAME: admin
MOODLE_PASSWORD: ChangeMe123!
ports:
- "80:8080"
volumes:
- moodledata:/var/www/moodledata
- moodlehtml:/var/www/html
depends_on:
- postgres
volumes:
postgres:
moodledata:
moodlehtml:
docker compose up -d
For production deployments (reverse proxy, TLS, Redis, tuning, upgrades), see the documentation siteā .
In certain situations, you might need to run commands as root within your Moodle container, for example, to install additional packages. You can do this using the docker compose exec command with the --user root option:
docker compose exec --user root moodle sh
Example ā install an extra Alpine package for debugging:
docker compose exec --user root moodle sh -c "apk update && apk add nano curl"
Define the ENV variables in docker-compose.yml. The full reference with notes, grouping and defaults lives at https://erseco.github.io/alpine-moodle/environment-variables/ā .
| Variable Name | Default | Description |
|---|---|---|
LANG | en_US.UTF-8 | System locale. |
LANGUAGE | en_US:en | System language fallback chain. |
SITE_URL | http://localhost | Public site URL. Must match what users type in the browser. |
REVERSEPROXY | false | Set to true only if the site is intentionally served under multiple base URLs. See the Reverse Proxyā guide. |
SSLPROXY | false | Set to true when a reverse proxy terminates TLS. Trusts X-Forwarded-Proto. |
REDIS_HOST | Hostname of the Redis instance (enables Redis sessions/cache). | |
REDIS_PASSWORD | Redis password. | |
REDIS_USER | Redis 6+ ACL user. Requires REDIS_PASSWORD. | |
DB_TYPE | pgsql | pgsql, mariadb, mysqli or sqlite3. |
MOODLE_DATABASE_TYPE | Optional override for DB_TYPE. Set to sqlite3 to enable single-container dev/demo mode. | |
DB_HOST | postgres | DB container name / hostname. |
DB_PORT | 5432 | Postgres=5432, MySQL/MariaDB=3306. |
DB_NAME | moodle | Database name. |
DB_USER | moodle | Database user. |
DB_PASS | moodle | Database password. |
DB_SQLITE_PATH | /var/www/moodledata/sqlite/moodle.sqlite | SQLite file path when using sqlite3. |
DB_FETCHBUFFERSIZE | Set to 0 with PgBouncer in transaction mode. | |
DB_DBHANDLEOPTIONS | false | Set to true with PgBouncer pool modes that reject SET options. |
DB_HOST_REPLICA | Read-only replica hostname. | |
DB_PORT_REPLICA | Replica port (falls back to DB_PORT). | |
DB_USER_REPLICA | Replica user (falls back to DB_USER). | |
DB_PASS_REPLICA | Replica password (falls back to DB_PASS). | |
DB_PREFIX | mdl_ | DB table prefix. Do not use numeric values. |
MY_CERTIFICATES | none | Base64-encoded LDAP CA bundle. |
MOODLE_EMAIL | [email protected] | Admin email. |
MOODLE_LANGUAGE | en | Installer language. |
MOODLE_SITENAME | Dockerized_Moodle | Full site name shown on the front page. |
MOODLE_USERNAME | moodleuser | Admin username. Override on first boot. |
MOODLE_PASSWORD | PLEASE_CHANGEME | Admin password. Override on first boot. |
SMTP_HOST | smtp.gmail.com | SMTP server. |
SMTP_PORT | 587 | SMTP port. |
SMTP_USER | [email protected] | SMTP username. |
SMTP_PASSWORD | your_password | SMTP password. |
SMTP_PROTOCOL | tls | tls, ssl or empty. |
MOODLE_MAIL_NOREPLY_ADDRESS | noreply@localhost | No-reply address. |
MOODLE_MAIL_PREFIX | [moodle] | Email subject prefix. |
AUTO_UPDATE_MOODLE | true | Set to false to skip admin/cli/upgrade.php on container start. |
DEBUG | false | When true, enables Moodle DEVELOPER debug level. |
client_max_body_size | 50M | Nginx max request body size. |
post_max_size | 50M | PHP post_max_size. |
upload_max_filesize | 50M | PHP upload_max_filesize. |
max_input_vars | 5000 | PHP max_input_vars. Keep high for Moodle course imports. |
memory_limit | 256M | PHP memory_limit. Increase if Moosh plugin installs run out of memory. |
PRE_CONFIGURE_COMMANDS | Shell commands run before Moodle configuration. | |
POST_CONFIGURE_COMMANDS | Shell commands run after Moodle configuration (great for Moosh). | |
RUN_CRON_TASKS | true | Set to false to disable the internal runit-managed cron loop. |
ā ļø Experimental.
alpine-moodlecan apply Moodle Playgroundā -compatibleblueprint.jsonfiles after Moodle has been installed or upgraded. This is an additional declarative provisioning layer for repeatable development, QA, CI and demo scenarios ā it does not replace the environment-variable configuration. Only a documented subset of steps is implemented; unsupported steps fail clearly and unsafe steps are disabled by default.
The same blueprint.json can describe one Moodle scenario for two complementary sibling runtimes:
moodle-playgroundā ā the browser/WASM runtime for ephemeral QA, demos, shareable reproductions and fast validation. No server required.alpine-moodle ā this Docker runtime for local development, CI, plugin development, integration testing, persistence and real server-side behaviour (cron, mail, database, file system).Author a blueprint once; run it in the browser for a quick look and in Docker when you need a real, persistent Moodle.
A new startup hook (rootfs/docker-entrypoint-init.d/03-apply-blueprint.sh) runs after 02-configure-moodle.sh and calls /usr/local/bin/moodle-blueprint apply when a blueprint variable is set.
| Variable | Description | Default |
|---|---|---|
MOODLE_BLUEPRINT | Path to a blueprint JSON file inside the container | empty |
MOODLE_BLUEPRINT_URL | Remote URL to a blueprint JSON file | empty |
MOODLE_BLUEPRINT_BUNDLE | Path to a local bundle directory or ZIP | empty |
MOODLE_BLUEPRINT_FORCE | Reapply even if already applied | false |
MOODLE_BLUEPRINT_ON_ERROR | abort or warn | abort |
MOODLE_BLUEPRINT_ALLOW_REMOTE_RESOURCES | Allow URL resources | true |
MOODLE_BLUEPRINT_ALLOW_UNSAFE_STEPS | Allow unsafe steps if implemented | false |
MOODLE_BLUEPRINT_MAX_RESOURCE_SIZE | Max remote resource size | 50M |
If several sources are set, precedence is MOODLE_BLUEPRINT_BUNDLE > MOODLE_BLUEPRINT > MOODLE_BLUEPRINT_URL.
Compatibility matrix:
| Step | Status | Notes |
|---|---|---|
setConfig | supported | Uses Moodle CLI |
setConfigs | supported | Loops over setConfig |
setAdminAccount | supported | Password not logged |
installMoodlePlugin | supported | ZIP resources, safe extraction |
installTheme | supported | ZIP resources |
setTheme | supported | Sets Moodle theme config |
createCategory | supported | Idempotent |
createCourse | supported | Idempotent by shortname |
createUser | supported | Idempotent by username |
createUsers | supported | Loops over createUser |
enrolUser | supported | Manual enrolment |
installMoodle | no-op | Handled by container startup |
login | no-op | Browser-only, not applicable |
restoreCourse | planned | Fails clearly until implemented |
runPhpCode | disabled | Unsafe |
runPhpScript | disabled | Unsafe |
writeFile | disabled | Unsafe by default |
unzip | disabled | Unsafe by default |
Minimal example:
services:
moodle:
image: erseco/alpine-moodle:latest
ports:
- "8080:8080"
environment:
MOODLE_DATABASE_TYPE: sqlite3
MOODLE_USERNAME: admin
MOODLE_PASSWORD: ChangeMe123!
MOODLE_EMAIL: [email protected]
MOODLE_SITENAME: "Blueprint Demo"
MOODLE_BLUEPRINT: /blueprints/demo.blueprint.json
volumes:
- moodledata:/var/www/moodledata
- ./demo.blueprint.json:/blueprints/demo.blueprint.json:ro
volumes:
moodledata:
{
"$schema": "https://raw.githubusercontent.com/ateeducacion/moodle-playground/main/assets/blueprints/blueprint-schema.json",
"preferredVersions": { "php": "8.3", "moodle": "5.0" },
"landingPage": "/course/index.php",
"steps": [
{ "step": "setConfig", "name": "debug", "value": 32767 },
{ "step": "createCategory", "name": "Blueprint demo", "idnumber": "blueprint-demo" },
{ "step": "createCourse", "fullname": "Blueprint demo course", "shortname": "BLUEPRINT101", "category": "blueprint-demo" },
{ "step": "createUser", "username": "student1", "password": "ChangeMe123!", "email": "[email protected]", "firstname": "Student", "lastname": "One" },
{ "step": "enrolUser", "username": "student1", "course": "BLUEPRINT101", "role": "student" }
]
}
Bundles co-locate a blueprint.json with its resources (directory or ZIP, blueprint.json at the root or one directory deep, __MACOSX ignored):
my-moodle-blueprint/
āāā blueprint.json
āāā plugins/
āāā mod_example.zip
See the full guide, resource descriptors, security model and idempotency notes in docs/blueprints.mdā (published at https://erseco.github.io/alpine-moodle/blueprints/ā ). A copy-pasteable example lives in docs/examples/demo.blueprint.jsonā .
erseco/alpine-php-webserverā ondemand process manager ā idles near-zero CPU (opt-in PHP 8.4 imagesā available for Moodle 5.x)/public layout) and mainamd64, arm64, arm/v7, arm/v6, 386, ppc64le, s390xPRE_CONFIGURE_COMMANDS, POST_CONFIGURE_COMMANDS)nobody userstdout / stderr ā just docker logs -frunit (configurable, or run it externally)The default erseco/alpine-moodle tags currently remain on PHP 8.3 to preserve compatibility with existing Moodle 4.5 LTS installations and avoid breaking existing deployments.
PHP 8.4 images are available as opt-in tags for Moodle 5.x and later, identified by a -php84 suffix:
| Moodle version | PHP 8.4 tag format |
|---|---|
| Moodle 5.0.x | v5.0.x-php84 |
| Moodle 5.1.x | v5.1.x-php84 |
| Moodle 5.2.x | v5.2.x-php84 |
| Moodle 5.3 LTS and later | v5.3.x-php84 and later |
docker pull erseco/alpine-moodle:v5.2.1-php84
docker pull ghcr.io/erseco/alpine-moodle:v5.2.1-php84
Moodle 4.x is not available on PHP 8.4. Moodle 4.5 LTS does not support PHP 8.4, so no
-php84images are published for the 4.x line ā keep using the default PHP 8.3 tags there.
These -php84 tags are built from the php84 branchā and never overwrite the existing latest, main, or vX.Y.Z tags, which stay on PHP 8.3 for now.
The default official tags ā including latest ā will move to PHP 8.4 once Moodle 5.3 LTS (planned for 5 October 2026) is released and becomes the new LTS baseline.
erseco/alpine-moodleghcr.io/erseco/alpine-moodleThe full, searchable documentation lives at https://erseco.github.io/alpine-moodle/ā :
Issues and pull requests are welcome: https://github.com/erseco/alpine-moodle/issuesā .
Documentation sources live under docs/ā and are built with Zensicalā via the docs.yml GitHub Actions workflow.
Content type
Image
Digest
sha256:9eb9b5787ā¦
Size
205.8 MB
Last updated
1 day ago
docker pull erseco/alpine-moodle:beta