こんにちは。CTOの馬場です。
最近利用する機会が増えてきたdockerネタです。 nginxを動かすときのTipsを3つ紹介します。
foregroudで起動する
dockerではコマンドをforegroundで動かさないとコンテナが停止してしまいます。 nginxはデフォルトはデーモンとして動くので、foregroundで動くように設定しましょう。
nginx.confで設定するならこうです。
daemon off;
Dockerfileの起動コマンドで指定するならこうです。
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
動的な設定を外部化する
イメージの中に設定値を入れちゃうのはダサいですよね。 コンテナ起動時に動的に設定したいものです。
dockerの場合は docker run
時に -e
で環境変数を指定できるので使いましょう。
docker run -d -e MYENV1="hoge" myimage
nginx.confで環境変数を利用するにはperlモジュール( ngx_http_perl_module
)かluaモジュール( ngx_lua
)を使います。
どちらのモジュールもUbuntu14.04のnginx-extraパッケージに入ってます。
まずはenvディレクティブで読み込みたい環境変数を指定します。
env APP_HOST;
perlモジュールであれば perl_set
を使います。
perl_set
は httpコンテキストで利用できます。
perl_set $app_host 'sub { return $ENV{"APP_HOST"}; }';
perlモジュールのかわりにluaモジュールを使う場合は set_by_lua
を使います。
set_by_lua
はserver, server if, location, location ifコンテキストで利用できます。
set_by_lua $app_host 'return os.getenv("APP_HOST")';
設定をもっと動的にしたい場合は設定値をRedisなどに持たせる形がよいでしょう。 これはバックエンドサーバを動的に切り替える例です。 luaであればこのように書きます。 社内ではdockerのホストにこのnginxを起動した上で定期的にdockerのコンテナ状況を監視して、自動的に http://<コンテナ名>.<ローカルのFQDN>/ で各コンテナのwebアプリケーションにアクセスできるようにしています。
location / {
set $upstream "";
rewrite_by_lua '
local res = ngx.location.capture("/redis")
if res.status == ngx.HTTP_OK then
ngx.var.upstream = res.body
else
ngx.exit(ngx.HTTP_FORBIDDEN)
end
';
proxy_pass http://$upstream;
}
location /redis {
internal;
set $redis_key $host;
redis_pass 127.0.0.1:6379;
default_type text/html;
}
このアイデアの元ネタは lua-nginx-module の紹介 ならびに Nginx+Lua+Redisによる動的なリバースプロキシの実装案 - hibomaのはてなダイアリー です
ログを外部に保存する
dockerコンテナ上に永続ファイルを保存するのはナンセンスです。 でもログは保存したい。 けど1コンテナ1プロセスでやるならfluentd同梱は厳しい...
docker run
時に -v
でホストのディレクトリをマウントできるのでこれを利用しましょう。
ホストの /tmp/container1_nginx_log
を /var/log/nginx
にマウントする場合は以下のようにします。
docker run -d -v /tmp/container1_nginx_log:/var/log/nginx myimage
nginx1.7.1からはログがsyslogに出力できます。 元ネタは nginx-1.7.1でsyslogにログを飛ばせるようになったので試してみた - Dマイナー志向 です。 nginx.confで設定するならこうです。
access_log syslog:server=logserver,facility=local1 main;
error_log syslog:server=logserver,facility=local2 notice;
Dockerfileの起動コマンドで指定するならこうです。
CMD ["/usr/sbin/nginx", "-g", "access_log syslog:server=logserver,facility=local1 main; error_log syslog:server=logserver,facility=local2 notice;"]
まとめ
docker楽しい!✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌
nginx+lua/perl楽しい!!!✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌
でも環境構築での時間の使いすぎには注意しましょう。