jimsihk/alpine-moodle

By jimsihk

Updated 5 days ago

Moodle docker image based on Alpine Linux, NGINX, PHP-FPM and official Moodle

Image
1

100K+

jimsihk/alpine-moodle repository overview

High Availability Moodle on Alpine Linux

Docker Pulls Docker Image Size nginx 1.28 php 8.4 moodle-5.0 License MIT

Moodle setup with high availability (HA) capabilities for Docker, build on Alpine Linux.

Repository: https://github.com/jimsihk/alpine-moodle

  • Based on official Moodle source https://github.com/moodle/moodle
  • Built on the lightweight image https://github.com/jimsihk/alpine-php-nginx
  • Smaller container image size (+/-150MB for full version, +/-90MB for slim version)
  • Supports HA installation with multiple type of cache stores (memcached, Redis) and PostgresSQL poolers like PgBouncer
  • Supports also Redis Sentinel as cache stores via plugin https://github.com/catalyst/moodle-cachestore_redissentinel
  • Pre-install Moodle plug-ins at build time with argument ARG_MOODLE_PLUGIN_LIST
  • Always up-to-date Moodle version and Alpine packages with Renovate (see below)
  • Supports read-only replica of database
  • Multi-arch support: 386, amd64, 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)
  • JIT enabled by default
  • Use of runit instead of supervisord to reduce memory footprint
  • Configured cron to run as non-privileged user https://github.com/gliderlabs/docker-alpine/issues/381#issuecomment-621946699
  • Configuration via ENV variables
  • Auto update Moodle plugin and upgrade to newer Moodle versions (via ARG_MOODLE_GIT_URL and ARG_MOODLE_GIT_BRANCH at build time, MOODLE_GIT_URL and MOODLE_GIT_BRANCH at run time) when container start
  • The servers NGINX, PHP-FPM run under a non-privileged user (nobody) to make it more secure
  • The logs of all the services are redirected to the output of the Docker container (visible with docker logs -f <container name>)
  • Follows the KISS principle (Keep It Simple, Stupid) to make it easy to understand and adjust the image to your needs

Automated Release

Renovate

Moodle version and package dependencies are monitored and automatically updated through pull requests by Renovate: https://github.com/renovatebot/renovate

When Renovate updates the jimsihk/alpine-php-nginx base image in Dockerfile, GitHub Actions also refreshes the Alpine package pins in that same PR if the image moves to a new Alpine major/minor series.

Nightly Build

A nightly build in GitHub Action scans for changes, then performs tagging and publishes a newer release on container registries.

The release tag will be in pattern: XXX.YYY.ZZ

  • XXX = Moodle Branch
  • YYY = Moodle Release Increments & Incremental Changes Number based on version.php of Moodle source
  • ZZ = Git Repo Releases

e.g. for Moodle 4.1.1+ branch 401 version 2022112801.06, the release tag number will be starting from 401.106.0

Multiple Container Registry

The images are available on multiple registries:

Image Variants

alpine-moodle:XXX.YYY.ZZZ
  • Standard version with full features
alpine-moodle:XXX.YYY.ZZZ-slim
  • Even smaller container image size
  • Git is not installed
  • Removed in-place code upgrade functionality (i.e. ignored UPDATE_MOODLE_CODE)
  • Controlled by build argument ARG_ENABLE_GIT_CLONE when build

Usage

Start the Docker containers:

docker compose up

Start a Moodle cluster:

./generate_ssl_cert.sh
docker compose --file docker-compose.replica.yml up

Login on the system using the provided credentials (ENV vars)

Sample docker-compose files
  • docker-compose.yml - with PostgreSQL
  • docker-compose.replica.yml - with PostgreSQL, Redis and multiple Moodle containers, using NGINX as load balancer with SSL termination
    • execute generate_ssl_cert.sh to generate a sample SSL certificate for localhost
    • refer to https://docs.moodle.org/en/Caching for setting up after login or set the SESSION_CACHE_* environment variables
    • please note this setup is NOT configured for production use, use it for demonstration only

Configuration

Define the ENV variables in docker-compose.yml file

