Nginxを拡張してLuaが便利なOpenRestyを使って簡単なAPIのサンプルを書いてみます。バックエンドのRedisに問い合わせてJSON形式でレスポンスを返します。LuaのRedisクライアントはlua-resty-redisを使っているようです。Luaで組み込みのプログラムが書けるので、リバースプロキシにも使うOpenRestyのところで、バックエンドのアプリのちょっとしたAPIの差異を吸収することができます。
プロジェクト
今回もサービスのオーケストレーションにはDocker Composeを使います。プロジェクトのディレクトリを作成してdocker-compose.ymlとnginx.confを作成します。
$ cd ~/openresty_apps
$ tree
.
├── docker-compose.yml
└── nginx
└── nginx.conf
OpenRestyのイメージはtenstartups/openrestyを使います。このイメージでは/entrypoint
という起動スクリプトがENTRYPOINTに設定されています。nginx.confを編集したあとにHUPを送って再読み込みしたいので、docker-compose.ymlで上書きます。
openresty:
restart: always
image: tenstartups/openresty
ports:
- "80:80"
volumes:
- ./nginx:/etc/nginx
links:
- redis
entrypoint: ["nginx", "-c", "/etc/nginx/nginx.conf"]
redis:
restart: always
image: redis
rediscli:
image: redis
links:
- redis
nginx.confで環境変数を読み込むためにenv
ディレクティブを使い、links
で指定されたRedisnサービスのIPアドレスとポートを設定します。クエリ文字列にuuid
を指定します。OpenRestyからRedisに問い合わせて対応するtokenを取得してJSONを返す簡単なサンプルです。
daemon off;
worker_processes 1;
env REDIS_PORT_6379_TCP_ADDR;
env REDIS_PORT_6379_TCP_PORT;
events {
worker_connections 256;
}
http {
server {
listen 80;
access_log /proc/self/fd/1;
error_log /proc/self/fd/2;
location /api/v1/tokens {
default_type text/html;
content_by_lua '
local cjson = require "cjson"
local redis = require "resty.redis"
local red = redis:new()
local args = ngx.req.get_uri_args()
local ok, err = red:connect(os.getenv("REDIS_PORT_6379_TCP_ADDR"), tonumber(os.getenv("REDIS_PORT_6379_TCP_PORT")))
if not ok then
ngx.say("failed to connect: ", err)
return
end
local res, err = red:get("users:" .. args.uuid)
if not res then
ngx.say("failed to get token: ", err)
return
end
ngx.header.content_type = "application/json; charset=utf-8"
ngx.say(cjson.encode({token = res}))
red:close()
';
}
}
}
Docker Composeからopenresty
サービスをupします。
$ docker-compose up openresty
docker-compose up openresty
Recreating openrestyapps_redis_1...
Recreating openrestyapps_openresty_1...
Attaching to openrestyapps_openresty_1
依存関係にあるredis
サービスも起動しますがrediscli
サービスは起動しません。
$ docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------
openrestyapps_op nginx -c /etc/ng Up 0.0.0.0:80->80/t
enresty_1 inx/nginx.conf cp
openrestyapps_re /entrypoint.sh Up 6379/tcp
dis_1 redis-server
redis-cliでレコード作成
rediscli
サービスでテスト用のレコードをRedisに作成します。
$ docker-compose run --rm rediscli bash -c 'redis-cli -h $REDIS_PORT_6379_TCP_ADDR set users:123 8Nyo7D9a'
OK
Removing openrestyapps_rediscli_run_1...
getからレコードの作成を確認します。
$ docker-compose run --rm rediscli bash -c 'redis-cli -h $REDIS_PORT_6379_TCP_ADDR get users:123'
"8Nyo7D9a"
Removing openrestyapps_rediscli_run_1...
curlでテスト
openresty
サービスにHUPを送ってnginx.confを再読込します。
$ docker-compose kill -s HUP openresty
Killing openrestyapps_openresty_1...
Dockerホストからcurlを使いJSON形式でtokenが取得できました。
$ curl "http://localhost/api/v1/tokens?uuid=123"
{"token":"8Nyo7D9a"}