読者です 読者をやめる 読者になる 読者になる

Mercari Engineering Blog

We're the software engineers behind Mercari. Check out our blog to see the tech that powers our marketplace.

nginx-build〜nginxのビルドプロセスを自動化〜

インフラチームの@cubicdaiyaです。今回はnginxのビルドプロセスを自動化するツールであるnginx-buildについて紹介します。

メルカリとnginx

メルカリでは多数のnginxを活用し、高速なレスポンスやサービスの安定稼働を実現するのに重要な役割を果たしています。実際の活用事例には、

  • リバースプロキシ、L7ロードバランサ
  • TLSターミネーション、SPDYゲートウェイ
  • 静的コンテンツの配信、キャッシュ
  • ngx_dynamic_upstreamを用いたゼロダウンタイムデプロイメント
  • ngx_lua(OpenResty)を用いたサービスコンポーネントの開発

などが挙げられます。そしてメルカリではこれら多数の用途のnginxをnginx-buildでソースコードからビルドしています。(OpenResty以外は合わせてrpm化も行っています)

既存のビルド済みパッケージの利用とソースコードからのビルド

nginxはyumやaptといった各Linuxディストリビューションのパッケージ管理ツールでビルド済みのパッケージをインストールすることができますし、公式サイトでもビルド済みパッケージを配布しています。インストールも簡単なので特にこだわりや理由がなければ広く配布されているビルド済みパッケージを利用するだけで問題ないでしょう。

一方で既存のビルド済みパッケージを利用する場合以下のデメリットが挙げられます。

  1. ビルド時のconfigureオプションが選べない(既に決まっている)
  2. サードパーティのモジュールが組み込めない

「1. ビルド時のconfigureオプションが選べない」が問題になることは少ないかもしれませんが、「2. サードパーティのモジュールが組み込めない」は大きなマイナスポイントです。というのもnginxのモジュールはすべてビルド時に組み込む必要があるためです。(この状況は今後変わるかもしれません。詳しくはこちら)

nginxをソースコードからビルドする

次にnginxをソースコードからビルドする手順を書いてみます。

wget http://nginx.org/download/nginx-1.9.4.tar.gz
tar zxf nginx-1.9.4.tar.gz
cd nginx-1.9.4
./configure
make
make install

非常に簡単です。しかしnginxを本格的にプロダクションで利用する場合は考えなければならないことが数多くあります。パッと思いつくものを挙げてみます。

  • 大量にあるビルドオプションの指定
  • PCRE、zlib、OpenSSLなどの依存ライブラリの組み込み・バージョン管理
  • サードパーティモジュールの組み込み・バージョン管理
  • 上記手順の自動化・構成管理・メンテナンス

これらの手間を大幅に省くために開発したのが次に紹介するnginx-buildです。

nginx-build〜seamless nginx builder〜

github.com

nginx-buildはnginxのビルドプロセスを自動化するためのツールです。Goで書かれています。

こちらからビルド済みの実行バイナリをダウンロードすることができます。MacユーザならHomebrewでインストールすることも可能です。

brew tap cubicdaiya/nginx-build
brew install nginx-build

また、Goがインストールされていればgo getでインストールすることができます。

go get -u github.com/cubicdaiya/nginx-build  

nginx-buildでnginxをビルドする

それではnginx-buildでnginxをビルドしてみましょう。

$ nginx-build -d work -v 1.9.4                                                                                                                  
nginx-build: 0.4.4
Compiler: gc go1.5
2015/08/23 21:37:57 Download nginx-1.9.4.....
2015/08/23 21:38:03 Extract nginx-1.9.4.tar.gz.....
2015/08/23 21:38:03 Generate configure script for nginx-1.9.4.....
2015/08/23 21:38:03 Configure nginx-1.9.4.....
2015/08/23 21:38:08 Build nginx-1.9.4.....
2015/08/23 21:38:12 Complete building nginx!

nginx version: nginx/1.9.4
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) 
configure arguments:

2015/08/23 21:38:12 Enter the following command for install nginx.

   $ cd work/1.9.4/nginx-1.9.4
   $ sudo make install
$

nginx-buildが行うのはソースコードやライブラリのダウンロードとコンパイルまでなので後は出力にしたがってインストール(make install)します。

configureオプションを指定する

nginx-buildにはnginxのconfigureのオプションを直接付加することができます。

$ nginx-build \
> -d work \
> -v 1.9.4 \
> --with-http_gzip_static_module \
> --with-http_gunzip_module \
> --with-http_stub_status_module \
> --with-http_realip_module
nginx-build: 0.4.4
Compiler: gc go1.5
2015/08/23 21:36:11 nginx-1.9.4 already exists.
2015/08/23 21:36:11 Generate configure script for nginx-1.9.4.....
2015/08/23 21:36:11 Configure nginx-1.9.4.....
2015/08/23 21:36:15 Build nginx-1.9.4.....
2015/08/23 21:36:20 Complete building nginx!

