https://github.com/erseco/alpine-moodle
Moodle docker image based on Alpine Linux
https://github.com/erseco/alpine-moodle
alpine docker hacktoberfest lightweight lms moodle nginx php8
Last synced: 3 months ago
JSON representation
Moodle docker image based on Alpine Linux
- Host: GitHub
- URL: https://github.com/erseco/alpine-moodle
- Owner: erseco
- License: mit
- Created: 2020-04-29T17:02:22.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2025-10-01T21:58:43.000Z (3 months ago)
- Last Synced: 2025-10-01T23:33:34.671Z (3 months ago)
- Topics: alpine, docker, hacktoberfest, lightweight, lms, moodle, nginx, php8
- Language: Shell
- Homepage: https://hub.docker.com/r/erseco/alpine-moodle
- Size: 203 KB
- Stars: 58
- Watchers: 6
- Forks: 40
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome - erseco/alpine-moodle - Moodle docker image based on Alpine Linux (Shell)
README
# Moodle on Alpine Linux
[](https://hub.docker.com/r/erseco/alpine-moodle/)







A lightweight Moodle Docker image built on [Alpine Linux](https://alpinelinux.org/). (~100MB)
Repository: https://github.com/erseco/alpine-moodle
**Key Features**
- Built on the lightweight image https://github.com/erseco/alpine-php-webserver
- Compact Docker image size (~100MB)
- Uses PHP 8.3 FPM for better performance, lower cpu usage & memory footprint
- Includes Composer.
- Supports Moodle <5.1 and >=5.1 (detects /public directory automatically).
- Includes Redis session handler support.
- Includes [Moosh CLI](https://github.com/tmuras/moosh) for Moodle management.
- Configurable via environment variables (see Dockerfile).
- Support for HA installations: php-redis, php-ldap (also with self-signed certs)
- Multi-arch support: 386, amd64, arm/v6, arm/v7, arm64, ppc64le, s390x
- Optimized for 100 concurrent users
- Optimized to only use resources when there's traffic (by using PHP-FPM's ondemand PM)
- Uses `runit` instead of `supervisord` to reduce memory footprint
- Cron jobs run every 180 seconds by runit
- Sample `docker compose.yml` with PostgreSQL and Redis
- Configuration via `ENV` variables
- Services (`Nginx`, `PHP-FPM` run under a non-privileged user (`nobody`) for improved security
- Logs are sent to container's STDOUT (`docker logs -f `)
- Extensible via pre/post configuration hooks
- Follows the KISS principle (Keep It Simple, Stupid) to make it easy to understand and adjust the image to your needs
## Important notes
- **Change default credentials**: Always override `MOODLE_USERNAME` and `MOODLE_PASSWORD` with secure values.
- **Moodle ≥ 5.1**: The script automatically reconfigures Nginx to serve files from `/public`.
- **Moodle < 5.1**: A compatibility patch is applied to `publicpaths.php` to support port mapping inside the container.
### Upgrading from Moodle < 5.1 to ≥ 5.1
Moodle 5.1 introduces a new `/public` directory for all web-accessible files.
If you are upgrading from 5.0 or earlier:
1. **Back up critical data**:
- `config.php`
- `moodledata/` directory
- Database dump
2. **Clean old files**: Remove any remaining files under `/var/www/html/` to prevent stale or conflicting code.
3. **Restore configuration**: Copy back `config.php` and custom plugins/themes to the new codebase.
4. **Run dependencies**: The container will automatically execute `composer install` when `/public` is detected.
## Usage
**From Docker Hub:**
```bash
docker compose up
```
> Log in using the credentials defined by environment variables.
**From GHCR:**
```yaml
services:
moodle:
image: ghcr.io/erseco/alpine-moodle
# rest of your config
```
## 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. Here's how:
```bash
docker compose exec --user root moodle sh
```
## Configuration
Define the ENV variables in docker compose.yml file
| Variable Name | Default | Description |
|-----------------------------|----------------------|------------------------------------------------------------------------------------------------|
| LANG | en_US.UTF-8 | |
| LANGUAGE | en_US:en | |
| SITE_URL | http://localhost | Sets the public site url |
| REVERSEPROXY | false | See [Reverse Proxy Configuration](#reverse-proxy-configuration). |
| SSLPROXY | false | See [Reverse Proxy Configuration](#reverse-proxy-configuration). |
| REDIS_HOST | | Set the host of the redis instance. Ej. redis |
| DB_TYPE | pgsql | mysqli - pgsql - mariadb |
| DB_HOST | postgres | DB_HOST Ej. db container name |
| DB_PORT | 5432 | Postgres=5432 - MySQL=3306 |
| DB_NAME | moodle | |
| DB_USER | moodle | |
| DB_FETCHBUFFERSIZE | | Set to 0 if using PostgresSQL poolers like PgBouncer in 'transaction' mode |
| DB_DBHANDLEOPTIONS | false | Set to true if using PostgresSQL poolers like PgBouncer which does not support sending options |
| DB_HOST_REPLICA | | Database hostname of the read-only replica database |
| DB_PORT_REPLICA | | Database port of replica, left it empty to be same as DB_PORT |
| DB_USER_REPLICA | | Database login username of replica, left it empty to be same as DB_USER |
| DB_PASS_REPLICA | | Database login password of replica, left it empty to be same as DB_PASS |
| DB_PREFIX | mdl_ | Database prefix. WARNING: don't use numeric values or moodle won't start |
| MY_CERTIFICATES | none | Trusted LDAP certificate or chain getting through base64 encode |
| MOODLE_EMAIL | user@example.com | |
| MOODLE_LANGUAGE | en | |
| MOODLE_SITENAME | New-Site | |
| MOODLE_USERNAME | moodleuser | |
| MOODLE_PASSWORD | PLEASE_CHANGEME | |
| SMTP_HOST | smtp.gmail.com | |
| SMTP_PORT | 587 | |
| SMTP_USER | your_email@gmail.com | |
| SMTP_PASSWORD | your_password | |
| SMTP_PROTOCOL | tls | |
| MOODLE_MAIL_NOREPLY_ADDRESS | noreply@localhost | |
| MOODLE_MAIL_PREFIX | [moodle] | |
| AUTO_UPDATE_MOODLE | true | Set to false to disable performing update of Moodle (e.g. plugins) at docker start |
| DEBUG | false | |
| client_max_body_size | 50M | |
| post_max_size | 50M | |
| upload_max_filesize | 50M | |
| max_input_vars | 5000 | |
| PRE_CONFIGURE_COMMANDS | | Commands to run before starting the configuration |
| POST_CONFIGURE_COMMANDS | | Commands to run after finished the configuration |
| RUN_CRON_TASKS | true | Set to false to disable the moodle cron job from running automatically |
## Reverse Proxy Configuration
When using a reverse proxy (e.g., Caddy, Traefik, nginx-proxy-manager) that handles SSL termination, you might encounter issues like missing CSS or a "too many redirects" error. This is a common problem and can be solved with the correct configuration.
### The Problem
1. **Missing CSS:** If you set `SITE_URL` to your internal Docker IP (e.g., `http://172.19.0.1:89`), Moodle will generate URLs with this internal address. When your browser, accessing the site via `https://moodle.example.com`, tries to load these assets, it will block them due to mixed content (trying to load `http` content on an `https` page).
2. **`ERR_TOO_MANY_REDIRECTS`:** If you set `SITE_URL` to your public HTTPS address (e.g., `https://moodle.example.com`) but don't configure the proxy settings correctly, Moodle might get confused about the protocol and enter a redirect loop.
### The Solution
The key is to tell Moodle that it's behind an SSL-terminating proxy. You can do this with the following environment variable settings:
- `SITE_URL`: Set this to your **public, external URL** with the `https` scheme (e.g., `https://moodle.example.com`).
- `REVERSEPROXY`: Set this to `false` for most reverse proxy setups. Set to `true` only if your Moodle site is intentionally accessible from multiple different base URLs (for example, if users access the site using different domain names or protocols). In a typical reverse proxy scenario where all users access Moodle through a single public URL, this should remain `false`. See [Moodle's documentation on reverse proxies](https://docs.moodle.org/en/Server_cluster) for more details.
- `SSLPROXY`: Set this to `true`. This tells Moodle to trust the `X-Forwarded-Proto` header from your proxy and understand that the connection is secure, even though the internal connection to the Docker container is over HTTP.
### Example Configuration
Here's an example of a `docker-compose.yml` file and a `Caddyfile` for a reverse proxy setup.
**`docker-compose.yml`**
```yaml
services:
moodle:
image: erseco/alpine-moodle
restart: unless-stopped
environment:
SITE_URL: https://moodle.example.com
REVERSEPROXY: "false"
SSLPROXY: "true"
# ... other environment variables
# No ports need to be exposed externally, as Caddy will connect
# to the container directly via the Docker network.
volumes:
- moodledata:/var/www/moodledata
- moodlehtml:/var/www/html
depends_on:
- postgres
# ... other services (postgres, etc.)
volumes:
moodledata:
moodlehtml:
```
**`Caddyfile`**
```caddy
moodle.example.com {
reverse_proxy moodle:8080 {
header_up Host {host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-For {remote}
}
}
```
By using this configuration, you can avoid the common pitfalls of running Moodle behind a reverse proxy. For more details, see issue [#101](https://github.com/erseco/alpine-moodle/issues/101).
## Minimal docker-compose.yml example
```yaml
---
services:
postgres:
image: postgres:alpine
restart: unless-stopped
environment:
- POSTGRES_PASSWORD=moodle
- POSTGRES_USER=moodle
- POSTGRES_DB=moodle
volumes:
- postgres:/var/lib/postgresql/data
moodle:
image: erseco/alpine-moodle
restart: unless-stopped
environment:
MOODLE_USERNAME: moodleuser
MOODLE_PASSWORD: PLEASE_CHANGEME
ports:
- 80:8080
volumes:
- moodledata:/var/www/moodledata
- moodlehtml:/var/www/html
depends_on:
- postgres
volumes:
postgres: null
moodledata: null
moodlehtml: null
```
## Advanced Features
### 1. Using Moosh CLI
This image includes [Moosh](https://github.com/tmuras/moosh) — a powerful CLI tool to manage Moodle installations. You can invoke any Moosh command using:
```bash
docker compose exec moodle moosh
```
Examples:
#### Upgrade plugin list (required to install)
```bash
docker compose exec moodle moosh plugin-list
```
#### Install a Plugin by Name
```bash
docker compose exec moodle moosh plugin-install mod_attendance
```
> You can force the installation of unsupported plugins with the `--force` option.
> NOTE:[There is a bug in moosh and the first installation is not working](https://github.com/tmuras/moosh/issues/520), so we recommend calling again the install function with the `--delete` flag option or use the `module-reinstall` option: eg: `docker compose exec moodle moosh plugin-install --delete theme_almondb` or call `docker compose exec moodle moosh module-reinstall theme_almondb`
#### Backup a Course
Backup course with provided id. By default, logs and grade histories are excluded.
Example: Backup course id=3 into default .mbz file in `/opt/moosh/` directory from container:
```bash
docker compose exec moodle moosh course-backup 3
```
#### Create a User
Create a new Moodle user. Provide one or more arguments to create one or more users.
Example: create user "testuser" with the all the optional values
```bash
docker compose exec moodle moosh user-create --password pass --email me@example.com --digest 2 --city Valverde --country ES --institution "IES Garoé" --department "Technology" --firstname "first name" --lastname name testuser
```
#### Delete a User
Delete user(s) from Moodle. Provide one or more usernames as arguments.
Example: delete user testuser
```bash
docker compose exec moodle moosh user-delete testuser
```
These examples can be included directly in `POST_CONFIGURE_COMMANDS` to automate plugin installation, backups, or any Moosh-supported functionality.
Using Moosh promotes the DRY (Don't Repeat Yourself) principle and leverages a powerful toolset for Moodle administration.
For the full list of commands, visit: https://moosh-online.com/commands/
### 2. Pre/Post Configuration Hooks
You can define commands to be executed before and after the configuration of Moodle using the `PRE_CONFIGURE_COMMANDS` and `POST_CONFIGURE_COMMANDS` environment variables. These can be useful for tasks such as installing additional packages or running scripts.
```yaml
environment:
PRE_CONFIGURE_COMMANDS: "cat config-dist.php"
POST_CONFIGURE_COMMANDS: |
moosh plugin-list
moosh plugin-install --delete theme_almondb
moosh plugin-install --delete theme_almondb
```
### 3. Specifying a Moodle Version
Calling `docker compose build` uses the latest version of Moodle from the main branch. If you need to use a specific Moodle version, you can specify it using the `MOODLE_VERSION` build argument.
To use a specific version, edit the build section for the moodle service in your docker compose.yml file:
```yaml
moodle:
image: erseco/alpine-moodle
build:
context: .
args:
MOODLE_VERSION: v4.5.3 # Replace with your desired version
```
You can find the list of available version tags at: https://github.com/moodle/moodle/tags
### 4. Enabling Test Scenario Generator
Moodle includes a tool to create [test scenarios](https://moodledev.io/general/development/tools/generator#create-a-testing-scenario-using-behat-generators) under `Admin > Development > Create testing scenarios`. To enable it, run the following command, or add it in `POST_CONFIGURE_COMMANDS`:
```bash
php admin/tool/generator/cli/runtestscenario.php
```
This tool allows generating all necessary elements for manual testing using `.feature` file syntax.
## Maintenance Tips
**Install Additional Alpine Packages (as root):**
```bash
docker compose exec --user root moodle sh -c "apk update && apk add nano"
```
**Manual Database Upgrade:**
```bash
docker compose exec moodle php admin/cli/upgrade.php
```
**Access Logs:**
```bash
docker compose logs -f moodle
```