月額ほぼ0円で社内eラーニング環境を作った話【GCP×Cloudflare×Moodle】

catch-img

新卒研修、ちゃんとやろうとすると講師が足りない問題

弊社では新卒採用に力を入れています。ただ、入社後のオンボーディングをどうするかがずっと課題でした。

当社のような人ベースのモデルの会社だと、OJTで育てていくのは一つの王道とは思いますが、これだとその人に割り当てられた仕事についてはスキルが身についていくけど、割り当たっていない仕事は全然身につくことがなく歪な成長になってしまうことが悩みです。「俺ビジネス分かってる」と宣っておきながら名刺交換できないみたいなバケモノが生まれてしまいます。

なので体系的な基礎研修を組んで、全員が「ここまで来て欲しい」のレベルに引き上げることが大事だと考えています。特に当社はマーケティングテクノロジー領域とデータ領域で事業が分かれていますが、マーケ側なのでデータわからなくていいとかないですし、逆もまた然りです。マーケのためのデータ基盤という際に当社が一番力を発揮するところでもあるので、どちらも一定水準を超えてほしいです。

じゃあどうするかで悩んでいたのが「講師問題」です。

3ヶ月間、毎日何を学ぶかを1時間単位でプランニングしました。が、そのプランを実行するには誰かが教えなければならない。講師が1日中、3ヶ月間張り付く。現実問題として無理です。メンター制度はあるのですがメンターが全部それを教えるなんてとてもじゃないけど無理ですし、じゃあ社長やれよというのもキツイ(一回全部自分でやるつもりで組んでたけど、あれ?無理じゃね?となり・・)

eラーニング入れたら講師の拘束時間が1日2時間になりそうだった

で、考えたのがeラーニングの仕組みを使うことです。

毎日の研修を「冒頭の頭出し(講師)→ eラーニング(動画・ワーク・テスト)→ 演習・アウトプット」の流れにすれば、講師が関わるのは1日2時間くらいで回せそうだと気づきました。

あとせっかくなので、ゲームのトロフィーみたいな仕組みも入れたいなと思いました。学ぶたびにトロフィーがもらえて、自分の成長の軌跡が見える。モチベーション維持にもよさそうです。

実際にAIで作ってみたトロフィー例が以下(グラセフみたいな感じ、治安悪めでって頼んでます)

研修で得られるトロフィー

ただ、こういうシステムってお金かかるんだろうな〜と思っていました。

Moodleという選択肢を知る

ChatGPTにトロフィーシステム付きのeラーニングシステムを聞いてみたところ、Moodleが出てきました。調べてみると、オープンソースで無料、コース管理・クイズ・バッジ(トロフィー)機能が標準搭載。要件を全部満たしていました。最高です。

さくらに入れようとしたら詰んだ

さっそく当社が契約しているさくらインターネットのサーバーに入れようとしました。ChatGPTに手順書を作ってもらって進めたのですが、そもそもさくらの契約プランだとMoodleの要求スペック(MySQL 8.4+)を満たしていないことが途中で発覚w

しかし当社はGoogle CloudパートナーであるのでGCPにて自前構築することに方針転換。ただChatGPTの手順書は手順が飛んでいたり、「どこで何を設定するのか」が分かりづらかったりで困っていました。Claudeに改めて聞いたら良い感じだったのでそちらに切り替えました。

それでも、UIが変わっていて存在しないメニューを指されたり、コマンドを叩いたら環境の問題でエラーが出たり、サーバーのメモリ不足だったりと、ちょいちょいうまくいかないことは出てきます。そこで一問一答スタイルに切り替えました。「手順を1ステップもらう → 実行 → スクショを送る → OKなら次、NGならその場でトラブルシュート」という流れでやったら、かなりサクサク進みました。これ自体は別記事で書こうと思います。

順調になってからゼロ〜完成までは4時間かからないくらい。事前調査や試行錯誤も含めたトータルだと12時間くらいかかりましたが、普段Compute EngineもCloudflareも触っていない自分でも完成できました。

この記事で共有すること

その時の構築手順を以下にまとめておきます。

