erseco/alpine-moodle

By erseco

•Updated 1 day ago

Moodle docker image based on Alpine Linux

Image
9

10K+

erseco/alpine-moodle repository overview

⁠Alpine Moodle

Docker Pulls Docker Image Size nginx 1.26 php 8.3 php 8.4 opt-in moodle moosh 1.27 License MIT Build Status

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.

⁠Quick start

⁠Single container (SQLite — dev/demo only)
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⁠.

⁠Running Commands as Root

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"

⁠Configuration

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 NameDefaultDescription
LANGen_US.UTF-8System locale.
LANGUAGEen_US:enSystem language fallback chain.
SITE_URLhttp://localhostPublic site URL. Must match what users type in the browser.
REVERSEPROXYfalseSet to true only if the site is intentionally served under multiple base URLs. See the Reverse Proxy⁠ guide.
SSLPROXYfalseSet to true when a reverse proxy terminates TLS. Trusts X-Forwarded-Proto.
REDIS_HOSTHostname of the Redis instance (enables Redis sessions/cache).
REDIS_PASSWORDRedis password.
REDIS_USERRedis 6+ ACL user. Requires REDIS_PASSWORD.
DB_TYPEpgsqlpgsql, mariadb, mysqli or sqlite3.
MOODLE_DATABASE_TYPEOptional override for DB_TYPE. Set to sqlite3 to enable single-container dev/demo mode.
DB_HOSTpostgresDB container name / hostname.
DB_PORT5432Postgres=5432, MySQL/MariaDB=3306.
DB_NAMEmoodleDatabase name.
DB_USERmoodleDatabase user.
DB_PASSmoodleDatabase password.
DB_SQLITE_PATH/var/www/moodledata/sqlite/moodle.sqliteSQLite file path when using sqlite3.
DB_FETCHBUFFERSIZESet to 0 with PgBouncer in transaction mode.
DB_DBHANDLEOPTIONSfalseSet to true with PgBouncer pool modes that reject SET options.
DB_HOST_REPLICARead-only replica hostname.
DB_PORT_REPLICAReplica port (falls back to DB_PORT).
DB_USER_REPLICAReplica user (falls back to DB_USER).
DB_PASS_REPLICAReplica password (falls back to DB_PASS).
DB_PREFIXmdl_DB table prefix. Do not use numeric values.
MY_CERTIFICATESnoneBase64-encoded LDAP CA bundle.
MOODLE_EMAIL[email protected]Admin email.
MOODLE_LANGUAGEenInstaller language.
MOODLE_SITENAMEDockerized_MoodleFull site name shown on the front page.
MOODLE_USERNAMEmoodleuserAdmin username. Override on first boot.
MOODLE_PASSWORDPLEASE_CHANGEMEAdmin password. Override on first boot.
SMTP_HOSTsmtp.gmail.comSMTP server.
SMTP_PORT587SMTP port.
SMTP_USER[email protected]SMTP username.
SMTP_PASSWORDyour_passwordSMTP password.
SMTP_PROTOCOLtlstls, ssl or empty.
MOODLE_MAIL_NOREPLY_ADDRESSnoreply@localhostNo-reply address.
MOODLE_MAIL_PREFIX[moodle]Email subject prefix.
AUTO_UPDATE_MOODLEtrueSet to false to skip admin/cli/upgrade.php on container start.
DEBUGfalseWhen true, enables Moodle DEVELOPER debug level.
client_max_body_size50MNginx max request body size.
post_max_size50MPHP post_max_size.
upload_max_filesize50MPHP upload_max_filesize.
max_input_vars5000PHP max_input_vars. Keep high for Moodle course imports.
memory_limit256MPHP memory_limit. Increase if Moosh plugin installs run out of memory.
PRE_CONFIGURE_COMMANDSShell commands run before Moodle configuration.
POST_CONFIGURE_COMMANDSShell commands run after Moodle configuration (great for Moosh).
RUN_CRON_TASKStrueSet to false to disable the internal runit-managed cron loop.

⁠Moodle Playground Blueprints

āš ļø Experimental. alpine-moodle can apply Moodle Playground⁠-compatible blueprint.json files 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.

VariableDescriptionDefault
MOODLE_BLUEPRINTPath to a blueprint JSON file inside the containerempty
MOODLE_BLUEPRINT_URLRemote URL to a blueprint JSON fileempty
MOODLE_BLUEPRINT_BUNDLEPath to a local bundle directory or ZIPempty
MOODLE_BLUEPRINT_FORCEReapply even if already appliedfalse
MOODLE_BLUEPRINT_ON_ERRORabort or warnabort
MOODLE_BLUEPRINT_ALLOW_REMOTE_RESOURCESAllow URL resourcestrue
MOODLE_BLUEPRINT_ALLOW_UNSAFE_STEPSAllow unsafe steps if implementedfalse
MOODLE_BLUEPRINT_MAX_RESOURCE_SIZEMax remote resource size50M

If several sources are set, precedence is MOODLE_BLUEPRINT_BUNDLE > MOODLE_BLUEPRINT > MOODLE_BLUEPRINT_URL.

Compatibility matrix:

StepStatusNotes
setConfigsupportedUses Moodle CLI
setConfigssupportedLoops over setConfig
setAdminAccountsupportedPassword not logged
installMoodlePluginsupportedZIP resources, safe extraction
installThemesupportedZIP resources
setThemesupportedSets Moodle theme config
createCategorysupportedIdempotent
createCoursesupportedIdempotent by shortname
createUsersupportedIdempotent by username
createUserssupportedLoops over createUser
enrolUsersupportedManual enrolment
installMoodleno-opHandled by container startup
loginno-opBrowser-only, not applicable
restoreCourseplannedFails clearly until implemented
runPhpCodedisabledUnsafe
runPhpScriptdisabledUnsafe
writeFiledisabledUnsafe by default
unzipdisabledUnsafe 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⁠.

⁠Key features

  • Compact image (~100 MB) built on erseco/alpine-php-webserver⁠
  • PHP 8.3 FPM with ondemand process manager — idles near-zero CPU (opt-in PHP 8.4 images⁠ available for Moodle 5.x)
  • PostgreSQL, MariaDB/MySQL or SQLite (single-container dev mode)
  • Optional Redis session handler
  • Supports Moodle 4.x, 5.0, 5.1+ (auto-detects /public layout) and main
  • Multi-arch: amd64, arm64, arm/v7, arm/v6, 386, ppc64le, s390x
  • Moosh CLI⁠ bundled for automation
  • Pre/post configuration hooks (PRE_CONFIGURE_COMMANDS, POST_CONFIGURE_COMMANDS)
  • Runs as the non-privileged nobody user
  • Logs to stdout / stderr — just docker logs -f
  • Internal cron via runit (configurable, or run it externally)

⁠PHP 8.4 opt-in images

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 versionPHP 8.4 tag format
Moodle 5.0.xv5.0.x-php84
Moodle 5.1.xv5.1.x-php84
Moodle 5.2.xv5.2.x-php84
Moodle 5.3 LTS and laterv5.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 -php84 images 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.

⁠Registries

  • Docker Hub: erseco/alpine-moodle
  • GitHub Container Registry: ghcr.io/erseco/alpine-moodle

⁠Documentation

The full, searchable documentation lives at https://erseco.github.io/alpine-moodle/⁠:

⁠Contributing

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.

⁠License

MIT⁠

Tag summary

Content type

Image

Digest

sha256:9eb9b5787…

Size

205.8 MB

Last updated

1 day ago

docker pull erseco/alpine-moodle:beta