かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その11 )( Docker コンテナの image をバージョンアップする、rabbitmq・haproxy・rabbitmq_exporter 編 )

概要

記事一覧はこちらです。

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その10 )( Spring Boot を 2.3.2 → 2.3.7 へバージョンアップする+Docker コンテナの image をバージョンアップする、redis・redis_exporter 編 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 今回は以下の Docker コンテナの image をバージョンアップします。
      • rabbitmq
      • haproxy
      • kbudde/rabbitmq-exporter

参照したサイト・書籍

目次

  1. .env を変更する
  2. docker-compose.yml を変更する
  3. docker-compose up -d コマンドを実行する
  4. rabbitmq が起動しない。。。
  5. 環境変数 RABBITMQ_ERLANG_COOKIE をやめて .erlang.cookie file に変更する
  6. HTTP access denied: user 'rabbitmq' - invalid credentials が出力されないようにする+管理画面からログインできるようにする
  7. clean タスク実行 → Rebuild Project 実行 → build タスクを実行する
  8. 変更前の docker image を削除する

手順

.env を変更する

..........

RABBITMQ_VERSION=3.8.9-management
RABBITMQ_ERLANG_COOKIE=Uzkm93w5e1Lz8AcP
RABBITMQ_DEFAULT_USER=rabbitmq
RABBITMQ_DEFAULT_PASS=12345678
RABBITMQ_DEFAULT_VHOST=/

..........
  • RABBITMQ_VERSION=3.8.2-managementRABBITMQ_VERSION=3.8.9-management に変更します。

docker-compose.yml を変更する

  ..........
  # http://localhost:1936/haproxy?stats
  haproxy:
    image: haproxy:2.3.2-alpine
    container_name: haproxy
    ports:
      - "1936:1936"
      - "5672:5672"
      - "15672:15672"
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    depends_on:
      - rabbitmq1
      - rabbitmq2
      - rabbitmq3
  ..........
  • image: haproxy:2.1.2-alpineimage: haproxy:2.3.2-alpine に変更します。

docker-compose up -d コマンドを実行する

以下のコマンドを実行して docker image を更新・ダウンロードします(画面キャプチャはなし)。

  1. docker-compose build --no-cache コマンドを実行し、Dockerfile で作成している image を更新します。
  2. kbudde/rabbitmq-exporter は latest の docker image をダウンロードしているので、ローカルの docker image を削除します。
  3. docker-compose up -d コマンドを実行してコンテナ一式(メールサーバ・rainloop を除く)を起動します。

rabbitmq が起動しない。。。

docker-compose up -d コマンドを実行した後、haproxy の画面で rabbitmq が起動するのを待っても rabbitmq2、rabbitmq3 がいつまでたっても起動しません。

f:id:ksby:20201215003222p:plain

IntelliJ IDEA でコンテナの状況を確認すると rabbitmq2、rabbitmq3 は停止しており、

  • RABBITMQ_ERLANG_COOKIE env variable support is deprecated and will be REMOVED in a future version. Use the $HOME/.erlang.cookie file or the --erlang-cookie switch instead. というログが出力されていました。ただし、あくまでも deprecated なので起動しない原因ではないようです。
  • 起動しない理由は以下3つのいずれかのようです。
    • Target node is unreachable (e.g. due to hostname resolution, TCP connection or firewall issues)
    • CLI tool fails to authenticate with the server (e.g. due to CLI tool's Erlang cookie not matching that of the server)
    • Target node is not running

f:id:ksby:20201215003616p:plain

環境変数 RABBITMQ_ERLANG_COOKIE をやめて .erlang.cookie file に変更する

deprecated のメッセージが出ているので、先に環境変数 RABBITMQ_ERLANG_COOKIE をやめて .erlang.cookie file に変更します。

docker/rabbitmq の下に .erlang.cookie を新規作成し、以下の内容を記述します。

Uzkm93w5e1Lz8AcP

.env から RABBITMQ_ERLANG_COOKIE=Uzkm93w5e1Lz8AcP を削除します。

RABBITMQ_VERSION=3.8.9-management
RABBITMQ_DEFAULT_USER=rabbitmq
RABBITMQ_DEFAULT_PASS=12345678
RABBITMQ_DEFAULT_VHOST=/

docker-compose.yml の rabbitmq1、rabbitmq2、rabbitmq3 の environment から - RABBITMQ_ERLANG_COOKIE を削除します。

  # RabbitMQ Clustering
  rabbitmq1:
    build:
      context: ./docker/rabbitmq
      args:
        - RABBITMQ_VERSION=${RABBITMQ_VERSION}
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq1
    hostname: rabbitmq1
    environment:
      - TZ=Asia/Tokyo
      - RABBITMQ_DEFAULT_USER
      - RABBITMQ_DEFAULT_PASS
      - RABBITMQ_DEFAULT_VHOST
  rabbitmq2:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq2
    hostname: rabbitmq2
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /bin/sh -c /usr/local/bin/cluster-entrypoint.sh
    depends_on:
      - rabbitmq1
  rabbitmq3:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq3
    hostname: rabbitmq3
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /usr/local/bin/cluster-entrypoint.sh
    depends_on:
      - rabbitmq1

https://www.rabbitmq.com/clustering.html#cookie-file-locations を見ると .erlang.cookie は /var/lib/rabbitmq/.erlang.cookie に配置すると記述されているので、docker/rabbitmq/Dockerfile を以下のように変更します。

ARG RABBITMQ_VERSION
FROM rabbitmq:${RABBITMQ_VERSION}-alpine
RUN apk add --no-cache tzdata
COPY .erlang.cookie /var/lib/rabbitmq/
  • COPY .erlang.cookie /var/lib/rabbitmq/ を追加します。

docker-compose build --no-cache コマンドを実行してから docker-compose up -d コマンドを実行します。。。が、Cookie file /var/lib/rabbitmq/.erlang.cookie must be accessible by owner only というメッセージが表示されて rabbitmq が起動しません。

f:id:ksby:20201217003125p:plain

docker/rabbitmq/Dockerfile の最後に RUN ls -al /var/lib/rabbitmq/ を追加して .erlang.cookie の owner、permission を確認すると -rwxr-xr-x 1 root root でした。

f:id:ksby:20201217004205p:plain

owner/group は https://github.com/docker-library/rabbitmq/blob/master/3.8/alpine/Dockerfile を見ると addgroup、adduser コマンドで rabbitmq が指定されており、permission は -rw------- にすれば良いはずなので、docker/rabbitmq/Dockerfile を以下のように変更してみます。

ARG RABBITMQ_VERSION
FROM rabbitmq:${RABBITMQ_VERSION}-alpine
RUN apk add --no-cache tzdata
COPY --chown=rabbitmq:rabbitmq .erlang.cookie /var/lib/rabbitmq/
RUN chmod 600 /var/lib/rabbitmq/.erlang.cookie
RUN ls -al /var/lib/rabbitmq/
  • COPY コマンドに --chown=rabbitmq:rabbitmq オプションを追加します。
  • RUN chmod 600 /var/lib/rabbitmq/.erlang.cookie を追加します。

docker-compose build --no-cache コマンドを実行すると owner、group は rabbitmq に変更されましたが、permission は -rwxr-xr-x のままでした。。。

f:id:ksby:20201217005337p:plain

この permission を変更する方法が最初全然分からなかったのですが、いろいろ検索してみた結果、以下の方法で解消できました。

  • chmod not working correctly in Docker を読むと VOLUME /var/lib/rabbitmq が指定されているから RUN コマンドで chmod できないらしい。VOLUME コマンドで指定していないディレクトリで chmod してからコピーすればよいとのこと。
  • ただし Dockerfile 内で COPY --chown=rabbitmq:rabbitmq .erlang.cookie /tmp/RUN chmod 600 /tmp/.erlang.cookie の後に RUN cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/ を実行してもコピーされませんでした。これは Dockerfile ではなくコンテナ起動時に command あるいは entrypoint で実行するシェルスクリプトでやればコピーできます。

    f:id:ksby:20201217011651p:plain

最終的に以下のようになりました。

■docker/rabbitmq/Dockerfile

ARG RABBITMQ_VERSION
FROM rabbitmq:${RABBITMQ_VERSION}-alpine
RUN apk add --no-cache tzdata
COPY --chown=rabbitmq:rabbitmq .erlang.cookie /tmp/
RUN chmod 600 /tmp/.erlang.cookie
  • 以下の2行を追加しました。.erlang.cookie を /tmp にコピー後、owner を rabbitmq:rabbitmq へ、permission を -rw------- へ変更します。
    • COPY --chown=rabbitmq:rabbitmq .erlang.cookie /tmp/
    • RUN chmod 600 /tmp/.erlang.cookie

■docker-compose.yml

  # RabbitMQ Clustering
  rabbitmq1:
    build:
      context: ./docker/rabbitmq
      args:
        - RABBITMQ_VERSION=${RABBITMQ_VERSION}
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq1
    hostname: rabbitmq1
    environment:
      - TZ=Asia/Tokyo
      - RABBITMQ_DEFAULT_USER
      - RABBITMQ_DEFAULT_PASS
      - RABBITMQ_DEFAULT_VHOST
    command:
      - /bin/sh
      - -c
      - |
        cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
        ls -al /var/lib/rabbitmq/
        rabbitmq-server
  rabbitmq2:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq2
    hostname: rabbitmq2
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /usr/local/bin/cluster-entrypoint.sh
    depends_on:
      - rabbitmq1
  rabbitmq3:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq3
    hostname: rabbitmq3
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./docker/rabbitmq/cluster-entrypoint.sh:/usr/local/bin/cluster-entrypoint.sh
    entrypoint: /usr/local/bin/cluster-entrypoint.sh
    depends_on:
      - rabbitmq1
  • rabbitmq1 に command を追加しました。ここで /tmp/.erlang.cookie を /var/lib/rabbitmq/ の下へコピーした後、rabbitmq-server を起動します。
  • rabbitmq2 の entrypoint を /bin/sh -c /usr/local/bin/cluster-entrypoint.sh/usr/local/bin/cluster-entrypoint.sh に修正しました(rabbitmq3 と違っていたのと /bin/sh -c があるとなぜかうまく動作しなかったためです)。

■docker/rabbitmq/cluster-entrypoint.sh

#!/bin/bash

set -e

cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
ls -al /var/lib/rabbitmq/
rabbitmq-diagnostics erlang_cookie_sources

# Start RMQ from entry point.
# This will ensure that environment variables passed
# will be honored
rabbitmq-server -detached

# Wait a while for rabbitmq1 to start
sleep 15s

# Do the cluster dance
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbitmq1

# Stop the entire RMQ server. This is done so that we
# can attach to it again, but without the -detached flag
# making it run in the forground
rabbitmqctl stop

# Wait a while for the app to really stop
sleep 3s

# Start it
rabbitmq-server
  • 以下の3行を追加しました。/tmp/.erlang.cookie を /var/lib/rabbitmq/ の下へコピーします。また https://www.rabbitmq.com/clustering.html#cookie-file-troubleshooting に .erlang.cookie をチェックするコマンドが記載されていたのでそれも追加します。
    • cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
    • ls -al /var/lib/rabbitmq/
    • rabbitmq-diagnostics erlang_cookie_sources
  • /usr/local/bin/docker-entrypoint.sh rabbitmq-server -detachedrabbitmq-server -detached に変更します(/usr/local/bin/docker-entrypoint.sh がなくても動いたので削除しました)。また rabbitmq1 の起動が完了するまで時間がかかるため sleep 15s を追加しました。
  • https://www.rabbitmq.com/clustering.html#creating に記載があったので rabbitmqctl reset を追加しました。
  • rabbitmqctl stop の後の待機時間を sleep 2ssleep 3s に変更しました。

docker-compose build --no-cache コマンドを実行してから docker-compose up -d コマンドを実行すると無事 rabbitmq1、rabbitmq2、rabbitmq3 の全てが起動しました。

f:id:ksby:20201217083004p:plain

rabbitmq2 のログを見ると RABBITMQ_ERLANG_COOKIE env variable support is deprecated ... のメッセージは出力されておらずサーバが問題なく起動していますが、今度は HTTP access denied: user 'rabbitmq' - invalid credentials という warning が延々と出力されていました(この warning は rabbitmq1、rabbitmq3 にも出力されています)。

f:id:ksby:20201217083221p:plain f:id:ksby:20201217083353p:plain

rabbitmq の管理画面から rabbitmq / 12345678 でログインしようしてもログインできませんでした。

f:id:ksby:20201217083835p:plain

HTTP access denied: user 'rabbitmq' - invalid credentials が出力されないようにする+管理画面からログインできるようにする

使っている RabbitMQ のバージョンは違いますが、CentOS7 RabbitMQ 3.7.4 cluster installation and use の記事を見つけました。「Report an error」のところに記述があり、rabbitmqctl add_user コマンドで rabbitmq ユーザを作成すればよいみたいです。

docker-compose.yml の rabbitmq1 コンテナの command で rabbitmqctl add_user コマンドを実行してもエラーが出て登録できなかったので、rabbitmqctl add_user コマンド実行用のコンテナを作成して対応することにします。

docker/rabbitmq の下に create-user-entrypoint.sh を新規作成し、以下の内容を記述します。sleep の時間は 15s だと rabbitmq1 が起動完了する前に rabbitmqctl add_user コマンドを実行する時があったのでここでは 30s にしました。

#!/bin/bash

set -e

cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
ls -al /var/lib/rabbitmq/
rabbitmq-diagnostics erlang_cookie_sources

# Wait a while for rabbitmq1 to start
sleep 30s

rabbitmqctl -n rabbit@rabbitmq1 add_user ${RABBITMQ_DEFAULT_USER} ${RABBITMQ_DEFAULT_PASS}
rabbitmqctl -n rabbit@rabbitmq1 set_user_tags ${RABBITMQ_DEFAULT_USER} administrator
rabbitmqctl -n rabbit@rabbitmq1 set_permissions -p / ${RABBITMQ_DEFAULT_USER} ".*" ".*" ".*"

docker-compose.yml に rabbitmq-create-user コンテナの記述を追加します。

  # RabbitMQ Clustering
  rabbitmq1:
    build:
      context: ./docker/rabbitmq
      args:
        - RABBITMQ_VERSION=${RABBITMQ_VERSION}
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq1
    hostname: rabbitmq1
    environment:
      - TZ=Asia/Tokyo
      - RABBITMQ_DEFAULT_USER
      - RABBITMQ_DEFAULT_PASS
      - RABBITMQ_DEFAULT_VHOST
    command:
      - /bin/sh
      - -c
      - |
        cp -p /tmp/.erlang.cookie /var/lib/rabbitmq/
        ls -al /var/lib/rabbitmq/
        rabbitmq-server
  rabbitmq-create-user:
    image: rabbitmq:${RABBITMQ_VERSION}-alpine-custom
    container_name: rabbitmq-create-user
    hostname: rabbitmq-create-user
    environment:
      - TZ=Asia/Tokyo
      - RABBITMQ_DEFAULT_USER
      - RABBITMQ_DEFAULT_PASS
    volumes:
      - ./docker/rabbitmq/create-user-entrypoint.sh:/usr/local/bin/create-user-entrypoint.sh
    entrypoint: /usr/local/bin/create-user-entrypoint.sh
    depends_on:
      - rabbitmq1
  rabbitmq2:
    ..........
  • 作成するユーザ名、パスワードは環境変数 RABBITMQ_DEFAULT_USER、RABBITMQ_DEFAULT_PASS の設定をそのまま使っています。
  • rabbitmq1 コンテナの environment の RABBITMQ_DEFAULT_USER、RABBITMQ_DEFAULT_PASS は不要なのでは?と思って削除したらエラーが出たので残しています。

動作確認します。docker-compose up -d コマンドを実行して起動した後、

f:id:ksby:20201218095100p:plain

rabbitmq-create-user コンテナのログを確認すると rabbitmqctl add_user コマンド等は全て正常に実行できており、

f:id:ksby:20201218095204p:plain

rabbitmq1、rabbitmq2 コンテナのログを見ると HTTP access denied: user 'rabbitmq' - invalid credentials は出力されていません。

f:id:ksby:20201218095618p:plain f:id:ksby:20201218095801p:plain

http://localhost:15672/ にアクセスして rabbitmq / 12345678 でログインすると無事ログインできました。

f:id:ksby:20201218100117p:plain f:id:ksby:20201218100204p:plain

rabbitmq_exporter の方は、Grafana で RabbitMQ の情報を表示させてみると問題なさそうです。

f:id:ksby:20201218102115p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行する

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20201218101652p:plain

変更前の docker image を削除する

以下の docker image を削除します。

  • rabbitmq:3.8.2-management-alpine
  • rabbitmq:3.8.2-management-alpine-custom

履歴

2020/12/18
初版発行。
2020/12/19
ユーザを作成できない場合があったため、docker/rabbitmq/create-user-entrypoint.sh 内の rabbitmq1 の起動待機時間を sleep 20ssleep 30s に変更しました。