なお「月額ほぼ0円」と書いていますが、弊社の場合はGCPの無料枠がすでに使い切られていたため、少しだけコストが発生しています。とはいえ1日0.2ドルくらいなので大した金額ではないです。GCPを初めて使う方は無料枠内で収まるはずです。

システム構成図

システム構成図

手順


完成した構成

ユーザー(ブラウザ)
    ↓ HTTPS
Cloudflare Access(Googleログイン認証)
    ↓
Cloudflare Tunnel(outbound接続)
    ↓
GCP VM(e2-micro、外部IP無し)
    ├── Docker: Moodle 4.5(Apache)
    └── Docker: MariaDB 10.11

コンポーネント

月額コスト

GCP e2-micro(us-central1)

$0(無料枠)

外部IPv4

$0(付与しない)

Cloud NAT(送信200GBまで)

$0

Cloudflare Tunnel

$0

Cloudflare Access(50席まで)

$0

合計

ほぼ$0

ドメイン代のみ別途かかる。


事前に用意するもの

  • GCPアカウント(課金有効化済み)
  • Cloudflareアカウント(無料でOK)
  • 管理するドメイン(CloudflareのDNSに委譲できるもの)
  • @会社ドメインのGoogleアカウント(社内限定アクセスに使用)

手順1:GCP VMを作成する

1-1. 予算アラートを先に設定する(必須)

作業を始める前に必ずやること。予期しない課金を防ぐため、月額アラートを設定しておく。

GCP Console → お支払い(Billing) → 予算とアラート → CREATE BUDGET

  • 名前:任意(例:moodle-monthly)
  • 金額:3000(円換算で約$20)
  • アラート:50% / 90% / 100% の3段階で通知

1-2. Compute Engine APIを有効化する

GCP Console → APIとサービス → ライブラリ で「Compute Engine API」を検索して有効化。

1-3. VMインスタンスを作成する

GCP Console → Compute Engine → VMインスタンス → CREATE INSTANCE

設定項目

値

リージョン

us-central1(無料枠対象)

マシンタイプ

e2-micro

OS

Ubuntu 22.04 LTS

ディスクタイプ

Standard persistent disk、30GB

外部IPv4

None(重要:これを忘れると月額課金が発生)

HTTP/HTTPSトラフィック

両方OFF(Tunnel経由のため不要)

「外部IPv4:None」が最重要ポイント。Cloudflare TunnelのoutboundだけでアクセスできるのでパブリックIPは不要で、付与すると時間課金が発生する。


手順2:Cloud NATを設定する(外部IPなしの場合は必須)

外部IPv4なしのVMは、そのままではapt-get updateすら動かない。Cloud NATを設定してアウトバウンド通信を可能にする。

GCP Console → 検索バーで「Cloud NAT」と検索 → Cloud NAT ゲートウェイを構成 → 開始

設定項目

値

ネットワーク

default

リージョン

us-central1(VMと同じ)

クラウドルーター

新規作成(名前:moodle-router)

NATのIPアドレス

自動(推奨)

ネットワークサービスティア

スタンダード(200GB/月無料)

設定後、VMのSSHターミナルでsudo apt-get updateが通ることを確認。


手順3:DockerとDocker Composeをインストールする

GCP Console → Compute Engine → VMインスタンス → exture-moodle の「SSH」ボタン

ブラウザSSHが開いたら:

sudo apt-get update
sudo apt-get install -y docker.io docker-compose
sudo usermod -aG docker $USER
newgrp docker

確認:

docker --version        # Docker version 28.x.x
docker-compose --version # docker-compose version 1.29.x
docker ps               # エラーなしで空の一覧が表示されればOK

手順4:Moodleコードをダウンロードする

mkdir -p ~/moodle/{mariadb_data,moodle_data,moodle_html}
cd ~/moodle
 
# Moodle 4.5をダウンロード
curl -L https://download.moodle.org/download.php/direct/stable405/moodle-latest-405.tgz -o moodle.tgz
tar -xzf moodle.tgz --strip-components=1 -C moodle_html
rm moodle.tgz
chmod -R 755 moodle_html
chmod -R 777 moodle_data

