set up moodle 4 in docker on a home server

Moodle is a web-based platform where you can create learning activities, manage course assessment and pretty much run a school or sell courses. If your needs are small enough, you can use WordPress plugins to do this, but Moodle provides the versatility and most of the tools for the job. Moodle is open-source and free unlike fully commercial learning management systems (LMS) like Canvas, Brightspace, Blackboard. But free doesn’t mean effortless.

You may be gifted if setting up moodle, an open source learning platform, on a server did not require forum searching to get it started. Going further, setting up a moodle container in Docker requires both giftedness and luck – and yet (to me) the Docker approach offers an easy way to process the frequent moodle app updates. If you’re a Docker ‘fan’ you already know its advantages but perhaps because it’s less popular there’s also less support out there. Let me document what I did to get you more started – with super thanks to Dave at dbtech (video below) who provided the head start needed.

Compared with every other Docker app, the instructions at moodleapp and bitnami aren’t typical or helpful. Indeed the policy at Moodle central prefers not to hand-hold by providing instructions in the interface. That’s cluttering they think. Better they say to put everything in the main docs – and indeed they do – without overseeing how unhelpful, and turgid the moodle docs have become.

Roger Frost

what you need to get you head round already

  • Get a Docker ‘engine’ installed. I use my homeserver which is a PC past its prime running openmediavault – OMV makes using debian linux more visual without the lagginess of a desktop operating system. Nevertheless Docker runs on many platforms. The Moodle Docker container will be stored in the Docker location by default.
  • Portainer is an app, a Docker container often installed immediately after the Docker engine. It will often spare you having to use a command line interface. You can immediately see what containers are running or delete things to start over without affecting your saved work.
  • Docker apps are installed from the cmd line or a script stored as a docker-compose,yml file or as a Stack using Portainer.
  • You need to know that Moodle keeps the settings for the Moodle LMS in a database which is controlled by a separate app. The database app I’ve used is the popular ‘mariadb’. The database ‘data’ must only be accessible in a secure way and the parameters (like a password) are set by the environmental variables in the script below.
  • You need to have a ‘shared folder’ on a volume or a hard disk where you will store the moodle database; the moodledata folder containing course uploads and the moodle app configuration. This shared folder stores all the effort you’ll put into setting up the Moodle. The location will probably referred to by ‘srv/dev-disk-by-xyx-long-code’. The system will create folders in the shared folder called moodledb; moodle and moodledata. In my setup the shared folder was called dckcnfg or dockconfig.
  • You need a free port to access the moodle in a browser – by default moodle uses port 80 but as this is already in use, I used port 8089 – a number I choose at random.
  • You may need to tell Docker the GUID and PUID of the user just in case there are permission issues. Find these by entering at the CLI this: id admin
  • The mariadb and moodle containers need access to the network. The compose file below sets up a network to join these containers to the local network. Read on to see what to do with it.

the docker-compose.yml

// docker-compose.yml - a 'script' that sets up mariadb and moodle
version: '2'
    image: mariadb
    container_name: mariadb
      - 3306:3306
      - /srv/dev-disk-by-x/dckcnfg/moodledb:/var/lib/mysql
      - MYSQL_ROOT_PASSWORD=moodle1
      - MYSQL_ROOT_USER=root
      - MYSQL_DATABASE=moodle
      - PUID=998
      - PGID=100
    image: bitnami/moodle:latest
    container_name: moodle
      - 8089:8080
      - 8449:8443
      - MOODLE_DATABASE_HOST=mariadb
      - PUID=998
      - PGID=100
      - /srv/dev-disk-by-x/dckcnfg/moodle:/bitnami/moodle
      - /srv/dev-disk-by-x/dckcnfg/moodledata:/bitnami/moodledata
      - mariadb
      - mariadb:mariadb

how to initiate the docker install

At the command line of a SSH terminal into your server enter

  • sudo docker-compose config / to check for errors
  • sudo docker-compose up -d / to install

you might see errors in the Portainer logs for mariadb and moodle

  • In Portainer go to the container to see the log. The container may start and then stop – here a problem connecting to the database might be fixed (as in the docker-compose above by adding this environment variable to the mariadb and moodle compose sections: ALLOW_EMPTY_PASSWORD=yes )
  • If the database stops with the error: “grep: /opt/bitnami/moodle/config.php: No such file or directory” you might delete the moodledata folder and start over if it’s a fresh install. It means there’s a permission issue getting access to this folder.
  • After starting the container you may need to wait for the Moodle install script to finish. You access the moodle via serverIP:8089 or localhost:8089 or
  • The default login to the Moodle is ‘user’ with password ‘bitnami’

the video which got me started

Thank you dave of dbtech. I have liked, subscribed and liked your channel forever.

Moodle starts a bit broken

Both of my Moodle 4 installs started in a running but broken state. An install on my decent spec ‘old PC home server’ was lacking its H5P plugin activities which I traced back to the Scheduled Task or cron job which had never run. The other Moodle was on the IONOS hosted system (which also runs this site): the new moodle failed to display with formatting – evidently a css problem. Do first check that your config.php file in the Moodle folder has the correct settings to access moodledata. My settings were OK and my fix required a ridiculous search and replace on the entire Moodle code – see below. In addition a Moodle Scheduled Task or cron job had never run – and this was fixed on both my Moodle installs as described next:

Moodle needs its cron job kick started

The Moodle docs say that your site will not work properly unless cron is running regularly*. This sort of troubling thing is more troubling in Docker, however here is my approach:

In Moodle Site Administration search for, or go to Server > Scheduled tasks. Look down the list to see if any enabled tasks have been run according to the schedule. You might investigate so: set one task to run in the night and then check back in the morning.

If your Scheduled and enabled tasks show as ‘never’ run, go to Site Administration and search for Site Security settings > Cron execution via command line only. Uncheck the Cron execution via command line only. Save the setting – at the bottom on the page. Now add ‘admin/cron.php’ on the end of your moodle site address and port eg or This should get the cron kick started and show you the script working. Go back to Site Security settings and check the box to revert the insecure setting:

uncheck the ‘Cron execution via command line only’ temporarily

If you’re using Moodle in Docker use (eg Portainer) to go to the Moodle container bin/bash console. Enter:

/etc/init.d/cron restart

Be wary: if you rebuild this container you might have to do this again – but I don’t know yet. According to one post I read that: “you can now go to to check if cron is running”.

*They do not say how to see if this step is required – but “it is very important you do not skip this step”

what about nginx proxy manager? do I need that?

Not yet, but when you’re ready to open your home server Moodle to the world you’ll want to route the incoming traffic via a reverse proxy. You’d do this in preference to opening that port to Moodle on your router. See the DBTECH video for details on setting up nginx proxy. That’s good though here’s what I do because I’m lazy and can use Home Assistant’s nginx proxy manager container.

Fix for non-Docker (i.e. IONOS hosting) Moodle install only

SCORM content, slash arguments PATH_INFO and 1and1 IONOS hosting
open the Moodle folder with a program like Visual Studio Code 
replace $_SERVER['PATH_INFO'] with $_SERVER['ORIG_PATH_INFO'] in all the files. 
(There are 7 or 8 files) 


I’m dreading having to do this again with the next Moodle update. Here’s the link to the forum post for this

Leave a Reply

Your email address will not be published. Required fields are marked *