nginxで動的プロキシ環境を作ります
バックエンドのアプリはdockerを使用してバックエンドで動くwebサーバーコンテナを立ててそれを動的にプロキシしてみます。
システム構成
OS
ubuntu 14.04 LTS
Middleware
nginx
リクエストを受けてバックエンドへプロキシします
docker
バックエンドのアプリを動かす環境として使用します
redis
ドメインとバックエンドのアプリのポートを紐付けます
lua
nginxの設定ファイルの中でredisに接続して動的に値を返す役割
まずはubuntuの設定
# アップデート
apt-get -y update && apt-get -y upgrade
# 必要なパッケージをインストールします
apt-get install -y build-essential autoconf libssl-dev curl libcurl4-gnutls-dev zlib1g zlib1g-dev libxml2 libxml2-dev libxslt-dev libreadline6-dev
# redisサーバーをインストール
apt-get install -y redis-server
# luaをインストール
apt-get install -y lua5.1 liblua5.1-0 liblua5.1-0-dev
ln -s /usr/lib/x86_64-linux-gnu/liblua5.1.so /usr/lib/liblua.so
# luaのソケットライブラリをインストール
apt-get install -y lua-svn
# nginxはluaモジュールを使用するためコンパイルします。
mkdir -p /tmp/src
cd /tmp/src
wget -O "nginx-1.7.0.tar.gz" "http://nginx.org/download/nginx-1.7.0.tar.gz"
wget -O "pcre-8.35.tar.gz" "ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.35.tar.gz"
wget -O "zlib-1.2.8.tar.gz" "http://zlib.net/zlib-1.2.8.tar.gz"
wget -O "openssl-1.0.1g.tar.gz" "http://www.openssl.org/source/openssl-1.0.1g.tar.gz"
wget -O "nginx_devkit.tar.gz" "https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz"
wget -O "nginx_lua.tar.gz" "https://github.com/openresty/lua-nginx-module/archive/v0.9.7.tar.gz"
tar zxf nginx-1.7.0.tar.gz
tar zxf pcre-8.35.tar.gz
tar zxf zlib-1.2.8.tar.gz
tar zxf openssl-1.0.1g.tar.gz
tar zxf nginx_devkit.tar.gz
tar zxf nginx_lua.tar.gz
# opensslのコンパイルはdocの生成で失敗するのでpatchを当てます
wget https://gist.githubusercontent.com/martensms/10107481/raw/e6bf3488f476e7eb1dc4a5f182a75641f7615380/1.0.1g-docfixes-diff.patch
patch -p0 < 1.0.1g-docfixes-diff.patch
# configure
cd nginx-1.7.0
export LUA_LIB=/usr/lib
export LUA_INC=/usr/include/lua5.1
./configure --prefix=/usr/local/nginx \
--with-http_gzip_static_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-zlib=../zlib-1.2.8 \
--with-pcre=../pcre-8.35 \
--with-openssl=../openssl-1.0.1g \
--add-module=../ngx_devel_kit-0.2.19 \
--add-module=../lua-nginx-module-0.9.7
# コンパイル
make && make install
# luaのredisスクリプト
mkdir -p /usr/local/lib/lua/5.1
cd /usr/local/lib/lua/5.1
wget https://raw.github.com/nrk/redis-lua/version-2.0/src/redis.lua
nginxの設定ファイル
server {
listen 80;
server_name _;
server_name_in_redirect off;
port_in_redirect off;
root /root/html;
location / {
set $upstream "";
rewrite_by_lua '
-- load global route cache into current request scope
-- by default vars are not shared between requests
local routes = _G.routes
-- setup routes cache if empty
if routes == nil then
routes = {}
ngx.log(ngx.ALERT, "Route cache is empty.")
end
-- try cached route first
local route = routes[ngx.var.http_host]
if route == nil then
local redis = require "redis"
local client = redis.connect("localhost", 6379)
route = client:get(ngx.var.http_host)
end
-- fallback to redis for lookups
if route ~= nil then
ngx.var.upstream = route
routes[ngx.var.http_host] = route
_G.routes = routes
else
ngx.exit(ngx.HTTP_NOT_FOUND)
end
';
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_connect_timeout 10;
proxy_send_timeout 30;
proxy_read_timeout 30;
proxy_pass http://$upstream;
}
}
こちらのものを使わせてもらっています。
dockerでnginxが起動されるイメージを作成
dockerをインストール
curl -s https://get.docker.io/ubuntu/ | sudo sh
コンテナイメージの作成
Dockerfile
FROM ubuntu
ENV DEBIAN_FRONTEND noninteractive
RUN locale-gen en_US.UTF-8 && update-locale LANG=en_US.UTF-8
ENV LC_ALL C
ENV LC_ALL en_US.UTF-8
RUN echo "deb http://us.archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update && apt-get upgrade -y && apt-get install -y nginx supervisor openssh-server && apt-get clean && rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/*
RUN dpkg-divert --local --rename --add /sbin/initctl && rm -f /sbin/initctl && ln -s /bin/true /sbin/initctl
RUN useradd -d /home/docker -m -s /bin/bash docker \
&& echo docker:docker | chpasswd \
&& echo 'docker ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
# sshd config
RUN sed -i -e '/^UsePAM\s\+yes/d' /etc/ssh/sshd_config \
&& mkdir -p /var/run/sshd \
&& /etc/init.d/ssh start \
&& /etc/init.d/ssh stop
RUN sed -i 's/.*session.*required.*pam_loginuid.so.*/session optional pam_loginuid.so/g' /etc/pam.d/sshd
RUN /bin/echo -e "LANG=\"ja_JP.UTF-8\"" > /etc/default/local
# supervisor
RUN mkdir -p /var/log/supervisor
ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf
EXPOSE 22 80
CMD ["/usr/bin/supervisord"]
supervisord.conf
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:nginx]
command=/usr/sbin/nginx -c /etc/nginx/nginx.conf
process_name=%(program_name)s
numprocs=1
stopsignal=QUIT
イメージをビルド
cd <Dockerfileがあるpath>
docker build --no-cache --rm -t test/nginx .
nginxコンテナを起動する
docker run -d -i -p 49153:80 -t test/nginx /usr/bin/supervisord
docker run -d -i -p 49154:80 -t test/nginx /usr/bin/supervisord
2つのコンテナの80番をそれぞれ49153, 49154に割り当てました
redisにドメインとコンテナを紐付けます
user1.example.com
を49153
ポートのコンテナ
user2.example.com
を49154
ポートのコンテナ
に紐付けます
※とりあえずhostsとかでubuntuのIPに向けます。実際使う時はワイルドカードとかでやると思います。
redis-cli =>
SET user1.example.com 127.0.0.1:49153
SET user2.example.com 127.0.0.1:49154
nginxを起動
/usr/local/nginx/sbin/nginx
user1.example.comにアクセスすれば49153のコンテナにプロキシされ
user2.example.comにアクセスすれば49154のコンテナにプロキシされるようになります。