手順5:スワップ領域を追加する(必須)

e2-microはメモリ1GBしかない。Moodleのインストール処理でメモリを使い切ってVMが固まるため、スワップを追加する。

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
 
# 確認
free -h  # Swap: 2.0G と表示されればOK

手順6:docker-compose.ymlを作成して起動する

cd ~/moodle

以下の内容でdocker-compose.ymlを作成する。パスワード3箇所は必ず変更すること。

services:
  mariadb:
    image: mariadb:10.11
    command: >
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_unicode_ci
      --innodb-file-per-table=1
      --innodb-large-prefix=1
    environment:
      - MARIADB_ROOT_PASSWORD=【強いパスワードに変更】
      - MARIADB_DATABASE=moodle
      - MARIADB_USER=moodle
      - MARIADB_PASSWORD=【強いパスワードに変更】
    volumes:
      - ./mariadb_data:/var/lib/mysql
    restart: unless-stopped
 
  moodle:
    image: moodlehq/moodle-php-apache:8.3
    ports:
      - "127.0.0.1:8080:80"
    depends_on:
      - mariadb
    restart: unless-stopped
    volumes:
      - ./moodle_html:/var/www/html
      - ./moodle_data:/var/www/moodledata

起動:

docker-compose up -d
sleep 30
docker-compose ps  # moodle_moodle_1 と moodle_mariadb_1 が Up であればOK
curl -I http://127.0.0.1:8080  # HTTP/1.1 302 Found が返ればOK

手順7:Cloudflareにドメインを追加する

Cloudflare Dashboard(dash.cloudflare.com) → Add a site → ドメインを入力 → Free Plan

ネームサーバーが表示されるので控えておく(例:nina.ns.cloudflare.com)。

ドメイン管理会社(お名前.com等)のコントロールパネルでネームサーバーをCloudflareのものに変更する。Cloudflare Dashboard上でStatusが「Active」になるまで待つ(数分〜数時間)。


手順8:Cloudflare Tunnelを設定する

Cloudflare Dashboard → Networking → Tunnels → Create a tunnel

  1. Cloudflared を選択 → トンネル名を入力(例:moodle-tunnel)→ Save tunnel
  2. OS Debian(64-bit) を選択
  3. 表示されたインストールコマンド(curl -L ... && sudo cloudflared service install eyJ...)をVMのSSHで実行
  4. サービス起動確認:sudo systemctl status cloudflared(active (running) であればOK)

ルートの追加:

Tunnel詳細 → Routes タブ → Add route → Published application

設定

値

Subdomain

空白(ルートドメインの場合)

Domain

your-domain.com

Service Type

HTTP

URL

localhost:8080


手順9:Moodleのブラウザインストールを実行する

https://your-domain.com にアクセスするとMoodleのインストール画面が表示される。

SSL/TLSエラーが出た場合:
Cloudflare Dashboard → your-domain.com → SSL/TLS → Overview → 暗号化モードを Flexible に変更

インストール画面の設定:

設定項目

値

言語

日本語

データディレクトリ

/var/www/moodledata

DBタイプ

MariaDB

DBホスト

mariadb

DB名

moodle

DBユーザー

moodle

DBパスワード

docker-compose.ymlで設定したパスワード

途中でconfig.phpを手動作成するよう求められる場合は、表示されたコードをVMで以下のように保存する:

cat > ~/moodle/moodle_html/config.php << 'EOF'
<?php  // Moodle configuration file
unset($CFG);
global $CFG;
$CFG = new stdClass();
 
$CFG->dbtype    = 'mariadb';
$CFG->dblibrary = 'native';
$CFG->dbhost    = 'mariadb';
$CFG->dbname    = 'moodle';
$CFG->dbuser    = 'moodle';
$CFG->dbpass    = '【DBパスワード】';
$CFG->prefix    = 'mdl_';
$CFG->dboptions = array(
  'dbpersist' => 0,
  'dbport' => '',
  'dbsocket' => '',
  'dbcollation' => 'utf8mb4_unicode_ci',
);
 
