Spring Boot 1.5.x の Web アプリを 2.0.x へバージョンアップする ( その21 )( Docker で RabbitMQ の環境を構築する )
概要
記事一覧はこちらです。
- 今回の手順で確認できるのは以下の内容です。
- RabbitMQ の環境を Windows バイナリ(rabbitmq-server-3.7.7.exe)をインストールして構築した環境から Docker の RabbitMQ による Cluster 環境へ変更します。
- 今回は単体の RabbitMQ サーバ環境を構築し、次回 Cluster 環境を構築する予定です。
- RabbitMQ は管理コンソールを使用したいので、末尾に
-management
が付いた 3.7.8-management を使用します。
参照したサイト・書籍
rabbitmq
https://hub.docker.com/_/rabbitmq/rabbitmq/3.7/debian/Dockerfile
https://github.com/docker-library/rabbitmq/blob/1a8fd1c6ee027baafb7144c24ad3c995ba5e0d24/3.7/debian/Dockerfilerabbitmqctl(8)
https://www.rabbitmq.com/rabbitmqctl.8.htmlRabbitMQ Monitoring
https://grafana.com/dashboards/4279kbudde/rabbitmq_exporter
https://github.com/kbudde/rabbitmq_exporter【超ざっくりわかる】DebianとUbuntuの違いを比較しました
https://eng-entrance.com/linux-debian-ubuntuAlpine Linux で Docker イメージを劇的に小さくする
https://qiita.com/asakaguchi/items/484ba262965ef3823f61alpine linuxベースのdocker imageに移行したはなし
https://techblog.zozo.com/entry/docker_image_slim_in_alpinelinux
目次
- 単体の RabbitMQ サーバの環境を構築する
- ksbysample-webapp-lending から接続する
- RabbitMQ のメトリックスを Prometheus + Grafana で表示してみる
docker-compose up -d
コマンドでコンテナが起動しないことがあるので Docker の利用可能メモリを 2GB → 4GB に変更する+一部のコンテナを "-alpine" イメージに変更する- メモ書き
手順
単体の RabbitMQ サーバの環境を構築する
.env に RabbitMQ のバージョン番号を記述します。
HOST_IP_ADDRESS=172.23.136.33 REDIS_VERSION=5.0.2 REDIS_CLUSTER_1_PORT=6379 REDIS_CLUSTER_2_PORT=6380 REDIS_CLUSTER_3_PORT=6381 REDIS_CLUSTER_4_PORT=6382 REDIS_CLUSTER_5_PORT=6383 REDIS_CLUSTER_6_PORT=6384 RABBITMQ_VERSION=3.7.8-management
RABBITMQ_VERSION=3.7.8-management
を追加します。
docker-compose.yml に rabbitmq の設定を追加します。
rabbitmq: image: rabbitmq:${RABBITMQ_VERSION} container_name: rabbitmq hostname: rabbitmq ports: - "5672:5672" - "15672:15672" environment: - RABBITMQ_DEFAULT_USER=rabbitmq - RABBITMQ_DEFAULT_PASS=12345678
docker-compose up -d
コマンドを実行して起動します。
IntelliJ IDEA の Docker Plugin からログを見てみると以下のように出力されています。エラーは出ていません。
管理コンソールにアクセスしてみます。http://localhost:15672/ にアクセスするとログイン画面が表示されますので、docker-compose.yml に RABBITMQ_DEFAULT_USER, RABBITMQ_DEFAULT_PASS で設定した rabbitmq / 12345678 でログインします。
無事ログインできました。問題はなさそうです。
ksbysample-webapp-lending から接続する
src/main/resources/application-develop.properties の以下の点を変更します。
spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=rabbitmq spring.rabbitmq.password=12345678
- 以下の2行を追加します。docker-compose.yml に RABBITMQ_DEFAULT_USER, RABBITMQ_DEFAULT_PASS で guest / guest 以外のユーザID、パスワードを設定したので、application-develop.properties にも同じユーザID、パスワードを設定します。
spring.rabbitmq.username=rabbitmq
spring.rabbitmq.password=12345678
Tomcat を起動します。Spring Actuator の health check を見ると rabbitmq が認識されています。
ブラウザから http://localhost:8080/ にアクセスして「貸出希望書籍 CSV ファイルアップロード」から貸出希望書籍を登録すると(ここで RabbitMQ にメッセージが送信されます)、
定期タスクが RabbitMQ からメッセージを受信して処理されて、結果のメールが返ってきました。
RabbitMQ の管理コンソールを見るとメッセージが配信されたことが確認できます。
rabbitmqctl コマンドでユーザ一覧を出力してみます。docker exec -it rabbitmq rabbitmqctl list_users
コマンドを実行すると、デフォルトで登録している rabbitmq ユーザが出力されました。
RabbitMQ のメトリックスを Prometheus + Grafana で表示してみる
RabbitMQ のメトリックスを Grafana で表示させる Dashboard があるのか調べてみたところ RabbitMQ Monitoring を見つけました。これを利用して表示させてみます。
RabbitMQ → Prometheus への exporter は kbudde/rabbitmq_exporter を Docker で起動して利用します。docker-compose.yml に rabbitmq_exporter の設定を追加します。
rabbitmq_exporter: image: kbudde/rabbitmq-exporter:latest container_name: rabbitmq_exporter ports: - "9419:9419" environment: - RABBIT_URL=http://${HOST_IP_ADDRESS}:15672 - RABBIT_USER=rabbitmq - RABBIT_PASSWORD=12345678 - RABBIT_CAPABILITIES=bert,no_sort - PUBLISH_PORT=9419
docker/prometheus/prometheus.yml に rabbitmq_exporter からメトリックスを収集する設定を追加します。
- job_name: 'rabbitmq_exporter' static_configs: - targets: ['172.23.136.33:9419']
docker-compose down
、docker-compose up -d
コマンドを実行します。
Grafana に RabbitMQ Monitoring の Dashboard を追加します。http://localhost:3000/ にアクセスした後、画面左側のメニューから「Create」-「Import」を選択します。
「Import」画面が表示されますので 4279
の ID を入力します。
「Prometheus」で「spring-actuator」を選択した後、「Import」ボタンをクリックします。
RabbitMQ Monitoring の Dashboard が表示されます(画面右上の表示間隔の設定を Last 3 hours Refresh every 5s → Last 15 minutes Refresh every 5s に変更しています)。
docker-compose up -d
コマンドでコンテナが起動しないことがあるので Docker の利用可能メモリを 2GB → 4GB に変更する+一部のコンテナを "-alpine" イメージに変更する
docker-compose.yml に Redis、RabbitMQ の設定を追加してから docker-compose down
、docker-compose up -d
コマンドを何度も実行すると、docker-compose up -d
コマンドでエラーメッセージが出ないにもかかわらず実際には Redis Cluster が構築できなかったり、RabbitMQ が起動していなかったりしたことがありました。
docker images
コマンドで Docker Image の一覧を表示させてサイズを確認すると、
- redis:5.0.2-custom (197MB x 7 = 1379MB)
- rabbitmq:3.7.8-management (149MB)
- grafana/grafana:latest (236MB)
- prom/prometheus:latest (97.7MB)
で合計が 1861.7MB もあり、Docker Engine にデフォルトで設定されている利用可能メモリのサイズ(2048MB)ぎりぎりでした。
Docker Engine が利用可能なメモリを 2048MB → 4096MB へ、Swap を 1024MB → 2048MB へ変更します。
また Redis のコンテナは全てを redis:5.0.2-custom にする必要はないので、redis-cluster-1~redis-cluster-6 コンテナは redis:${REDIS_VERSION}-custom
→ redis:${REDIS_VERSION}-alpine
に変更し、redis-cluster-make コンテナだけ redis:${REDIS_VERSION}-custom
を使用するように変更します。redis-cluster-1~redis-cluster-6 コンテナには volumes: - ./docker/redis/redis.conf:/etc/redis/redis.conf
も追加します。rabbitmq コンテナも rabbitmq:${RABBITMQ_VERSION}
→ rabbitmq:${RABBITMQ_VERSION}-alpine
に変更します。
# 起動したコンテナに /bin/sh でアクセスする場合には以下のコマンドを実行する # docker exec -it redis /bin/sh # # 起動したコンテナの redis に redis-cli でアクセスするには以下のコマンドを実行する # docker exec -it redis redis-cli # ############################################################################# # 単体 Redis サーバ # redis: # image: redis:${REDIS_VERSION} # container_name: redis # ports: # - "6379:6379" # ############################################################################# # Redis Cluster redis-cluster-1: image: redis:${REDIS_VERSION}-alpine container_name: redis-cluster-${REDIS_CLUSTER_1_PORT} ports: - "${REDIS_CLUSTER_1_PORT}:6379" - "1${REDIS_CLUSTER_1_PORT}:16379" volumes: - ./docker/redis/redis.conf:/etc/redis/redis.conf command: - /bin/sh - -c - | redis-server /etc/redis/redis.conf \ --cluster-announce-ip ${HOST_IP_ADDRESS} \ --cluster-announce-port ${REDIS_CLUSTER_1_PORT} \ --cluster-announce-bus-port 1${REDIS_CLUSTER_1_PORT} redis-cluster-2: image: redis:${REDIS_VERSION}-alpine container_name: redis-cluster-${REDIS_CLUSTER_2_PORT} ports: - "${REDIS_CLUSTER_2_PORT}:6379" - "1${REDIS_CLUSTER_2_PORT}:16379" volumes: - ./docker/redis/redis.conf:/etc/redis/redis.conf command: - /bin/sh - -c - | redis-server /etc/redis/redis.conf \ --cluster-announce-ip ${HOST_IP_ADDRESS} \ --cluster-announce-port ${REDIS_CLUSTER_2_PORT} \ --cluster-announce-bus-port 1${REDIS_CLUSTER_2_PORT} depends_on: - redis-cluster-1 redis-cluster-3: image: redis:${REDIS_VERSION}-alpine container_name: redis-cluster-${REDIS_CLUSTER_3_PORT} ports: - "${REDIS_CLUSTER_3_PORT}:6379" - "1${REDIS_CLUSTER_3_PORT}:16379" volumes: - ./docker/redis/redis.conf:/etc/redis/redis.conf command: - /bin/sh - -c - | redis-server /etc/redis/redis.conf \ --cluster-announce-ip ${HOST_IP_ADDRESS} \ --cluster-announce-port ${REDIS_CLUSTER_3_PORT} \ --cluster-announce-bus-port 1${REDIS_CLUSTER_3_PORT} depends_on: - redis-cluster-1 redis-cluster-4: image: redis:${REDIS_VERSION}-alpine container_name: redis-cluster-${REDIS_CLUSTER_4_PORT} volumes: - ./docker/redis/redis.conf:/etc/redis/redis.conf ports: - "${REDIS_CLUSTER_4_PORT}:6379" - "1${REDIS_CLUSTER_4_PORT}:16379" command: - /bin/sh - -c - | redis-server /etc/redis/redis.conf \ --cluster-announce-ip ${HOST_IP_ADDRESS} \ --cluster-announce-port ${REDIS_CLUSTER_4_PORT} \ --cluster-announce-bus-port 1${REDIS_CLUSTER_4_PORT} depends_on: - redis-cluster-1 redis-cluster-5: image: redis:${REDIS_VERSION}-alpine container_name: redis-cluster-${REDIS_CLUSTER_5_PORT} volumes: - ./docker/redis/redis.conf:/etc/redis/redis.conf ports: - "${REDIS_CLUSTER_5_PORT}:6379" - "1${REDIS_CLUSTER_5_PORT}:16379" command: - /bin/sh - -c - | redis-server /etc/redis/redis.conf \ --cluster-announce-ip ${HOST_IP_ADDRESS} \ --cluster-announce-port ${REDIS_CLUSTER_5_PORT} \ --cluster-announce-bus-port 1${REDIS_CLUSTER_5_PORT} depends_on: - redis-cluster-1 redis-cluster-6: image: redis:${REDIS_VERSION}-alpine container_name: redis-cluster-${REDIS_CLUSTER_6_PORT} volumes: - ./docker/redis/redis.conf:/etc/redis/redis.conf ports: - "${REDIS_CLUSTER_6_PORT}:6379" - "1${REDIS_CLUSTER_6_PORT}:16379" command: - /bin/sh - -c - | redis-server /etc/redis/redis.conf \ --cluster-announce-ip ${HOST_IP_ADDRESS} \ --cluster-announce-port ${REDIS_CLUSTER_6_PORT} \ --cluster-announce-bus-port 1${REDIS_CLUSTER_6_PORT} depends_on: - redis-cluster-1 redis-cluster-make: build: context: ./docker/redis args: - REDIS_VERSION=${REDIS_VERSION} image: redis:${REDIS_VERSION}-custom container_name: redis-cluster-make command: - /bin/sh - -c - | expect -c " spawn redis-cli --cluster create \ ${HOST_IP_ADDRESS}:${REDIS_CLUSTER_1_PORT} \ ${HOST_IP_ADDRESS}:${REDIS_CLUSTER_2_PORT} \ ${HOST_IP_ADDRESS}:${REDIS_CLUSTER_3_PORT} \ ${HOST_IP_ADDRESS}:${REDIS_CLUSTER_4_PORT} \ ${HOST_IP_ADDRESS}:${REDIS_CLUSTER_5_PORT} \ ${HOST_IP_ADDRESS}:${REDIS_CLUSTER_6_PORT} \ --cluster-replicas 1 expect \"Can I set the above configuration? (type 'yes' to accept): \" send \"yes\n\" expect eof " depends_on: - redis-cluster-1 - redis-cluster-2 - redis-cluster-3 - redis-cluster-4 - redis-cluster-5 - redis-cluster-6 redis_exporter: image: oliver006/redis_exporter:latest container_name: redis_exporter ports: - "9121:9121" environment: - REDIS_ADDR=redis://${HOST_IP_ADDRESS}:${REDIS_CLUSTER_1_PORT},redis://${HOST_IP_ADDRESS}:${REDIS_CLUSTER_2_PORT},redis://${HOST_IP_ADDRESS}:${REDIS_CLUSTER_3_PORT},redis://${HOST_IP_ADDRESS}:${REDIS_CLUSTER_4_PORT},redis://${HOST_IP_ADDRESS}:${REDIS_CLUSTER_5_PORT},redis://${HOST_IP_ADDRESS}:${REDIS_CLUSTER_6_PORT} # 起動したコンテナに /bin/sh でアクセスする場合には以下のコマンドを実行する # docker exec -it rabbitmq /bin/sh # # 起動したコンテナの rabbitmq に rabbitmqctl で接続して管理コマンドを実行するには以下のコマンドを実行する # docker exec -it rabbitmq rabbitmqctl ... rabbitmq: image: rabbitmq:${RABBITMQ_VERSION}-alpine container_name: rabbitmq hostname: rabbitmq ports: - "5672:5672" - "15672:15672" environment: - RABBITMQ_DEFAULT_USER=rabbitmq - RABBITMQ_DEFAULT_PASS=12345678 rabbitmq_exporter: image: kbudde/rabbitmq-exporter:latest container_name: rabbitmq_exporter ports: - "9419:9419" environment: - RABBIT_URL=http://${HOST_IP_ADDRESS}:15672 - RABBIT_USER=rabbitmq - RABBIT_PASSWORD=12345678 - RABBIT_CAPABILITIES=bert,no_sort - PUBLISH_PORT=9419
docker/redis/Dockerfile は ADD redis.conf /etc/redis/
を削除します。
ARG REDIS_VERSION FROM redis:${REDIS_VERSION} RUN apt-get update -qq && apt-get install -y expect
redis:5.0.2-custom の Docker Image を削除してから docker-compose up -d
コマンドを実行します。
(.....途中は長いので省略.....)
IntelliJ IDEA の Docker Plugin で見ると、コンテナは全て起動しており、Redis Cluster の構築も成功していました。
Grafana の Dashboard も正常に表示されて、Tomcat を起動して Web アプリケーションを実行しても特に問題はありませんでした(画面キャプチャは省略)。
再度 docker images
コマンドで Docker Image の一覧を表示させてサイズを確認すると、
- redis:5.0.2-custom (197MB)
- redis:5.0.2-alpine (40.9MB x 6 = 245.4MB)
- rabbitmq:3.7.8-management-alpine (82.8MB)
- grafana/grafana:latest (236MB)
- prom/prometheus:latest (97.7MB)
で合計が 858.9MB まで下がりました。
メモ書き
今回は記事を書いている途中に書いたり、最後に書いたりしたメモ書きです。
- redis/5.0/Dockerfile も rabbitmq/3.7/debian/Dockerfile もベースの OS には
debian:stretch-slim
を使用していました。 OFFICIAL REPOSITORY だと debian が多いのでしょうか? 1. 【超ざっくりわかる】DebianとUbuntuの違いを比較しました の記事を読んだ限りでは、堅実で下記の alpine 程ではないが少ないメモリで動くらしい。 - それとは別に
-alpine
という Docker Image もありました。Alpine Linux を使用していて、軽量で docker pull、docker build コマンド等が超高速になるらしい。。。というか Docker for Windows でコンテナを多数起動する時には Docker Image のサイズが小さくなる alpine 版が用意されているのはありがたいということが分かりました。 - Redis も RabbitMQ も管理で使うポート番号に +10000 するのは何かよく使われるルールなのでしょうか?
- Spring Actuator の Health Check がここにきてすごい便利に感じています。Web アプリケーションから Redis や RabbitMQ がきちんと認識できているのかを簡単に確認できます! DBサーバとしか接続しない場合にはそんなに気にしないのかもしれませんが、いろいろなサーバに接続するようになるとその便利さが実感できます。
履歴
2018/12/02
初版発行。