Variable NameDefaultDescription
LANGen_US.UTF-8
LANGUAGEen_US:en
SITE_URLhttp://localhostSets the public site URL
SSLPROXYfalseDisable SSL proxy to avoid site loop. e.g. Cloudflare
DB_TYPEpgsqlmysqli - pgsql - mariadb
DB_HOSTpostgresDatabase hostname e.g. database container name
DB_PORT5432PostgresSQL=5432 - MySQL/MariaDB=3306
DB_NAMEmoodleDatabase name
DB_USERmoodleDatabase login username
DB_PASSmoodleDatabase login password
DB_FETCHBUFFERSIZESet to 0 if using PostgresSQL poolers like PgBouncer in 'transaction' mode
DB_DBHANDLEOPTIONSfalseSet to true if using PostgresSQL poolers like PgBouncer which does not support sending options
DB_DBPERSISTfalseSet to true to keep database connected with Moodle PHP thread while active, may have performance gain but may also used up database connections
DB_HOST_REPLICADatabase hostname of the read-only replica database
DB_PORT_REPLICADatabase port of replica, left it empty to be same as DB_PORT
DB_USER_REPLICADatabase login username of replica, left it empty to be same as DB_USER
DB_PASS_REPLICADatabase login password of replica, left it empty to be same as DB_PASS
DB_PREFIXmdl_Database prefix. WARNING: don't use numeric values or Moodle won't start
MOODLE_EMAIL[email protected]
MOODLE_LANGUAGEen
MOODLE_SITENAMENew-Site
MOODLE_SHORTNAMEmoodle
MOODLE_USERNAMEmoodleuser
MOODLE_PASSWORDPLEASE_CHANGEME
SMTP_HOSTsmtp.gmail.com
SMTP_PORT587
SMTP_USER[email protected]
SMTP_PASSWORDyour_password
SMTP_PROTOCOLtls
MOODLE_MAIL_NOREPLY_ADDRESSnoreply@localhost
MOODLE_MAIL_PREFIX[moodle]
memory_limit128MMaximum amount of memory that a PHP script is allowed to allocate (default value inherited from base image)
client_max_body_size50MSets the maximum allowed size of the client request body, specified in the “Content-Length” request header field
post_max_size50MMax size of post data allowed. This setting also affects file upload. To upload large files, this value must be larger than upload_max_filesize
upload_max_filesize50MMaximum size of an uploaded file.
max_input_vars5000Maximum number of input variables allowed per request, set to at least 5000
opcache_jit_buffer_size64MAmount of shared memory to reserve for compiled JIT code, set to 0 to disable the JIT
opcache_jit1235Configure the JIT mode (default value inherited from base image)
opcache_memory_consumption128Size of the shared memory storage used by OPcache in megabytes (default value inherited from base image)
SESSION_CACHE_TYPEOptionally sets shared session cache store: memcached, redis, database (leave it blank to keep unchanged)
SESSION_CACHE_HOSTHostname of the external cache store, required for memcached and redis
SESSION_CACHE_PORTMemcached=11211, Redis=6379, required for memcached and redis
SESSION_CACHE_PREFIXmdlCache prefix
SESSION_CACHE_AUTHAuthentication key for cache store, may be required for redis
AUTO_UPDATE_MOODLEtrueSet to false to disable performing update of Moodle (e.g. plugins) at docker start
UPDATE_MOODLE_CODEtrueSet to false to disable auto download latest patch of Moodle core code, only effective if AUTO_UPDATE_MOODLE is true or built with ARG_ENABLE_GIT_CLONE as true
DISABLE_WEB_INSTALL_PLUGINfalseSet to true to disable plugin installation via site admin UI, could be useful to avoid image outsync with HA setting
MAINT_STATUS_KEYWORDStatus: enabledKeyword for detecting Moodle maintenance status when running admin/cli/maintenance.php, language following the Moodle site default language
LOCAL_CACHE_DIRECTORYSet the path to a local fast filesystem for Moodle local caching that no need to be shared with other instances
SKIP_MOODLE_CONFIGfalseSet to true to skip the Moodle configuration script

More settings on PHP and NGINX can refer to the base image https://github.com/jimsihk/alpine-php-nginx/blob/dev/README.md

Important Note about using AUTO_UPDATE_MOODLE and UPDATE_MOODLE_CODE

