twemproxy + Redis 環境を Docker で構築
twemproxy(別名 nutcracker) + Redis の環境を Docker で構築してみます。 (twemproxy は memcached・Redis 用の軽量なプロキシです)
使用した設定ファイル等は http://github.com/fits/try_samples/tree/master/blog/20151124/
Redis の Docker イメージを取得
Redis の Docker イメージは docker pull で取得する事にします。
$ docker pull redis
twemproxy の Docker イメージを構築
twemproxy の Docker イメージは、下記 Dockerfile を使って centos のイメージをベースに twemproxy のソースをビルドして作成する事にします。
Dockerfile
FROM centos RUN yum -y update RUN yum -y install make automake libtool git RUN git clone https://github.com/twitter/twemproxy.git RUN cd twemproxy && autoreconf -fvi && ./configure && make && make install RUN rm -fr twemproxy RUN yum clean all
上記 Dockerfile で docker build を実行すれば Docker イメージを作成できます。
Docker イメージの作成
$ docker build --no-cache -t sample/twemproxy:0.1 . ・・・ Successfully built ・・・
twemproxy のビルドで warning は出ましたが、Docker イメージの作成に成功しました。
twemproxy + Redis × 2 の実行
twemproxy と Redis 2台を個別の Docker コンテナで実行してみます。
twemproxy の設定ファイルで接続する Redis サーバーを <ホスト名 or IPアドレス>:<ポート番号>:<重み>
で指定する必要があり、これが課題となります。
twemproxy 設定ファイル例
sample: ・・・ redis: true servers: - 127.0.0.1:6380:1 - 127.0.0.1:6381:1 ・・・
今回は、起動スクリプトを使って twemproxy と Redis の Docker コンテナをまとめて起動するようにしてみました。
該当コンテナを docker start (コンテナを再起動) してみて、失敗した場合は docker run を行うようにしています。 (docker start し易いように --name=<コンテナ名>
で名前を付けています)
また、コンテナ間の接続を容易にするため、docker run 時に -h <ホスト名>
でホスト名も付けました。 (コンテナ名をそのままホスト名に使っています)
/vagrant/tmp/start_twemproxy (twemproxy + Redis コンテナの起動スクリプト)
#!/bin/sh INDENT=" " CONF_DIR=/vagrant/tmp/conf CONTAINER_CONF_DIR=/conf TWEMPROXY_IMAGE=sample/twemproxy:0.1 CONTAINER_REDIS_LIST="redis1 redis2" CONTAINER_TWEMPROXY=twemproxy1 REDIS_SERVERS="" # Redis のコンテナを個々に起動 for s in $CONTAINER_REDIS_LIST do if test -z `docker start $s`; then docker run --name=$s -h $s -d redis else echo start $s fi REDIS_SERVERS="$REDIS_SERVERS$INDENT- $s:6379:1\n" done # twemproxy の設定ファイルを生成 sed -e "s/#{SERVERS}/$REDIS_SERVERS/g" `dirname $0`/nutcracker.yml.tpl > $CONF_DIR/nutcracker.yml # twemproxy のコンテナ起動 if test -z `docker start $CONTAINER_TWEMPROXY`; then docker run --name=$CONTAINER_TWEMPROXY -h $CONTAINER_TWEMPROXY -d -p 6379:6379 -v $CONF_DIR:$CONTAINER_CONF_DIR $TWEMPROXY_IMAGE nutcracker -c $CONTAINER_CONF_DIR/nutcracker.yml else echo start $CONTAINER_TWEMPROXY fi
twemproxy は nutcracker -c <設定ファイル>
で起動しています。
また、twemproxy 設定ファイル(nutcracker.yml)は Redis サーバーの構成に合わせて下記テンプレートの #{SERVERS}
を sed
で置き換えて生成するようにしています。
/vagrant/tmp/nutcracker.yml.tpl (twemproxy 設定ファイルのテンプレート)
sample: listen: 0.0.0.0:6379 hash: fnv1a_64 distribution: ketama timeout: 500 redis: true servers: #{SERVERS}
実行
それでは実行してみます。
初回起動時は docker start に失敗し docker run を実施する事になります。
twemproxy1, redis1, redis2 コンテナの実行例
$ /vagrant/tmp/start_twemproxy Error response from daemon: no such id: redis1 Error: failed to start containers: [redis1] bdc12db5・・・ Error response from daemon: no such id: redis2 Error: failed to start containers: [redis2] fd4546fc・・・ Error response from daemon: no such id: twemproxy1 Error: failed to start containers: [twemproxy1] 87bb567e・・・
redis-cli で twemproxy1 へ接続する Docker コンテナを起動し (Redis の Docker イメージを使っています) 、動作確認してみます。
動作確認
$ docker run --rm -it redis redis-cli -h twemproxy1 twemproxy1:6379> set a 123 OK twemproxy1:6379> get a "123"
twemproxy は正常に動作しているようです。
redis1・2 へ直接接続するコンテナをそれぞれ実行し確認すると、値は redis2 の方に設定されていました。
$ docker run --rm -it redis redis-cli -h redis1 redis1:6379> keys * (empty list or set) redis1:6379> exit $ docker run --rm -it redis redis-cli -h redis2 redis2:6379> keys * 1) "a" redis2:6379> exit
備考 - Vagrant 利用時
Vagrant で起動したゲスト OS 上で Docker を実行している場合、Vagrantfile へ以下のような設定を追加すれば provision で各コンテナを起動しホスト OS から twemproxy へ接続できるようになります。
Vagrantfile
・・・ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| ・・・ # twemproxy 用のポートフォワード設定 config.vm.network "forwarded_port", guest: 6379, host: 6379 # twemproxy + redis の起動スクリプト実行 config.vm.provision :shell, :inline => "/vagrant/tmp/start_twemproxy" end
provision 実施例
> vagrant up --provision ・・・ ==> default: Running provisioner: shell... default: Running: inline script ==> default: start redis1 ==> default: start redis2 ==> default: start twemproxy1
ホスト OS からの接続例
> redis-cli 127.0.0.1:6379> get a "123"