OpenRestyでLuaを使った動的リバースプロキシを構築1

Docker

前回、最後にちらっと予告していた「OpenResty」Dockerでたてて、Luaスクリプトを使って動的リバースプロキシを構築したいと思います。

まずはDockerfileを作成していきます。ベースとなるイメージは公式で出している「buster-fat」のフレーバーを使います。

FROM openresty/openresty:buster-fat

次に「LuaRocks」というLua用のパッケージマネージャを入れます。公式の説明では alpine-fatcentos, bionic のフレーバーには内包されているということですが、buster-fat には入っていないので独自に入れます。公式にサンプルがあるので、それを流用しちゃいます。

ARG RESTY_LUAROCKS_VERSION="3.7.0"

# install LuaRocks
RUN DEBIAN_FRONTEND=noninteractive apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
        curl \
        make \
        unzip \
        git \
        logrotate \
    && cd /tmp \
    && curl -fSL https://luarocks.github.io/luarocks/releases/luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz -o luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz \
    && tar xzf luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz \
    && cd luarocks-${RESTY_LUAROCKS_VERSION} \
    && ./configure \
        --prefix=/usr/local/openresty/luajit \
        --with-lua=/usr/local/openresty/luajit \
        --lua-suffix=jit-2.1.0-beta3 \
        --with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1 \
    && make build \
    && make install \
    && cd /tmp \
    && rm -rf luarocks-${RESTY_LUAROCKS_VERSION} luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz

# Add LuaRocks paths
# If OpenResty changes, these may need updating:
#    /usr/local/openresty/bin/resty -e 'print(package.path)'
#    /usr/local/openresty/bin/resty -e 'print(package.cpath)'
ENV LUA_PATH="/usr/local/openresty/site/lualib/?.ljbc;/usr/local/openresty/site/lualib/?/init.ljbc;/usr/local/openresty/lualib/?.ljbc;/usr/local/openresty/lualib/?/init.ljbc;/usr/local/openresty/site/lualib/?.lua;/usr/local/openresty/site/lualib/?/init.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/lualib/?/init.lua;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua"

ENV LUA_CPATH="/usr/local/openresty/site/lualib/?.so;/usr/local/openresty/lualib/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so"
# install a rock
RUN /usr/local/openresty/luajit/bin/luarocks install ljsyscall \
    && /usr/local/openresty/luajit/bin/luarocks install lua-resty-ipmatcher

一部追加しているものを説明します。

    && /usr/local/openresty/luajit/bin/luarocks install lua-resty-ipmatcher

まずはこの部分ですが、独自に実装したLuaスクリプトでIPアドレスをCIDRで判定したいので、lua-resty-ipmatcherというモジュールを追加します。

このモジュールですがIPアドレスを下記のようにCIDR形式で判定することができるようになります。

local ipmatcher = require("resty.ipmatcher")
local ip = ipmatcher.new({
    "127.0.0.1",
    "192.168.0.0/16",
    "::1",
    "fe80::/32",
})

ngx.say(ip:match("127.0.0.1"))
ngx.say(ip:match("192.168.1.100"))
ngx.say(ip:match("::1"))

上記のモジュールをインストールするには「git」が必要になるので「apt-get」 しているところに追加します。あとNGINXのログをホストにバインドしてローテしたいので「logrotate」もついでにいれます。logrotateはインストールしただけだと実行されないので以下の設定ファイルを /etc/logrotate.d に格納してサービスを有効にします。

