ngx_small_lightを使って画像をリサイズする

nozomi yonezawa
nextbeat-engineering
10 min readNov 15, 2021

こんにちは、ネクストビートのエンジニアの米澤です。
宿泊業界特化の人材紹介サービス「おもてなしHR」の開発に携わっています。

この記事では、Docker環境でnginxをソースファイルからビルドする方法と、ngx_small_lightの設定方法をご紹介したいと思います。
ポイント毎にコードを抜粋して説明し、コードの全体像は記事の最後に掲載する流れでご紹介します。

~ 目次 ~
1. ngx_small_lightでできること
2. Dockerで環境構築
・依存パッケージのインストール
・ビルド定義、コンパイル、インストール
・foregroundでnginxを起動する
3. 画像リサイズ設定(nginx.conf)
4. コードの全体像
・Dockerfile
・nginx.conf
・sample.html
5. 感想
6. 参考サイト

1. ngx_small_lightでできること

ngx_small_lightは、URLで設定を指定することで画像を変換して返却してくれるnginxのモジュールです。例えば、次のことができます。

  • 画像の横幅や縦幅、画像形式を変える
  • blurやsharpenをかける
  • キャンバスエリアを追加する
  • ロゴなどの別画像を指定した位置にマージする

2. Dockerで環境構築

依存パッケージのインストール

FROM alpine:3.1RUN apk --update add \
wget \
tar \
git \
make \
gcc \
build-base \
perl-dev \
g++ \
zlib-dev \
imagemagick-dev \
pcre-dev

今回は、ベースとなるDocker Imageに、Alpine Linuxを使いました。
apkコマンドで必要なパッケージをインストールしています。

Alpine LinuxはミニマムなOSのため、他のOSをベースにする場合よりも必要なパッケージが多いかもしれません。エラーを確認しつつ、パッケージを入れていきました。
正規表現ライブラリであるPCREと、画像リサイズライブラリのImageMagickは、ngx_small_lightが依存しているため必須です。

また、サフィックスに-devがついているパッケージがいくつかありますが、これらはサフィックスなしのパッケージだとDocker Imageビルドがnginxコンパイル時点で失敗しました。
以下は、その際のエラーメッセージです。

#10 3.011 adding module in ../ngx_small_light
#10 3.011 checking for ngx_small_light dependencies … not found
#10 3.048 The compilation test below failed:
#10 3.048
#10 3.048 #include <wand/MagickWand.h>
#10 3.048
#10 3.048 MagickWandGenesis();
#10 3.048

-devのあるなしで」何が違うの…?と思い調べてみると、

開発に必要なライブラリオブジェクトやヘッダファイル(lib***.soや***.h)が含まれています。
そのライブラリを使ってプログラムをコンパイルするときに必要になります。
引用元:https://okwave.jp/qa/q1764993.html

という回答を見つけました。
上記のエラーの場合、ヘッダファイルがないためincludeできずエラーになったのですね。

nginxをインストール

RUN wget https://nginx.org/download/nginx-1.20.1.tar.gz \
&& tar -xzf nginx-1.20.1.tar.gz \
&& rm -r nginx-1.20.1.tar.gz

nginxのインストール方法は大きく分けて2通りあり、利用したいモジュールのビルド方法よってどちらにするかが決まります。

  1. nginx公式やディストリビューションが提供しているパッケージでインストールする方法
  2. ソースファイルをダウンロードする方法

例えば、今回利用するngx_small_lightは、静的ビルドで組み込むモジュールです。1の「パッケージインストール」では静的ビルドができないため、2の方法をとることになります。

nginxのバージョンには、Mainline(最新版)とStable(安定版)があります。Mainlineは新しいモジュールが実験的に組み込まれているもので、StableはMainlineで発覚した致命的なバグが解消された状態のバージョンです。

今回は、最新のStableバージョンである1.20.1を使用しています。
ダウンロードページはこちらです。

ビルド定義、コンパイル、インストール

RUN cd nginx-1.20.1 \
&& ./configure \
-- with-debug \ # デバッグログを有効にする
-- prefix=/usr/local/nginx \ # configureオプションのパスのプレフィックス
-- conf-path=/conf/nginx.conf \ # nginx.confファイルのパス
-- sbin-path=/sbin/nginx \ # 実行ファイルのパス
-- add-module=../ngx_small_light \ # 追加するモジュールのパス
&& make \
&& make install

ここでは、nginxのビルド定義、コンパイル、インストールをしています。

先ほどダウンロードしたnginx-1.20.1.tar.gzの内容はこのようになっていて、

/work # ls nginx-1.20.1/
CHANGES CHANGES.ru LICENSE Makefile README auto conf configure contrib html man objs src

この中のconfigureファイルの実行でビルド定義、makeコマンドによるMakefileファイル実行でコンパイルとビルドを行うことができます。

また、./configureにオプションをつけて実行することで、ビルド定義のカスタマイズができます。

その他のオプションは以下のページから参照できます。

foregroundでnginxを起動する

CMD ["/sbin/nginx", "-g", "daemon off;"]

nginxは、デーモンでの起動がデフォルトです。
Dockerはforegroundでコンテナを動かさないとコンテナが永続化されないので、指定はマストです。

3. 画像リサイズ設定(nginx.conf)

server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index sample.html;
}
small_light on;
location ~ ^/small_light[^/]*/(.+)$ {
set $file $1;
proxy_pass http://s3.ap-northeast-1.amazonaws.com;
rewrite ^ /S3バケット名/$file;
break;
}
}

S3にある画像をリサイズする想定で、nginx.confファイルにnginxとngx_small_lightの設定をしています。

ngx_small_lightは、

  • small_light on;でngx_small_lightを有効にする
  • /small_light(リサイズ設定)というフォーマットのURIを受け取る

ことで、small_light関数の引数で指定された設定を適用します。
指定できる設定はこちらのページを参照ください。

今回は、画像をS3に置いているので、S3へリダイレクトするためにlocationコンテキスト内でrewriteproxy_passでホストとパスを書き換えています。

4. ファイルの全体像

ディレクトリ構成は以下の通りです。

.
├── Dockerfile
├── README.md
├── html
│ └── sample.html
└── nginx.conf

Dockerfile

nginx.conf

sample.html

「1. ngx_small_lightでできること」にあるGIFのUI作成に利用したhtmlです。リサイズ設定を気軽に試したかったので、JavaScriptでフォームから設定内容を書き換えられるようにしています。

感想

普段の業務ではあまり触れる機会のないnginxですが、コードを読む機会があったので「せっかくだし何か作ろう」と思い、勉強してみました。
使うモジュールによってインストール方法が違ったり、Dockerコンテナが永続化してくれなかったり…とハマりながらも作りきれてよかったです。

nginxでは他にもロードバランシングやコンテンツキャッシュなどできるので、ネットワーク周りの勉強のために設定方法を調べてみたいと思います。

最後まで読んでいただきありがとうございました!

We are Hiring!

株式会社ネクストビートでは

「人口減少社会において必要とされるインターネット事業を創造し、ニッポンを元気にする。」
を理念に掲げ一緒に働く仲間を募集しております。

バックエンドにはPlay Framework(言語はScala)、フロントエンドの開発には主にAngularを用いています。フルスタックに開発したい!という方のご応募をお待ちしております。

--

--