「docker build」に、「--no-cache」を付与。
$ docker build --no-cache -t [タグ:バージョン] .
「docker build」に、「--no-cache」を付与。
$ docker build --no-cache -t [タグ:バージョン] .
今までDockerを使う時はdockerコマンド単体で扱っていたのですが、最近少し複数コンテナを扱いそうな機会が増えてきまして。これを機に、Docker Composeを試してみようかと思います。
Docker Composeを使うと、複数のコンテナをまとめて管理できるのだとか。
早速使ってみます。
参考)
docker-composeを使うと複数コンテナの管理が便利に - Qiita
Docker Compose チュートリアル - ようへいの日々精進XP
ドキュメントに沿って、まずはインストール。Docker自体は、あらかじめインストールが済んでいるものとします。
なお、当方の環境はUbuntu Linux 14.04 LTSです。
で、ドキュメントのインストールコマンドだと
curl -L https://github.com/docker/compose/releases/download/VERSION_NUM/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
と書いているのですが、「VERSION_NUM」のところは自分で置き換えてあげる必要があります。
どのバージョンを使うかは、こちらを見て選ぶことになるのでは。
https://github.com/docker/compose/releases
今回は、1.4.1を使用します。
また、このコマンドは
/usr/local/bin/docker-compose
というファイルに書き込めと言っているのですが、rootで実行しているわけでもないのでsudo越しになります。
というわけで、結果このようなコマンドになりました。
$ sudo sh -c 'curl -L https://github.com/docker/compose/releases/download/1.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose'
権限変更。
$ sudo chmod +x /usr/local/bin/docker-compose
オプションな手順ではありますが、コマンド補完ができるようにbashの設定も追加しておきます。こちらも案内されている手順は
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose --version | awk 'NR==1{print $NF}')/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
ですが、やはりこのままだとroot権限がないので、以下のようにsudo越しになりました。
$ sudo sh -c "curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose --version | awk 'NR==1{print $NF}')/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose"
バージョン確認。
$ docker-compose --version docker-compose version: 1.4.1
以上で、インストールはおしまいです。
アップグレードする時は、削除して再度インストールするみたいです。
では、Docker Composeを動かしてみます。Docker Composeを使うには、「docker-compose.yml」というYAMLファイルを作成することになるみたいです。
適当なディレクトリを作成して、そちらに移動。
$ mkdir docker-compose-getting-started $ cd docker-compose-getting-started
ドキュメントに載っているDjango、Rails、Wordpressにチャレンジするのもちょっと微妙な気がしたので、ここは自分で書いてみました。
コンテナは、MySQL
https://hub.docker.com/r/library/mysql/
それから簡単なWebアプリケーションとしてGroovyでスクリプトを書いて試すことにします。
https://hub.docker.com/r/webratio/groovy/
今回は、自分でDockerイメージは作りません。docker-compose.ymlを書いて、その中に「build:」があれば以下のコマンドでDockerイメージのビルドが
$ docker-compose build
またDockerイメージのpullは以下のコマンドで行うそうなのですが、今回は使いません。
$ docker-compose pull
で、用意したdocker-compose.ymlはこちら。
docker-compose.yml
web: image: webratio/groovy:2.4.4 ports: - "18080:8080" volumes: - ./web/script:/source - ./web/graperoot:/graperoot links: - mysql command: "rest-server.groovy" mysql: image: mysql:5.6.26 ports: - "3306" environment: MYSQL_ROOT_PASSWORD: my-secret-pw
webと付けた方のコンテナは、後述しますがgroovyコマンドで実行するスクリプト(ここでは「rest-server.groovy」)でサーバーが立ち、ポート8080でリッスンします。これをホスト側の18080ポートにあてています。また、いくつかVOLUMEを設定し(webratio/groovyイメージ参照)、mysqlとリンク設定を入れています。
最後のcommandは、DockerfileのENTRYPOINTの引数となります。
mysqlは、ポート3306を定義していますが、ホスト側の定義を書いていないので、ホスト側の適当なポートにマッピングされるようになります。パスワードは、環境変数で設定。
で、用意したGroovyスクリプトはこちら。
web/script/rest-server.groovy
@Grab('mysql:mysql-connector-java:5.1.36') @GrabConfig(systemClassLoader = true) import groovy.sql.Sql @Grab('org.jboss.resteasy:resteasy-jackson2-provider:3.0.13.Final') @Grab('org.jboss.resteasy:resteasy-jdk-http:3.0.13.Final') import javax.ws.rs.* import javax.ws.rs.core.* import org.jboss.resteasy.plugins.server.sun.http.HttpContextBuilder import com.sun.net.httpserver.HttpServer class Entry { int id String name } @Path("mysql") class MySqlResource { @GET @Path("select") @Produces(MediaType.APPLICATION_JSON) def select() { def sql = Sql.newInstance('jdbc:mysql://mysql:3306/test', 'root', 'my-secret-pw', 'com.mysql.jdbc.Driver') def result = sql.rows("SELECT * FROM entry ORDER BY id").collect { row -> new Entry([id: row.id, name: row.name]) } sql.close() result } @PUT @Path("insert") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) def insert(Entry entry) { def sql = Sql.newInstance('jdbc:mysql://mysql:3306/test', 'root', 'my-secret-pw', 'com.mysql.jdbc.Driver') sql.execute("INSERT INTO entry(id, name) VALUES(${entry.id}, ${entry.name})") sql.close() } } def server = HttpServer.create(new InetSocketAddress(8080), 10) def contextBuilder = new HttpContextBuilder() [MySqlResource].each { contextBuilder.deployment.actualResourceClasses.add(it) } def context = contextBuilder.bind(server) server.start() println("[${new Date()}] RestEasyJdkHttpd startup[${server.address}].")
作りはかなり適当ですが、ご愛嬌…。
JDBCの接続URLでのホスト名は、Dockerでリンクを貼った物にしています。
Sql.newInstance('jdbc:mysql://mysql:3306/test', 'root', 'my-secret-pw', 'com.mysql.jdbc.Driver')
このスクリプトを、先ほどVOLUMEで定義した「./web/script」配下に置いています。
では、docker-compose.ymlファイルをカレントディレクトリに置いた状態で、「up」。
$ docker-compose up dockercomposegettingstarted_mysql_1 is up-to-date dockercomposegettingstarted_web_1 is up-to-date Attaching to
起動したまま、待ち状態になります。「docker run -d」のようにするには、同じく「-d」オプションを付与します。
いったんCtrl-Cで終了して、コンテナ削除。
$ docker-compose rm
「-d」付きで起動。
$ docker-compose up -d
Creating dockercomposegettingstarted_mysql_1...
Creating dockercomposegettingstarted_web_1...
今度は、端末に制御が戻ってきます。
「docker-compose ps」で、コンテナの一覧が見れます。
$ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------------ dockercomposegettingstarted_mysql_1 /entrypoint.sh mysqld Up 0.0.0.0:32795->3306/tcp dockercomposegettingstarted_web_1 groovy -Dgrape.root=/grape ... Up 0.0.0.0:18080->8080/tcp
ログを確認するには、「docker-compose logs」。
$ docker-compose logs
停止。
$ docker-compose stop Stopping dockercomposegettingstarted_web_1... done Stopping dockercomposegettingstarted_mysql_1... done
先ほど1度出しましたが、「docker-compose rm」でコンテナ削除。
$ docker-compose rm Going to remove dockercomposegettingstarted_web_1, dockercomposegettingstarted_mysql_1 Are you sure? [yN] y Removing dockercomposegettingstarted_web_1... done Removing dockercomposegettingstarted_mysql_1... done
また、各コマンドは後ろにコンテナ名の指定ができるので、以下のように特定のコンテナのみを起動することも可能です。
$ docker-compose up -d mysql
Creating dockercomposegettingstarted_mysql_1...
複数指定も可。
コンテナ単位に起動していなくても、ログを個別に見れます。
$ docker-compose logs mysql
おお、便利だ!!
で、コンテナ操作をしただけで、上に乗っているものを何も動かしていないので、ちょっと動かしてみます。
まずは起動。
$ docker-compose up -d
Starting dockercomposegettingstarted_mysql_1...
Creating dockercomposegettingstarted_web_1...
MySQLにテーブルなどが何もないので、コンテナに入って作成。
$ docker exec -it dockercomposegettingstarted_mysql_1 /bin/bash
データベース、テーブル作成。
# mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.6.26 MySQL Community Server (GPL) Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> CREATE DATABASE test; Query OK, 1 row affected (0.05 sec) mysql> USE test; Database changed mysql> CREATE TABLE entry(id INT, name VARCHAR(255), PRIMARY KEY(id)); Query OK, 0 rows affected (0.06 sec)
ホスト側から確認してみます。
$ curl http://localhost:18080/mysql/select
{}
とりあえず、エラーにはなりません、と。
データ登録。
$ curl -XPUT -H 'Content-Type: application/json' http://localhost:18080/mysql/insert -d '{ "id": 1, "name": "Taro" }' $ curl -XPUT -H 'Content-Type: application/json' http://localhost:18080/mysql/insert -d '{ "id": 2, "name": "Jiro" }'
確認。
$ curl http://localhost:18080/mysql/select [{"id":1,"name":"Taro"},{"id":2,"name":"Jiro"}]
OKそうです。
Docker Composeでは、scaleコマンドで実行中のインスタンスを増やすことができるようです。
webを3つにしています。
$ docker-compose scale web=3 The "web" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash. Creating and starting 2... error Creating and starting 3... error ERROR: for 2 Cannot start container bb19e6f7acab86eaad22eafe51c3ba39e25f1d525c796f276a07a1053ee98afa: Bind for 0.0.0.0:18080 failed: port is already allocated ERROR: for 3 Cannot start container 6bab879c70bcb455e5d48329d5d3ba00141b9df456b7358a1a584cbf05d35d80: Bind for 0.0.0.0:18080 failed: port is already allocated Removing dockercomposegettingstarted_web_2... done Removing dockercomposegettingstarted_web_3... done
まあ、ホスト側に18080でバインドしようとするので、失敗しますよね…。
いったん停止。
$ docker-compose stop Stopping dockercomposegettingstarted_web_1... done Stopping dockercomposegettingstarted_mysql_1... done
仕方がないので、web側のポートをいったんホスト側で固定するのをやめます。
web: image: webratio/groovy:2.4.4 ports: - "8080"
再度起動。
$ docker-compose up -d
Starting dockercomposegettingstarted_mysql_1...
Recreating dockercomposegettingstarted_web_1...
web側も適当なポートに割り当てられました。
$ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------------ dockercomposegettingstarted_mysql_1 /entrypoint.sh mysqld Up 0.0.0.0:32800->3306/tcp dockercomposegettingstarted_web_1 groovy -Dgrape.root=/grape ... Up 0.0.0.0:32801->8080/tcp
webを3つにしてみます。
$ docker-compose scale web=3 Creating and starting 2... done Creating and starting 3... done
確認。
## ポート確認 $ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------------ dockercomposegettingstarted_mysql_1 /entrypoint.sh mysqld Up 0.0.0.0:32800->3306/tcp dockercomposegettingstarted_web_1 groovy -Dgrape.root=/grape ... Up 0.0.0.0:32801->8080/tcp dockercomposegettingstarted_web_2 groovy -Dgrape.root=/grape ... Up 0.0.0.0:32802->8080/tcp dockercomposegettingstarted_web_3 groovy -Dgrape.root=/grape ... Up 0.0.0.0:32803->8080/tcp ## web#1 $ curl http://localhost:32801/mysql/select [{"id":1,"name":"Taro"},{"id":2,"name":"Jiro"}] ## web#2 $ curl http://localhost:32802/mysql/select [{"id":1,"name":"Taro"},{"id":2,"name":"Jiro"}] ## web#3 $ curl http://localhost:32803/mysql/select [{"id":1,"name":"Taro"},{"id":2,"name":"Jiro"}]
できてそうです。
なるほど、確かにこれは便利そうですね。覚えておきましょう。
Docker Composeを試してみたので、これを使ってApache Solrのレプリケーションを構成してみたいと思います。
Index Replication | Apache Solr Reference Guide 6.6
Solrのレプリケーションは、マスターとスレーブがあって、それぞれの設定をsolrconfig.xmlにすればよいみたいです。
参考)
https://cwiki.apache.org/confluence/display/solr/Making+and+Restoring+Backups+of+SolrCores
tree-tips: solrのReplicationHandlerで簡単レプリケーション! | Apache Solr
moco(beta)'s backup: Solrのレプリケーション機能を試す (1)
このあたりを参考にSolrを設定します。
で、Docker Composeを使って構成すると言いましたが、とりあえず普通にDockerfileを書いてDockerイメージをビルドします。
Dockerfile
FROM ubuntu:latest ENV JAVA_HOME /usr/lib/jvm/java-8-oracle ENV SOLR_VERSION 5.3.0 ENV SOLR_ARCHIVE solr-${SOLR_VERSION}.tgz ENV SOLR_INSTALL_DIR /opt ENV SOLR_DATA_DIR /var/solr ENV SOLR_PORT 8983 ENV SOLR_CORE_NAME mycore ## Oracle JDK 8インストール RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && \ apt-get install -y software-properties-common && \ add-apt-repository -y ppa:webupd8team/java && \ apt-get update && \ apt-get install -y oracle-java8-installer ## ツールインストール RUN apt-get install -y lsof \ curl \ vim ## 日本語環境サポート RUN apt-get install -y language-pack-ja-base \ language-pack-ja \ ibus-mozc \ man \ manpages-ja && \ update-locale LANG=ja_JP.UTF-8 LANGUAGE=ja_JP:ja ENV LANG ja_JP.UTF-8 ENV LC_ALL ja_JP.UTF-8 ENV LC_CTYPE ja_JP.UTF-8 ## Solrインストール RUN wget -q http://ftp.jaist.ac.jp/pub/apache//lucene/solr/${SOLR_VERSION}/${SOLR_ARCHIVE} && \ tar -zxvf ${SOLR_ARCHIVE} solr-${SOLR_VERSION}/bin/install_solr_service.sh && \ solr-${SOLR_VERSION}/bin/install_solr_service.sh ${SOLR_ARCHIVE} -i ${SOLR_INSTALL_DIR} -d ${SOLR_DATA_DIR} -p ${SOLR_PORT} EXPOSE ${SOLR_PORT} ## コア作成 RUN service solr restart && \ sudo -u solr ${SOLR_INSTALL_DIR}/solr/bin/solr create -c ${SOLR_CORE_NAME} && \ service solr stop && \ rm /var/solr/data/${SOLR_CORE_NAME}/conf/managed-schema ADD solrconfig.xml /var/solr/data/${SOLR_CORE_NAME}/conf/solrconfig.xml ADD schema.xml /var/solr/data/${SOLR_CORE_NAME}/conf/schema.xml ADD entrypoint.sh entrypoint.sh RUN chmod a+x entrypoint.sh ## 実行コマンド ENTRYPOINT ["./entrypoint.sh"]
いくつか設定ファイルのコピーやシェルスクリプトが登場しますが、それは後でまた載せます。
今回は、こんな名前でDockerイメージとして作成しました。
$ docker build -t kazuhira/apache-solr-replication:5.3.0 .
Dockerfileが置かれているカレントディレクトリの内容は、このようになっています。
$ ls -l 合計 84 -rw-rw-r-- 1 xxxxx xxxxx 1843 9月 22 17:16 Dockerfile -rw-rw-r-- 1 xxxxx xxxxx 520 9月 22 17:32 entrypoint.sh -rw-rw-r-- 1 xxxxx xxxxx 10784 9月 22 20:44 schema.xml -rw-rw-r-- 1 xxxxx xxxxx 62463 9月 22 20:43 solrconfig.xml
Dockerfileの中でSolrのコアを作成するようにしているのですが、今回のコアの名前は「mycore」としています。
ENV SOLR_CORE_NAME mycore
で、schema.xmlとsolrconfig.xmlの2つのファイルは、ここで作ったコアに対して反映するようにDockerfileを書いています。
schema.xmlの内容はお好みで…ですが、今回はこのくらいの少ない内容で。
※いろいろ端折っています
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> <field name="_version_" type="long" indexed="true" stored="true"/> <field name="name" type="text_ja" indexed="true" stored="true"/> <!-- Field to use to determine and enforce document uniqueness. Unless this field is marked with required="false", it will be a required field --> <uniqueKey>id</uniqueKey>
Kuromojiは、ユーザー定義辞書を含めるようにしています。
<fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false"> <analyzer> <!-- <tokenizer class="solr.JapaneseTokenizerFactory" mode="search"/> --> <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
solrconfig.xmlですが、schema.xmlを使うようにClassicIndexSchemaFactoryを使うようにしているのと、レプリケーション向けに以下のような設定を入れています。
<requestHandler name="/replication" class="solr.ReplicationHandler"> <lst name="master"> <str name="enable">${solr.repl.master:false}</str> <str name="replicateAfter">startup</str> <str name="replicateAfter">commit</str> <str name="replicateAfter">optimize</str> <str name="confFiles">schema.xml,stopwords.txt,synonyms.txt,lang/stopwords_ja.txt,lang/userdict_ja.txt</str> <str name="backupAfter">optimize</str> </lst> <int name="maxNumberOfBackups">3</int> <lst name="slave"> <str name="enable">${solr.repl.slave:false}</str> <str name="masterUrl">http://solr-master:8983/solr/mycore/replication</str> <str name="pollInterval">00:00:05</str> <str name="httpConnTimeout">5000</str> <str name="httpReadTimeout">10000</str> </lst> </requestHandler>
こちらを参考に、システムプロパティでマスターとスレーブを切り替える設定しています。
tree-tips: solrのReplicationHandlerで簡単レプリケーション! | Apache Solr
マスター側の設定は、レプリケーションのトリガーは起動時、コミット時、オプティマイズ時
<str name="replicateAfter">startup</str> <str name="replicateAfter">commit</str> <str name="replicateAfter">optimize</str>
の3つとし、設定ファイルは以下の内容をレプリケーションします。
<str name="confFiles">schema.xml,stopwords.txt,synonyms.txt,lang/stopwords_ja.txt,lang/userdict_ja.txt</str>
最後に、オプティマイズ後にバックアップを取るように設定。
<str name="backupAfter">optimize</str>
バックアップの数は3つまで。
<int name="maxNumberOfBackups">3</int>
で、マスターとして機能させるかどうかはシステムプロパティで設定します、と。
<str name="enable">${solr.repl.master:false}</str>
スレーブ側は、有効/無効をシステムプロパティで切り替えるとともに、タイムアウトなどの設定を入れています。
<lst name="slave"> <str name="enable">${solr.repl.slave:false}</str> <str name="masterUrl">http://solr-master:8983/solr/mycore/replication</str> <str name="pollInterval">00:00:05</str> <str name="httpConnTimeout">5000</str> <str name="httpReadTimeout">10000</str> </lst>
Solrのレプリケーションは、スレーブからマスターに問い合わせにいく形なので、そのエンドポイントをまずは指定。
<str name="masterUrl">http://solr-master:8983/solr/mycore/replication</str>
ホスト名は、「solr-master」としています。あと、ポーリング間隔は5秒で。
<str name="pollInterval">00:00:05</str>
で、この両者の切り替えなんですけど、DockerのENTRYPOINTに設定するシェルスクリプト内で、どうこうしてしまおうという作戦。シェルスクリプトの中身は、こんな感じです。
entrypoint.sh
#!/bin/bash if [ "$1" == "master" ]; then grep 'SOLR_OPTS="$SOLR_OPTS -Dsolr.repl.master=true"' /var/solr/solr.in.sh || \ echo 'SOLR_OPTS="$SOLR_OPTS -Dsolr.repl.master=true"' >> /var/solr/solr.in.sh elif [ "$1" == "slave" ]; then grep 'SOLR_OPTS="$SOLR_OPTS -Dsolr.repl.slave=true"' /var/solr/solr.in.sh || \ echo 'SOLR_OPTS="$SOLR_OPTS -Dsolr.repl.slave=true"' >> /var/solr/solr.in.sh else echo "require argument 'master' or 'slave'" exit 1 fi service solr start && tail -f /dev/null
「master」と入力されると/var/solr/solr.in.shに「-Dsolr.repl.master=true」を追加し、「slave」と入力されると「-Dsolr.repl.slave=true」を追加するようにしました。
ここまでで、Dockerの準備はおしまい。
あとは、作成したDockerイメージを使ってレプリケーションを構成するための、Docker Composeの設定を書きます。
docker-compose.yml
master: image: kazuhira/apache-solr-replication:5.3.0 ports: - "8983:8983" container_name: solr-master hostname: solr-master command: "master" slave: image: kazuhira/apache-solr-replication:5.3.0 ports: - "8983" links: - master command: "slave"
同じDockerイメージを使って、「command」で追加引数を入れます。あと、マスターのみホスト側から参照するポートは固定にしました。
それでは、起動してみます。「docker-compose.yml」が配置されているディレクトリで、以下のコマンドを実行。
$ docker-compose up -d
Creating solr-master...
Creating solrreplication_slave_1...
コンテナが2つ起動します。
利用しているポートの割り振りは、こんな感じで。
$ docker-compose ps Name Command State Ports ---------------------------------------------------------------------------------- solr-master ./entrypoint.sh master Up 0.0.0.0:8983->8983/tcp solrreplication_slave_1 ./entrypoint.sh slave Up 0.0.0.0:32820->8983/tcp
この場合、それぞれ以下のURLでSolrの管理画面にアクセスできます。
マスター http://localhost:8983/solr/#/mycore
スレーブ http://localhost:32820/solr/#/mycore
マスター側にデータ登録。対象データは、とりあえずこんな感じ。
data1.json
[ { "id": 1, "name": "[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン" }, { "id": 2, "name": "Apache Lucene 入門 〜Java・オープンソース・全文検索システムの構築" } ]
実行。
$ curl -H 'Content-Type: application/json' 'http://localhost:8983/solr/mycore/update?commit=true' --data-binary @data1.json
マスターで検索。
$ curl 'http://localhost:8983/solr/mycore/select?wt=json&indent=true' -d '{ "query": "*:*" }'{ "responseHeader":{ "status":0, "QTime":21, "params":{ "indent":"true", "json":"{ \"query\": \"*:*\" }", "wt":"json"}}, "response":{"numFound":2,"start":0,"docs":[ { "id":"1", "name":"[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン", "_version_":1513016793776521216}, { "id":"2", "name":"Apache Lucene 入門 〜Java・オープンソース・全文検索システムの構築", "_version_":1513016793951633408}] }}
スレーブで検索。
$ curl 'http://localhost:32820/solr/mycore/select?wt=json&indent=true' -d '{ "query": "*:*" }' { "responseHeader":{ "status":0, "QTime":32, "params":{ "indent":"true", "json":"{ \"query\": \"*:*\" }", "wt":"json"}}, "response":{"numFound":2,"start":0,"docs":[ { "id":"1", "name":"[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン", "_version_":1513016793776521216}, { "id":"2", "name":"Apache Lucene 入門 〜Java・オープンソース・全文検索システムの構築", "_version_":1513016793951633408}] }}
OKそうですね。
ここで、Docker Composeでスレーブを3台にしてみます。
$ docker-compose scale slave=3 Creating and starting 2... done Creating and starting 3... done
ポートの状態。
$ docker-compose ps Name Command State Ports ---------------------------------------------------------------------------------- solr-master ./entrypoint.sh master Up 0.0.0.0:8983->8983/tcp solrreplication_slave_1 ./entrypoint.sh slave Up 0.0.0.0:32820->8983/tcp solrreplication_slave_2 ./entrypoint.sh slave Up 0.0.0.0:32821->8983/tcp solrreplication_slave_3 ./entrypoint.sh slave Up 0.0.0.0:32822->8983/tcp
追加したスレーブからも、同じようにデータが検索できます。
$ curl 'http://localhost:32821/solr/mycore/select?wt=json&indent=true' -d '{ "query": "*:*" }' { "responseHeader":{ "status":0, "QTime":34, "params":{ "indent":"true", "json":"{ \"query\": \"*:*\" }", "wt":"json"}}, "response":{"numFound":2,"start":0,"docs":[ { "id":"1", "name":"[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン", "_version_":1513016793776521216}, { "id":"2", "name":"Apache Lucene 入門 〜Java・オープンソース・全文検索システムの構築", "_version_":1513016793951633408}] }}
ここでさらに、マスターにデータ登録。
data2.json
[ { "id": 3, "name": "高速スケーラブル検索エンジン ElasticSearch Server" }, { "id": 4, "name": "Beginning Java EE 6 GlassFish 3で始めるエンタープライズJava" }, { "id": 5, "name": "Javaエンジニア養成読本" } ]
登録。
$ curl -H 'Content-Type: application/json' 'http://localhost:8983/solr/mycore/update?commit=true' --data -binary @data2.json
追加した3台目になるスレーブに対して、検索を実行。
$ curl 'http://localhost:32822/solr/mycore/select?wt=json&indent=true' -d '{ "query": "*:*" }' { "responseHeader":{ "status":0, "QTime":25, "params":{ "indent":"true", "json":"{ \"query\": \"*:*\" }", "wt":"json"}}, "response":{"numFound":5,"start":0,"docs":[ { "id":"1", "name":"[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン", "_version_":1513016793776521216}, { "id":"2", "name":"Apache Lucene 入門 〜Java・オープンソース・全文検索システムの構築", "_version_":1513016793951633408}, { "id":"3", "name":"高速スケーラブル検索エンジン ElasticSearch Server", "_version_":1513017253929418752}, { "id":"4", "name":"Beginning Java EE 6 GlassFish 3で始めるエンタープライズJava", "_version_":1513017253932564480}, { "id":"5", "name":"Javaエンジニア養成読本", "_version_":1513017253937807360}] }}
OKそうですね。
最後に、スレーブは減らしておきます…。
$ docker-compose scale slave=1 Stopping solrreplication_slave_2... done Stopping solrreplication_slave_3... done Removing solrreplication_slave_3... done Removing solrreplication_slave_2... done $ docker-compose ps Name Command State Ports ---------------------------------------------------------------------------------- solr-master ./entrypoint.sh master Up 0.0.0.0:8983->8983/tcp solrreplication_slave_1 ./entrypoint.sh slave Up 0.0.0.0:32820->8983/tcp