Steps to deploy Moodle LMS via docker-compose and Kubernetes. Uses branch 404_STABLE Uses Docker base image moodlehq/moodle-docker.
-
Update the
.envfile appropriately. Please note that we are using v3 compose files which do not use.envfiles by default. Instead,docker-compose.ymlsources the.envfile into the microservices manually. -
Deploy. This builds the image locally.
docker-compose up -dRequisites (run only once)
- Source envfile
source ./k8s/overlays/prod/.env- Create dedicated namespace for Moodle
and a Kubernetes app instance for customer eg.
fhcgr. These are interpolated by envsubst in the Kustomize templates.
export \
NAMESPACE=tess \
INSTANCE=fhcgr \
TAG=latest
kubectl create namespace $NAMESPACEMoodle install script requires ready database instance on your kubernetes cluster.
in the database namespace.
Supported database engines in externalDatabase.type are: mysqli, mariadb, pgsql, auroramysql
Hints below for MariaDB and PostgreSQL.
- Copy existing MariaDB secrets from the "database" namespace to this project,
kubectl -n database get secrets/mariadb -o yaml | \
yq 'del(.metadata.creationTimestamp, .metadata.uid, .metadata.resourceVersion, .metadata.namespace)' | \
kubectl apply -n $NAMESPACE -f -Nota: We will use above created secrets/mysql in place of mariadb.mariadbRootPassword.
This will be referenced use by the externalDatabase.existingSecret config below.
Subsequently, in chart config, reference existing mysql database resp. to its namespace ie. mysql.database.
- Create the database
# Forward pgpool service to localhost:5432
kubectl -n database port-forward svc/mariadb 3306:3306
# Connect to MariaDB as user "root"
DB_PASSWORD=$(kubectl -n database get secrets/mariadb -o jsonpath="{.data.mariadb-root-password}" | base64 -d)
mysql -u root -p$DB_PASSWORD -h localhost
# Then, in MySQL shell, run:
# create database fhcgr_moodle;- Obtain
DB_HOST,DB_PORT,DB_USER,DB_PASSWORDfor your existing db instance.
Note that we do NOT use the DB_PASSWORD env. In this particular setting, the db root password is pulled manually a Secret resource existing in our production cluster and
injected into the $NAMESPACE namespace using a ConfigMap.
Eg., following example extracts existing PostgreSQL db secret from our database namespace, and injects it into the moodle namespace.
Nota: our root db_username defaults to postgres.
kubectl -n database get secrets/pgpool -o yaml | \
yq 'del(.metadata.creationTimestamp, .metadata.uid, .metadata.resourceVersion, .metadata.namespace)' | \
kubectl apply -n $NAMESPACE -f -- Create database in PostgreSQL
kubectl -n database port-forward svc/pg-pgpool 5432
# Connect to PostgreSQL as user "root"
DB_PASSWORD=kubectl -n database get secrets/mariadb -o jsonpath="{.data.mariadb-root-password}" | base64 -d
psql postgresql://$DB_USER:$DB_PASSWORD@localhost:5432 "create database "$DB_NAME" encoding utf8;"Build and push the image to my private DockerHub
docker build ./docker -t ceduth/moodle:$TAG \
&& docker push ceduth/moodle:$TAGFollow up with additional steps for GKE if applies.
This setup uses Kustomize layere-based configuration management.
By default deploys and exposes Moodle behind a Nginx ingress controller pre-installed on GKE. Check for instructions to setup a Nginx Ingress Controller with CertManager that provisions TLS certificates for an entire cluster.
-
Set your
.envfile appropriately in directorydocker-moodle/k8s/. Note, we have setSSL_PROXY=truein the env file since we seat behind Nginx Ingress proxy. -
Create Moodle user and email
kubectl -n $NAMESPACE create secret/fhcgr-moodle \
--from-literal=moodle-password='Th3P@ssw0rd!' \
--from-literal=moodle-email='francois.carvalho.alvarenga@gmail.com' - From
moodle-k8sdirectory, run: Nota: This creates an internal service resource, reachable only within the cluster.
# kubectl apply -n $NAMESPACE -k ./k8s/overlays/prod
~/DevOps/bin/kustomize build ./k8s/overlays/prod | envsubst | kubectl -n $NAMESPACE apply -f -- Create an ExternalName resource in the default namespace, that point to the internal moodle service in namespace designated namespace.
cat <<EOF | envsubst | kubectl apply -n $NAMESPACE -f -
kind: Service
apiVersion: v1
metadata:
name: fhcgr-moodle
spec:
type: ExternalName
externalName: moodle.$NAMESPACE
EOF- Finally merge following rule that routes https traffic into existing Nginx Ingress configuration:
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: web-ingress
annotations:
kubernetes.io/ingress-class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
...
# <THE-UPDATE>
spec:
tls:
...
rules:
- host: "fc.echq.online"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: moodle
port:
number: 80
# </THE-UPDATE>
- Point your browser at:
https://<MOODLE_URL>Note:MOODLE_URLwas previously set in our env file.
- Fix moodle version in database (did'nt work for me!)
# Get version from the git repo at
# Or copy version from running pod via ssh at /var/www/html/version.php
# Or fetch it from https://moodledev.io/general/releases
# Cf. https://stackoverflow.com/a/32208453/4615806
# eg. 2022041912.00 for MOODLE_404_STABLE
# --
# Worth reading, but did'nt work for me!
# https://docs.moodle.org/404/en/Installation_FAQ#"Could_not_find_a_top_level_course"
INSERT INTO mdl_config (name, value) VALUES ('version', '2022041912');- Run the installer manually
Follow the wizard.
Choose /var/moodledata when asked for Moodle data dir (cf. Dockerfile)
su www-data -c 'php admin/cli/install.php --agree-license' -s /bin/bash
su www-data -c 'php admin/cli/install_database.php --agree-license --adminpass=Th3P@ssw0rd!' -s /bin/bash- Check php info
# Create info.php in public dir, then
# Open https://fc.echq.online/info.php in brnowser
cat << EOF > /var/www/html/info.php
<?php
phpinfo();
?>
EOFkubectl -n tess delete deployment/fhcgr-moodle
kubectl -n tess delete pvc/fhcgr-moodle-pvc