nginx version: nginx/1.9.4
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) 
configure arguments: --with-http_gunzip_module --with-http_stub_status_module --with-http_realip_module --with-http_gzip_static_module

2015/08/23 21:36:20 Enter the following command for install nginx.

   $ cd work/1.9.4/nginx-1.9.4
   $ sudo make install
$

なおオプションを直接与える方法にはほんの少しだけ制限があるのでconfigureの実行スクリプトをファイルで指定する方法も用意しています。

#!/bin/sh

./configure \
 --with-http_gzip_static_module \
 --with-http_gunzip_module \
 --with-http_stub_status_module \
 --with-http_realip_module

このシェルスクリプトファイルをnginx-build-cオプションで付加することでnginxのconfigureオプションを指定できます。

$ nginx-build -d work -v 1.9.4 -c configure.sh
nginx-build: 0.4.4
Compiler: gc go1.5
2015/08/23 21:37:02 Download nginx-1.9.4.....
2015/08/23 21:37:07 Extract nginx-1.9.4.tar.gz.....
2015/08/23 21:37:07 Generate configure script for nginx-1.9.4.....
2015/08/23 21:37:07 Configure nginx-1.9.4.....
2015/08/23 21:37:11 Build nginx-1.9.4.....
2015/08/23 21:37:16 Complete building nginx!

nginx version: nginx/1.9.4
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) 
configure arguments: --with-http_gzip_static_module --with-http_gunzip_module --with-http_stub_status_module --with-http_realip_module

2015/08/23 21:37:16 Enter the following command for install nginx.

   $ cd work/1.9.4/nginx-1.9.4
   $ sudo make install
$

依存ライブラリの組み込み

nginxにはいくつか依存ライブラリがあります。代表的なのは以下の3つです。

nginxはこれらのライブラリを静的あるいは動的に組み込めるようになっています。動的組み込みの場合nginxのconfigureスクリプトがシステムのパスを検索してライブラリのパスを発見してくれますが、静的組み込みに場合は別途依存ライブラリのパスを指定する必要があります。

./configure \
 -with-pcre=../pcre-8.37 \
 --with-zlib=../zlib-1.2.8 \
 --with-openssl=../openssl-1.0.2d

nginx-buildはこれらのライブラリの組み込みをダウンロードも含めて自動化するためのオプションを用意しています。

$ nginx-build \
 -d work \
 -v 1.9.4 \
 -pcre \
 -pcreversion=8.37 \
 -zlib \
 -zlibversion=1.2.8 \
 -openssl \
 -opensslversion=1.0.2d
nginx-build: 0.4.4
Compiler: gc go1.5
2015/08/23 21:47:30 Download nginx-1.9.4.....
2015/08/23 21:47:30 Download zlib-1.2.8.....
2015/08/23 21:47:30 Download openssl-1.0.2d.....
2015/08/23 21:47:30 Download pcre-8.37.....
2015/08/23 21:47:32 Extract zlib-1.2.8.tar.gz.....
2015/08/23 21:47:33 Extract pcre-8.37.tar.gz.....
2015/08/23 21:47:34 Extract openssl-1.0.2d.tar.gz.....
2015/08/23 21:47:37 Extract nginx-1.9.4.tar.gz.....
2015/08/23 21:47:37 Generate configure script for nginx-1.9.4.....
2015/08/23 21:47:37 Configure nginx-1.9.4.....
2015/08/23 21:47:41 Build nginx-1.9.4.....
2015/08/23 21:50:47 Complete building nginx!

nginx version: nginx/1.9.4
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) 
built with OpenSSL 1.0.2d 9 Jul 2015
TLS SNI support enabled
configure arguments: --with-pcre=../pcre-8.37 --with-openssl=../openssl-1.0.2d --with-zlib=../zlib-1.2.8 --with-http_ssl_module

2015/08/23 21:50:47 Enter the following command for install nginx.

   $ cd work/1.9.4/nginx-1.9.4
   $ sudo make install
$

--with-http_ssl_moduleはOpenSSL関連のオプションを指定すると自動的に付加されます。(でないとコンパイルに失敗してしまうので)

サードパーティモジュールの組み込み

nginxにサードパーティのモジュールを組み込むには--add-moduleオプションを利用します。

./configure --add-module={モジュールのパス}

先述の通りnginx-buildではnginxのconfigureのオプションを直接指定出来るので--add-moduleも利用可能です。ここではecho-nginx-moduleheaders-more-nginx-moduleを組み込んでみます。