If set to true, Moodle will be set to CLI maintenance mode at container start while performing the update. No user will be able to use Moodle, not even admin.

If a cluster of Moodle containers are deployed for HA (e.g. on Kubernetes), it is suggested to set both to false to avoid unexpected interruption to users when auto scaling, such as adding extra containers to the cluster or container restart for auto healing.

Custom builds

Moodle plugins
ARG_MOODLE_PLUGIN_LIST: define the list of plugins
  • For installing plugins while building the main Dockerfile (slower), use ARG_MOODLE_PLUGIN_LIST:
docker buildx build . -t my_moodle_image:my_tag \
    --build-arg ARG_MOODLE_PLUGIN_LIST='mod_attendance mod_checklist mod_customcert block_checklist gradeexport_checklist'
  • For building only to install additional moodle plugins (faster), create a Dockerfile like the following and then build.
  • Example of Dockerfile.plugins:
# Dockerfile.plugins
FROM quay.io/jimsihk/alpine-moodle:latest

# Install additional plugins, a space/comma separated arg, (optional)
# Run install-plugin-list with argument "-f" to force install 
#   if the plugin is not compatible with current Moodle version
ARG ARG_MOODLE_PLUGIN_LIST=''
ENV MOODLE_PLUGIN_LIST=${ARG_MOODLE_PLUGIN_LIST}
RUN if [ -n "${MOODLE_PLUGIN_LIST}" ]; then /usr/libexec/moodle/install-plugin-list -p "${MOODLE_PLUGIN_LIST}"; fi && \
    rm -rf /tmp/moodle-plugins
  • Since v4.2.1.02-2 (402.102.2), this could be further simplified into:
# Dockerfile.plugins
FROM quay.io/jimsihk/alpine-moodle:latest

# Install additional plugins, a space/comma separated arg, (optional)
ARG ARG_MOODLE_PLUGIN_LIST=''
ENV MOODLE_PLUGIN_LIST=${ARG_MOODLE_PLUGIN_LIST}
RUN /usr/libexec/moodle/download-moodle-plugin
  • Example of build using Dockerfile.plugins:
# Build
docker buildx build . -t my_moodle_image:my_tag \
    -f Dockerfile.plugins \
    --build-arg ARG_MOODLE_PLUGIN_LIST='mod_attendance,mod_checklist,mod_customcert,block_checklist,gradeexport_checklist'
ARG_ALLOW_INCOMPATIBLE_PLUGIN: allow installing incompatible plugins
  • Since v4.2.1.02-2 (402.102.2), ARG_ALLOW_INCOMPATIBLE_PLUGIN is also available to easily control if continue the installation of latest available version despite lack of compatibility from maturity, default as false:
docker buildx build . -t my_moodle_image:my_tag \
    --build-arg ARG_MOODLE_PLUGIN_LIST='mod_attendance mod_checklist mod_customcert block_checklist gradeexport_checklist' \
    --build-arg ARG_ALLOW_INCOMPATIBLE_PLUGIN='true'
  • Or using a custom Dockerfile.plugins:
# Dockerfile.plugins
FROM quay.io/jimsihk/alpine-moodle:latest

ARG ARG_MOODLE_PLUGIN_LIST='mod_attendance mod_checklist mod_customcert block_checklist gradeexport_checklist'
ARG ARG_ALLOW_INCOMPATIBLE_PLUGIN='true'
ENV MOODLE_PLUGIN_LIST=${ARG_MOODLE_PLUGIN_LIST}
ENV ALLOW_INCOMPATIBLE_PLUGIN=${ARG_ALLOW_INCOMPATIBLE_PLUGIN}
RUN /usr/libexec/moodle/download-moodle-plugin

Known Issues

Unable to Create/Update Moodle Roles with "Incorrect role short name" (https://github.com/erseco/alpine-moodle/issues/26)
  • Workaround: install Moosh and use the role-update-capability command, but beware that only version 0.39 of the plugin has this command
  • FIXED since release v4.1.2.07-1 (401.207.1)

Credits

Tag summary

Content type

Image

Digest

sha256:70a41466e

Size

100.3 MB

Last updated

5 days ago

docker pull jimsihk/alpine-moodle:latest-slim