コンテンツにスキップ

はじめに

このページでは、ngx_mrubyを組み込んだnginxをDockerで動かし、Rubyのスクリプトが答えるリクエストを送ってから、そのスクリプトを書き換えます。例は、リポジトリのフォルダexamples/startにあります。Composeは、compose.yamlに従い、Dockerfileを使って、チェックアウトしたソースからngx_mrubyを組み込んだnginxをビルドします。次に、フォルダのnginx.confとhello.rbでそのnginxを起動します。

  • Dockerと、docker composeのコマンドを使うためのComposeのプラグイン、git、curl、ネットワークへの接続が要ります。ビルドは、nginxをnginx.orgから、build_config.rbのmrbgemsをGitHubからダウンロードします。
  • このv3開発版の検証済みビルド済みイメージは提供していないため、最初の実行では、mrubyとnginxをコンパイルします。2026年10月29日に、GitHubのubuntu-24.04のランナーで、Docker Engine 28.0.4とDocker Compose 2.38.2を使ったとき、手順3は170秒かかりました。2回目からは、ビルド済みのイメージを使い回します。
  • これらの手順は、examples/を変えるすべてのプルリクエストでCIが実行します。そのワークフローの.github/workflows/examples.ymlは、このページの出力をすべて、コマンドが表示したものと比べます。

Rubyのハンドラを持つnginxを動かす

Section titled “Rubyのハンドラを持つnginxを動かす”

このサイトで扱うのは、ブランチnextで開発中のngx_mruby 3.xです。

  1. リポジトリから、ブランチnextをクローンします。

    $ git clone --branch next https://github.com/matsumotory/ngx_mruby.git
  2. 例のフォルダへ移動します。

    $ cd ngx_mruby/examples/start
  3. イメージをビルドし、nginxを起動します。--waitを付けると、nginxがcompose.yamlのヘルスチェックに答えたときにコマンドが戻り、Composeはコンテナstart-nginx-1をhealthyとして表示します。

    $ docker compose up --build --wait
  4. 引数nameを付けて、/helloへリクエストを送ります。レスポンスはRubyのスクリプトが書きます。

    $ curl -s 'http://localhost:8080/hello?name=Ruby'
    Hello, Ruby! hello.rb answered GET /hello.

nginxは、nginx.confのmruby_content_handlerに従って、/helloへのリクエストをRubyのスクリプトに渡します。

nginx.conf
# The nginx configuration of the start page. compose.yaml mounts this
# folder at /example, and the image starts nginx with this file.
user nobody nogroup;
worker_processes 1;
error_log /dev/stderr;
events {
worker_connections 64;
}
http {
access_log /dev/stdout;
server {
listen 8080;
location /hello {
mruby_content_handler /example/hello.rb;
}
}
}

hello.rbは、Nginx::Requestで引数を読み、Nginx.rputsでボディを書き出します。

hello.rb
# The content handler of the start page (examples/start/nginx.conf).
r = Nginx::Request.new
name = r.var.arg_name.to_s
name = "world" if name.empty?
r.content_type = "text/plain"
Nginx.rputs "Hello, #{name}! hello.rb answered #{r.method} #{r.uri}.\n"

nginxは、ワーカープロセスの中でngx_mrubyがnginxに組み込んだmrubyのVMを使ってスクリプトを実行します。ほかのプロセスは関わりません。スクリプトが使えるクラスとメソッドは、Rubyのリファレンスにあります。

Composeは、compose.yamlに従ってこのフォルダをコンテナにマウントします。ディレクティブは、パラメータcacheを付けずにスクリプトを指定しています。そのため、nginxはリクエストのたびにファイルを読み直します。hello.rbを変えると、リロードしなくても次のリクエストから変更が効きます。

  1. hello.rbのHelloをGood morningに置き換えます。このコマンドは、元のファイルをhello.rb.origとして残します。

    $ sed -i.orig 's/Hello/Good morning/' hello.rb
  2. もう一度リクエストを送ります。レスポンスには新しいあいさつが入っています。

    $ curl -s 'http://localhost:8080/hello?name=Ruby'
    Good morning, Ruby! hello.rb answered GET /hello.
  3. 元のスクリプトを戻します。

    $ mv hello.rb.orig hello.rb
  4. マウントした設定を検証してリロードします。PATHに依存せず、このイメージのバイナリと設定のパスを指定します。

$ docker compose exec -T nginx /usr/local/nginx/sbin/nginx -t -c /example/nginx.conf
$ docker compose exec -T nginx /usr/local/nginx/sbin/nginx -s reload -c /example/nginx.conf
$ curl -s 'http://localhost:8080/hello?name=Ruby'
Hello, Ruby! hello.rb answered GET /hello.
  1. コンテナを止めて削除します。Composeは、コンテナstart-nginx-1をremovedと表示します。

    $ docker compose down

リクエストのたびにファイルを読むと、スクリプトを書いている間は便利です。その代わり、nginxはリクエストの処理の途中でディスクを読みます。本番では、コンパイルしたコードのキャッシュにあるように、ディレクティブにcacheを付けてください。cacheを付けると、nginxは設定を読むときにスクリプトを1回だけコンパイルします。

変更 反映方法 理由
cacheなしのRuby 再送 マウントしたスクリプトを毎回読みます
nginx.conf、またはcache付きRuby nginx -tで検証してから上記コマンドでreload 設定読込時にコードをコンパイルします
gem・ビルド設定 再ビルド ビルド条件が変わる

コンテナ内のマウントは読み取り専用です。ホスト側のファイルを編集します。この例はホストのインターフェースに8080番を公開するため、ローカルだけで試す場合は起動前にComposeの対応を127.0.0.1:8080:8080へ変更してください。

healthcheckや設定エラーはdocker compose logs nginxで調べます。イメージmetadataの取得失敗は、コンパイル前のレジストリ・ネットワークの問題です。

コンテナは試用の入口の一つです。既存のLinux環境へ組み込む場合はインストールに従い、nginxの版とビルド条件を合わせます。公式nginxパッケージやイメージにはngx_mrubyは含まれず、--with-compatも任意のnginx版との互換性を意味しません。Mac上でLinuxコンテナを動かした結果は、macOSネイティブビルドの証明ではありません。

上記170秒は過去のCI環境での記録であり、現在の所要時間やarm64での結果を保証しません。2026-10-30のfresh linux/arm64試行はUbuntu基盤イメージのmetadata取得で止まり、コンパイル前に終了しました。その試行では起動・編集反映・reloadは未検証です。examplesワークフローがLinuxランナーでコマンドを検査するため、使用するcommitの実行結果を確認してください。

一次資料: NGINXコンテナ、Linuxパッケージ、動的モジュール、reload、bind mount。

  • インストール:ngx_mrubyを、静的なモジュールか動的なモジュールとして、自分のnginxに組み込んでビルドします。

  • ディレクティブ:nginxがRubyを実行するフェーズと、各フェーズのディレクティブを載せています。

  • リクエストのフェーズ:nginxが1つのリクエストのハンドラを実行する順序を説明しています。

  • エージェントプロキシ: 検証済みのモデル振り分けとストリーム中継へ進みます。