$ git clone https://github.com/openresty/echo-nginx-module.git
$ git clone https://github.com/openresty/headers-more-nginx-module.git
$ nginx-build \
 -d work \
 -v 1.9.4 \
 --add-module=echo-nginx-module \
 --add-module=headers-more-nginx-module
nginx-build: 0.4.4
Compiler: gc go1.5
2015/08/23 22:05:26 Download nginx-1.9.4.....
2015/08/23 22:05:32 Extract nginx-1.9.4.tar.gz.....
2015/08/23 22:05:32 Generate configure script for nginx-1.9.4.....
2015/08/23 22:05:32 Configure nginx-1.9.4.....
2015/08/23 22:05:37 Build nginx-1.9.4.....
2015/08/23 22:05:42 Complete building nginx!

nginx version: nginx/1.9.4
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) 
configure arguments: --add-module=/home/bokko/nginx/echo-nginx-module --add-module=/home/bokko/nginx/headers-more-nginx-module

2015/08/23 22:05:42 Enter the following command for install nginx.

   $ cd work/1.9.4/nginx-1.9.4
   $ sudo make install
$

さきほどの依存ライブラリ組み込みの例ではダウンロードも自動化していましたが、サードパーティモジュールについてもダウンロードの自動化は可能です。次のようなiniファイル(modules3rd.ini)を用意します。

[echo-nginx-module]
form=git
url=https://github.com/openresty/echo-nginx-module.git
rev=v0.58

[headers-more-nginx-module]
form=git
url=https://github.com/openresty/headers-more-nginx-module.git
rev=v0.261

このファイルをnginx-build-mオプションで付加します。

$ nginx-build -d work -v 1.9.4 -m modules3rd.ini                
nginx-build: 0.4.4
Compiler: gc go1.5
2015/08/23 22:25:22 Download headers-more-nginx-module-v0.261.....
2015/08/23 22:25:22 Download nginx-1.9.4.....
2015/08/23 22:25:22 Download echo-nginx-module-v0.58.....
2015/08/23 22:25:28 Extract nginx-1.9.4.tar.gz.....
2015/08/23 22:25:28 Generate configure script for nginx-1.9.4.....
2015/08/23 22:25:28 Configure nginx-1.9.4.....
2015/08/23 22:25:32 Build nginx-1.9.4.....
2015/08/23 22:25:37 Complete building nginx!

nginx version: nginx/1.9.4
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) 
configure arguments: --add-module=../echo-nginx-module --add-module=../headers-more-nginx-module

2015/08/23 22:25:37 Enter the following command for install nginx.

   $ cd work/1.9.4/nginx-1.9.4
   $ sudo make install
$

nginxをビルドした後にビルド時のconfigureのオプションを確認するのはnginx -Vを実行します。しかし、サードパーティモジュールの場合、どのバージョンのサードパーティモジュールを組み込んだかについては確認するのが困難です。

なのでnginx-build-mオプションを利用してサードパーティモジュールの組み込み手順をファイルに残しておくことは後々のnginxの構成管理をやりやすくするためにもなります。

nginxの派生プロジェクトへの対応

nginxには以下の派生プロジェクトが存在します。

nginx-buildは本家のnginxだけでなくこれらの派生プロジェクトのソースコードのビルドにも対応しています。

OpenResty

OpenRestyはnginxにngx_luaをはじめとする便利なサードパーティモジュールやLuaとLuaJIT、ngx_lua向けのモジュール群(restyモジュール)をバンドルしたアプリケーションフレームワークです。メルカリでも一部のサービスコンポーネントで利用しています。nginx-buildでOpenRestyをビルドするには-openrestyオプションを付加します。また、-openrestyversionでバージョンを指定することが可能です。

nginx-build -d work -pcre -openresty -openrestyversion=1.9.3.1

Tengine

Tengineはnginxのフォークプロジェクトです。モジュールの動的組み込みやアップストリームのヘルスチェックなど本家のnginxには含まれていない(あるいは有償版のNGINX Plusにしかない)便利な機能が利用できるのが特徴です。nginx-buildでTengineをビルドするには-tengineオプションを付加します。また、-tengineversionでバージョンを指定することが可能です。

nginx-build -d work -tengine -tengineversion=2.1.1

まとめ

nginxのビルドプロセスを自動化するためのツールであるnginx-buildについて紹介しました。nginx-buildを利用することで以下の作業の大部分を自動化することができます。

  • nginxのビルド
  • 依存ライブラリのダウンロードと組み込み
  • サードパーティモジュールのダウンロードと組み込み

また、ビルドする際のconfigureのオプションやサードパーティモジュールの組み込み方法をファイルに残すことで後々のnginxの構成管理に役立てることができます。

それでは快適なnginxライフを。