$CFG->wwwroot   = 'https://your-domain.com';
$CFG->dataroot  = '/var/www/moodledata';
$CFG->admin     = 'admin';
$CFG->directorypermissions = 0777;
$CFG->reverseproxy = false;
$CFG->sslproxy = true;
require_once(__DIR__ . '/lib/setup.php');
EOF

ポイント: sslproxy = true、reverseproxy = false の組み合わせがCloudflare Tunnel環境では正解。これを間違えるとERR_TOO_MANY_REDIRECTSが発生する。

インストール完了後、管理者アカウントとサイト名を設定すれば完了。


手順10:Cloudflare Accessでアクセス制限をかける

このままでは誰でもアクセスできるので、社内メールドメインのみに制限する。

Cloudflare Zero Trust(one.dash.cloudflare.com)にアクセス

初回はチーム名の設定とFree Planの登録(クレジットカード登録が必要だが課金なし)が必要。

設定完了後:

Access controls → Applications → Add an application → Self-hosted

設定

値

Application name

任意(例:Company LMS)

Application domain

your-domain.com

Policies で:

設定

値

Policy name

任意

Action

Allow

Include

Emails ending in → your-company.jp

これでyour-company.jpドメインのGoogleアカウントでしかアクセスできなくなる。


手順11:cronを設定する(バッジ・通知に必須)

sudo apt-get install -y cron
 
(crontab -l 2>/dev/null; echo "* * * * * docker exec \$(docker ps -qf 'name=moodle_moodle') php /var/www/html/admin/cli/cron.php >/dev/null 2>&1") | crontab -
 
# 確認
crontab -l

はまりやすいポイントまとめ

構築中に実際に遭遇したトラブルと対処法をまとめておく。

①apt-get updateが全部エラーになる
→ Cloud NATを設定していないのが原因。外部IPv4なしのVMはCloud NATなしでは外部通信できない。

②bitnami/moodleイメージが見つからない
→ BitnamiはDocker Hubからイメージを撤退済み。moodlehq/moodle-php-apache+Moodleコード直接ダウンロードの方式を使う。

③Moodleインストール中にVMがフリーズする
→ e2-microのメモリ1GBでは足りない。スワップ2GBの追加が必須。

④ERR_TOO_MANY_REDIRECTSが発生する
→ config.phpに$CFG->sslproxy = true;と$CFG->reverseproxy = false;を追加。require_onceの前に記述すること。

⑤MariaDBのROW_FORMAT=Compressedエラー
→ docker-compose.ymlのMariaDBのcommandに--innodb-file-per-table=1 --innodb-large-prefix=1を追加。


Moodleでできること(社内研修活用例)

構築後にすぐ使える主な機能:

機能

活用例

コース管理

研修をWeek単位でモジュール化

クイズ

理解度テスト。合格点設定・自動採点

課題提出

レポート提出→管理者がMoodle上で採点

バッジ(トロフィー)

コース完了・クイズ合格で自動付与

進捗トラッキング

受講者の進捗を管理者が一覧で確認

掲示板

研修中の質問・議論スペース


まとめ

GCP e2-micro + Cloudflare TunnelでほぼMoodle環境が無料で作れる。さくら等のレンタルサーバーでMySQLのバージョンが古くて困っている場合も、この構成で解決できる。

Cloud NATの設定とスワップの追加を忘れなければ、あとは比較的スムーズに構築できるはず。


構成:GCP Compute Engine e2-micro / Ubuntu 22.04 / Docker / Moodle 4.5 / MariaDB 10.11 / Cloudflare Tunnel / Cloudflare Access

原田 憲悟
原田 憲悟
エクスチュア株式会社 代表取締役。 2001年よりデータ分析に従事し、2005年からデジタルマーケティング領域に特化。Adobe Analytics歴20年超、GA4・Snowflake・Tableau・CDPの設計・実装に精通し、延べ200社以上のエンタープライズ企業のMarTech・データ基盤構築を支援。本ブログではこれらの実務経験に基づいた技術解説と知見を発信しています。

人気記事ランキング

タグ一覧