/usr/local/openresty/nginx/logs/*.log {
    daily
    rotate 10
    missingok
    notifempty
    sharedscripts
    compress
    delaycompress
    postrotate
        /usr/local/openresty/nginx/sbin/nginx -s reopen >/dev/null 2>&1 || true
    endscript
}

サービス有効化はENTRYPOINTにシェルスクリプトをかまして service cron start を実行します。

#!/bin/sh

echo "Starting cron service"
service cron start

echo "Starting openresty"
/usr/bin/openresty -g 'daemon off;'

exec "$@"

Luaスクリプトはコンパイルしてバイトコード化することができるのでその処理を追加します。スクリプトの置き場とバイナリの出力先は呼び出しやすいようにLUA_PATHで定義してるところにしましょう。

# Compile script
RUN cd /usr/local/openresty/nginx/lua/ \
    && ls *.lua | sed -e s/\.lua// | xargs -I{} luajit -b {}.lua {}.luac

あとはいつもの如く、実行ユーザーとドキュメントルートの作成、各種ファイルのコピー、ヘルスチェック等を追加します。最終的に以下のDockerfileになります。

FROM openresty/openresty:buster-fat

ARG RESTY_LUAROCKS_VERSION="3.7.0"
ARG PUID=300
ARG PGID=300

# install LuaRocks & Others
RUN DEBIAN_FRONTEND=noninteractive apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
        curl \
        make \
        unzip \
        git \
        logrotate \
    && cd /tmp \
    && curl -fSL https://luarocks.github.io/luarocks/releases/luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz -o luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz \
    && tar xzf luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz \
    && cd luarocks-${RESTY_LUAROCKS_VERSION} \
    && ./configure \
        --prefix=/usr/local/openresty/luajit \
        --with-lua=/usr/local/openresty/luajit \
        --lua-suffix=jit-2.1.0-beta3 \
        --with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1 \
    && make build \
    && make install \
    && cd /tmp \
    && rm -rf luarocks-${RESTY_LUAROCKS_VERSION} luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz

# Add LuaRocks paths
# If OpenResty changes, these may need updating:
#    /usr/local/openresty/bin/resty -e 'print(package.path)'
#    /usr/local/openresty/bin/resty -e 'print(package.cpath)'
ENV LUA_PATH="/usr/local/openresty/site/lualib/?.ljbc;/usr/local/openresty/site/lualib/?/init.ljbc;/usr/local/openresty/lualib/?.ljbc;/usr/local/openresty/lualib/?/init.ljbc;/usr/local/openresty/site/lualib/?.lua;/usr/local/openresty/site/lualib/?/init.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/lualib/?/init.lua;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua"

ENV LUA_CPATH="/usr/local/openresty/site/lualib/?.so;/usr/local/openresty/lualib/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so"

# install a rock
RUN /usr/local/openresty/luajit/bin/luarocks install ljsyscall \
    && /usr/local/openresty/luajit/bin/luarocks install lua-resty-ipmatcher

# create webservd user
RUN groupadd -g ${PGID} webservd \
    && useradd -u ${PUID} -g webservd -d /home/webservd -m webservd \
    && mkdir -p /home/webservd/WebContent/ROOT

# Copy nginx configuration files
COPY ./conf/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
COPY ./conf/ssl.conf /etc/nginx/ssl.conf
COPY ./conf/dhparam /etc/nginx/dhparam
COPY ./conf/conf.d/*.conf /etc/nginx/conf.d/
COPY ./conf/logrotate.d/* /etc/logrotate.d/
COPY ./lua /usr/local/openresty/nginx/lua
COPY entrypoint.sh /

# Compile script
RUN cd /usr/local/openresty/nginx/lua/ \
    && ls *.lua | sed -e s/\.lua// | xargs -I{} luajit -b {}.lua {}.luac

# Healthcheck to make sure container is ready
HEALTHCHECK CMD curl --fail http://localhost:80 || exit 1

ENTRYPOINT ["sh", "/entrypoint.sh"]

EXPOSE 80 443

# Declare volumes for mount point directories
VOLUME ["/usr/local/openresty/nginx/logs", "/etc/ssl", "/home/webservd/WebContent/ROOT"]

ひとまず、Dockerfileはこれで完成したのであとは肝心のLuaスクリプトとNGINXの設定ですが長くなったので次回に回します。

コメント

タイトルとURLをコピーしました