はじめに
matsumoto-r/ngx_mrubyをCentOSで試そうと思い、ビルドするためのDockerfileを書いてみました。
hnakamur/docker-ngx_mruby-centosに置いてあります。MITライセンスです。
ngx_mrubyのビルド設定
ngx_mrubyではデフォルトで以下のモジュールをビルドするようになっています。
#
# Recommended for ngx_mruby
#
# comment out because of moving error.h
conf.gem :git => 'git://github.com/iij/mruby-io.git'
conf.gem :git => 'git://github.com/iij/mruby-process.git'
conf.gem :git => 'git://github.com/iij/mruby-pack.git'
conf.gem :git => 'git://github.com/iij/mruby-digest.git'
conf.gem :git => 'git://github.com/mattn/mruby-json.git'
conf.gem :git => 'git://github.com/matsumoto-r/mruby-redis.git'
conf.gem :git => 'git://github.com/matsumoto-r/mruby-vedis.git'
conf.gem :git => 'git://github.com/matsumoto-r/mruby-memcached.git'
conf.gem :git => 'git://github.com/matsumoto-r/mruby-sleep.git'
conf.gem :git => 'git://github.com/matsumoto-r/mruby-userdata.git'
conf.gem :git => 'git://github.com/mattn/mruby-onig-regexp.git'
# ngx_mruby extended class
conf.gem :git => 'git://github.com/matsumoto-r/mruby-ngx-mruby-ext.git'
私の書いたDockerfileではbuild_config.rbを以下のように変更しています。
sed -i.orig "s|conf.gem :git => 'git://github.com/matsumoto-r/mruby-memcached.git'|#&|;/^ conf.gem :git => 'git:\/\/github.com\/mattn\/mruby-onig-regexp.git'/a\
\ conf.gem :git => 'git://github.com/iij/mruby-env.git'" \
build_config.rb && \
- mruby-memcachedはビルド対象から外す
- matsumoto-r/mruby-memcachedはlibmemcachedのソースをビルドして参照するようにしてみたんですが、mruby-memcachedがコンパイルエラーになってしまいました。とりあえず私は使う予定がなかったので外すことにしました。
- mruby-envを追加
- mrubyのスクリプト内で環境変数を参照したかったのでiij/mruby-envを追加しました。
nginxのビルド
matsumoto-r/ngx_mrubyのBuildのドキュメントには3通りの方法が書かれています。nginxにモジュールを追加したい場合もあるので、3番めの方法にしたかったのですが、mrubyがビルドされずエラーになってしまったので、1番めの方法でmrubyをビルドしておいてから、3番めの方法でビルドするようにしてみたら、うまく行きました。
nginxのconfigureは以下のようにしています。適宜変更してご利用ください。
./configure --prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-file-aio \
--with-ipv6 \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_xslt_module \
--with-http_image_filter_module \
--with-http_geoip_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_degradation_module \
--with-http_stub_status_module \
--with-md5-asm \
--with-sha1-asm \
--with-pcre-jit --with-pcre=/usr/local/src/pcre-8.35 \
--with-cc-opt='-O2 -g' \
--add-module=/usr/local/src/ngx_mruby \
--add-module=/usr/local/src/ngx_mruby/dependence/ngx_devel_kit && \
mrubyとnginxが依存しているもののビルドまたはインストール
- ruby
- mrubyのビルドに必要。2.1.1をソースからビルド
-
Redis
- redis/hiredisのビルドに必要
- ソースからビルド
-
redis/hiredis
- matsumoto-r/mruby-redisが依存
- ソースからビルド
-
PCRE - Perl Compatible Regular Expressions
- JITを使いたい(nginxのconfigureの--with-pcre-jitオプション)ので最新版8.35をソースからビルド
-
GeoIP
- これは依存しているというわけではなく、nginxにGeoIPモジュールを組み込んで(nginxのconfigureの--with-http_geoip_moduleオプション)ビルドしたかったので利用。
- epelからインストール
- ソースからビルドする場合はHow to install Nginx GeoIP moduleが参考になりそうです(試してないです)。
Dockerイメージのビルド
Dockerfileのあるディレクトリで以下のコマンドを実行します。
docker build -t hnakamur/ngx_mruby .
コンテナの起動
redisはdockerでlua-resty-redisのコンテナからredisのコンテナに通信するサンプル - Qiitaの記事で作ったコンテナを利用します。以下のコマンドでredisのコンテナを起動します。
docker run -d -p 6379:6379 -name redis hnakamur/redis
以下のコマンドでngx_mrubyのコンテナを起動します。
docker run -d -p 80:80 -link redis:redis hnakamur/ngx_mruby
ngx_mrubyからredisにアクセスするサンプル
まずDockerによって環境変数を参照するためにnginx.confに以下の設定を入れています。
env REDIS_PORT_6379_TCP_ADDR;
env REDIS_PORT_6379_TCP_PORT;
/redisのlocation設定は以下のようにしています。
location /redis {
mruby_content_handler /usr/local/nginx/conf/get_redis.rb;
}
host = ENV["REDIS_PORT_6379_TCP_ADDR"]
port = ENV["REDIS_PORT_6379_TCP_PORT"].to_i
db = Redis.new host, port
# Note: a value must be String
# > db.set "key1", 100
# (mirb):1: expected String (TypeError)
db.set "key1", "100"
value = db.get "key1"
r = Nginx::Request.new
r.content_type = "text/html"
Nginx.rputs "host = #{host}, port = #{port}, value is #{value}\n"
私の環境ではdockerでlua-resty-redisのコンテナからredisのコンテナに通信するサンプル - Qiitaに書いたように8080→80のポートフォワーディングを設定していますので、OSXで
curl http://localhost:8080/redis
でアクセスすると
host = 172.17.0.2, port = 6379, value is 100
といった出力が得られます。