Ubuntu

Dockerで稼働しているKeycloakをアップグレードする

SSOを始めようとしたときにKeycloakの存在を知って、幾つかのシステムをKeycloakで認証できるようにセットアップしてみている。
SSOとは何なのか、Keycloakが何なのか、Dockerって何なのか、と言ったところを理解せずに始めたツケとして、Keycloakのアップグレードが立ちはだかっている。



広告


認証の中心になっているので、これが止まるとサービスが利用できなくなってしまう。
でも、古いのを使い続けるのはセキュリティ観点で良くないからアップグレードしたい。

例えばDiscourseはアップグレードを意識した作りになっていて、コマンド一発でアップグレードができるようになっているが、Keycloakはそうなっていない。
アップグレードガイドは、運用中のシステムに直接Keycloakをインストールした場合に対応しているっぽくて、Dockerの場合のやり方がよく分からない。

一般にDockerでは、永続的なデーターをVolume指定した場所に書き込んでいて、つまりはホストのディスクに直接データーを書き出すことになっている。この場合、コンテナを消してイメージを差し替えて、新しいイメージからコンテナを起動すればアップグレードができるっぽい。
でも、Keycloakの実行ガイドはrunで始めるようになっていてVolume指定はなかったので、データーはコンテナに書き込まれており、一般的なやり方ではデーターが消えてしまう。

さてさて…

環境

試験環境はUbuntu 20.04 LTS。work.hogeserver.hogeddns.jp で名前解決ができるようになっている。
Dockerは公式のリポジトリからインストールしており(過去記事)、バージョンは20.10.6、docker-composeは1.29.1となっている。

Keycloakは公式の手順で使い始めていて、バージョンは10.0.2だった。
データーベースは内蔵のH2を使っていて、幾つか設定に手を入れていて、keytabファイルと拡張機能を追加で配置している。

やること

やることをざっくりまとめてみると、

  • exportでコンテナをバックアップする。
  • 環境変数を変えられるようにdocker-compose.ymlを作成する。
  • コンテナの永続化したいディレクトリをホストにコピーしておき、コンテナでvolumeを指定する。
  • 新バージョンのイメージからコンテナを作成する。

という具合。

今回は、本番環境のデーターを試験環境に持ってきて動作を確認しているので、もう少し色々とやってみている。

なお、イメージとコンテナは意識して書き分けているので、注意されたし。

試験環境にコンテナを持ってくる

本番環境のコンテナをバックアップ

現在動作中のKeycloakのコンテナをイメージ化して、試験環境に持っていく。
exportを使うことで、コンテナに書き込まれた様々な情報がイメージ化されるので、試験環境で特別な設定をせずとも動作するはずだ。

$ sudo docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED        STATUS      PORTS                                                 NAMES
58nnnnnnnnnn   keycloak:10.0.2   "/opt/jboss/tools/do…"   9 months ago   Up 6 days   0.0.0.0:8081->8081/tcp, :::8081->8081/tcp, 8444/tcp   keycloak
$ sudo docker export -o docker-keycloak.tar keycloak

イメージがtar形式で保管されるので、これを試験環境にscpで送った。

試験環境でコンテナをインポートする

tarファイルを試験環境でインポートする。
そして、Keycloakをインストールしたときの記事を参考にしつつ、本番環境でinspectして設定値を確認しながら、docker runでイメージを実行。
本番環境では、運用の都合上ポートをコンテナ側もホスト側も8081に変更していた。

$ sudo docker import docker-keycloak.tar keycloak
sha256:708871c1bd72c7a2ec05c6e537122f734cab8ed174e141265088de75342af70a
$ sudo docker image ls
REPOSITORY            TAG                 IMAGE ID       CREATED          SIZE
keycloak              latest              708871c1bd72   28 seconds ago   780MB
…
$ sudo docker run -p 8081:8081 -u 1000 \
-e PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
-e TZ=Asia/Tokyo \
-e KEYCLOAK_VERSION=10.0.2 \
-e LAUNCH_JBOSS_IN_BACKGROUND=1 \
-e PROXY_ADDRESS_FORWARDING=true \
-e JBOSS_HOME=/opt/jboss/keycloak \
-e LANG=en_US.UTF-8 \
--name="keycloak" keycloak /opt/jboss/tools/docker-entrypoint.sh -b 0.0.0.0

=========================================================================

  Using Embedded H2 database
…

過去記事が怪しい…エントリーポイントかコマンドを探して実行すれば良かったっぽい。

環境変数の設定に失敗したら、コンテナを削除して再度作成…ってな感じで上のコマンドパラメーターにたどり着いている。

Chromeでアクセスしてみたところ、Welcome to Keycloakの画面が表示された。
http://work.hogeserver.hogeddns.jp:8081/
※シークレット ウィンドウを開いてアクセス。勝手にhttpsに変わってしまうため。

今までは、/var/lib/docker配下のファイルを直接いじったりしてどうにかこうにか動かしていたが、どうにかまともな手段で移設ができた。

環境変数を変えられるようにする

起動してみたら、やっぱこの環境変数が必要だった、なんてことがあったりするかもしれない。
特にタイムゾーンの設定は、後から是非入れたい設定だった。

docker runで一度コンテナができあがった後で、もう一度runすると「もう、コンテナできてるから」とエラーが返ってくる。
調べてみた限り、「Dockerのコンセプトから考えると、コンテナはイメージをベースに気軽に作り替えられるようにしておく。永続的なデーターはVolumeに入れておく。」ということっぽくて、起動するたびに環境変数をコロコロ変えるというのは違うでしょ?コンテナを作り直しなよ!とされている。

でも、Keycloakのコンテナには永続的に保管したいデーターが含まれており、単純にコンテナを作り直すわけにはいかない。

んー…でもまぁ、これは良い機会なので、環境変数を安全に変える方法を探してみよう。

先日、Redmineを導入するときにdocker-composeを使い、必要に応じて環境変数を変えることができていたので、これを使う。
本番環境でinspectした結果を見ながら、docker-compose.ymlを作って必要な設定を入れていく。

docker-compose.yml

version: "3.9"
services:

  keycloak:
    image: keycloak
    container_name: keycloak
    restart: always
    user: "1000"
    ports:
      - 8081:8081
    environment:
      PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      container: oci
      TZ: Asia/Tokyo
      KEYCLOAK_VERSION: 10.0.2
      JDBC_POSTGRES_VERSION: 42.2.5
      JDBC_MYSQL_VERSION: 8.0.19
      JDBC_MARIADB_VERSION: 2.5.4
      JDBC_MSSQL_VERSION: 7.4.1.jre11
      LAUNCH_JBOSS_IN_BACKGROUND: 1
      PROXY_ADDRESS_FORWARDING: "true"
      JBOSS_HOME: /opt/jboss/keycloak
      LANG: en_US.UTF-8
    entrypoint:
      - /opt/jboss/tools/docker-entrypoint.sh
    command:
      - -b
      - 0.0.0.0

※タブコードが入るとエラーになる。インデントは空白で、かつ、インデントのレベルも重要なのでしっかりと合わせていく。

抜け漏れはあるかもしれないが、起動してみる。

$ sudo docker-compose up

起動後にinspectしてみたところ、指定した環境変数が反映されていた。
ポート番号の変更も、docker-compose.ymlの中でポート指定を変えてupするだけで変更ができた。

イメージをアップグレードする

これまでの手順で、

  • 現在のコンテナをイメージとしてバックアップした。
  • コンテナの環境変数が変更できる。

という状況で、コンテナがかなり扱いやすくなった。

ここから、イメージをアップグレードしていく。

イメージをアップグレードすることとは

イメージをアップグレードするというのは一体どういうことなのか、ということから試してみた。
具体的には、インポートしたイメージではなく、keycloak公式でガイドしてくれている quay.io/keycloak にあるイメージをdocker-compose.ymlで指定してみた。
※この操作を行うと、コンテナに保存されたデーターはなくなってしまうので注意。バックアップがある前提での操作です。

docker-compose.yml

version: "3.9"
services:

  keycloak:
    image: quay.io/keycloak/keycloak:10.0.2
    container_name: keycloak
…

コンテナを起動する。

$ sudo docker-compose up

どのような動作になるかというと、

  • quay.io/keycloak/keycloak:10.0.2をダウンロードしてくる。
  • quay.io/keycloak/keycloak:10.0.2をベースとしてコンテナが作成され、keycloakという名前になる。

であった。コンテナは初期状態になっており、動作時のポートは8080、adminユーザーもなくログインすらできない。

この段階でイメージとコンテナはこんな感じ。

$ sudo docker image ls
REPOSITORY                  TAG                 IMAGE ID       CREATED          SIZE
keycloak                    latest              7d67d3c96204   10 minutes ago   780MB
quay.io/keycloak/keycloak   10.0.2              20e7923ebde7   10 months ago    687MB

$ sudo docker container ls -a
CONTAINER ID   IMAGE                              COMMAND                  CREATED          STATUS                      PORTS         NAMES
26a8b185651a   quay.io/keycloak/keycloak:10.0.2   "/opt/jboss/tools/do…"   12 minutes ago   Exited (0) 11 minutes ago                keycloak

この動作確認で、イメージをアップグレードするためには

  • コンテナの永続化すべきディレクトリをVolume指定する。
  • コンテナを削除し、新バージョンのイメージを持ってきて新しくコンテナを作る。
  • Volume指定するほどでもない変更は、事前に準備しておいて、新しいコンテナに適用する。

をすれば良いと分かった。

動作が分かったところで、試験環境を元に戻す。
具体的には、今作ったコンテナを削除し、本番環境のイメージからコンテナを作り直して起動する。

$ sudo docker-compose rm
Going to remove keycloak
Are you sure? [yN] y
Removing keycloak … done

※ここでdocker-compose.ymlを修正し、本番環境のイメージからコンテナが作られるようにして…
$ sudo docker-compose up

これで、本番環境の状態を復元できた。

永続化する対象をVolume指定する

さて…永続化する対象を決めるために、過去にいじったところを色々と考えてみた。

ディレクトリ永続化理由
/opt/jboss/keycloak/standalone/data/var/keycloak/dataH2データーベースはここに情報を保管している模様。
永続化する際のホスト側のディレクトリは、Discourseを参考にした。
/opt/jboss/keycloak/standalone/configurationしないKerberos認証の為にkeytabファイルを置いた場所。
コンテナが動き出してからファイルを置いても問題は発生しない。
/opt/jboss/keycloak/standalone/deploymentsしない拡張機能を置いた場所。
これも、コンテナが動き出してから置いても問題は発生しない。

マウント先はDiscourseを参考に /var/keycloak と考えたけれども、一般にVolumeの場合はそういったことは考えないで良いことが分かった。
Qiita / Dockerのvolumeとbind mountの違い

ただし、コンテナを作った後でディレクトリを永続化する場合には、ホスト側にディレクトリを用意して、そこにファイルをコピーしておく必要がある模様。
せろとにんぱわー. / 既に動いてるdockerコンテナのボリュームを後から永続化する

そうなると、永続化する際のディレクトリは指定せざるを得ない。

まず、/var/keycloak/data を作り、コンテナが停止した状態でディレクトリをまるごとコピーする。

$ sudo mkdir -p /var/keycloak/data
$ sudo docker cp -a keycloak:/opt/jboss/keycloak/standalone/data /var/keycloak

docker cp に -a パラメーターを付ければ属性を含めたコピーができていると思っていたが、上手くいかなかったので属性を修正。

$ sudo chown 1000:0 -R /var/keycloak/

docker-compose.yml にvolumes指定を追加する。

…
    entrypoint:
      - /opt/jboss/tools/docker-entrypoint.sh
    command:
      - -b
      - 0.0.0.0
    volumes:
      - /var/keycloak/data:/opt/jboss/keycloak/standalone/data

※最後の行に追加してみた。

コンテナを起動して様子を見る。

$ sudo docker-compose up

Keycloakは起動時にDBを触るらしく、keycloak.mv.dbの日付が変わっていた。
永続化が上手くいったことが分かった。

$ ll /var/keycloak/data/
total 5400
drwxrwxr-x 6 rohhie root    4096 May 23 21:45 ./
drwxr-xr-x 3 rohhie root    4096 May 23 18:59 ../
drwxrwxr-x 3 rohhie root    4096 May 23 21:45 content/
drwxrwxr-x 2 rohhie root    4096 Jun  2  2020 kernel/
-rw-r--r-- 1 rohhie root     146 May 23 21:45 keycloak.lock.db
-rw-r--r-- 1 rohhie root 4993024 May 23 21:45 keycloak.mv.db
-rw-r--r-- 1 rohhie root  503987 May 23 20:05 keycloak.trace.db
drwxr-xr-x 2 rohhie root    4096 Jul  5  2020 timer-service-data/
drwxr-xr-x 3 rohhie root    4096 Jul  5  2020 tx-object-store/

念のため中に入って確認してみたが、同じに見える。

$ sudo docker exec -u 0 -it keycloak /bin/bash --login
# ls -l /opt/jboss/keycloak/standalone/data/
total 5392
drwxrwxr-x 3 jboss root    4096 May 23 21:45 content
drwxrwxr-x 2 jboss root    4096 Jun  2  2020 kernel
-rw-r--r-- 1 jboss root     146 May 23 21:45 keycloak.lock.db
-rw-r--r-- 1 jboss root 4993024 May 23 21:45 keycloak.mv.db
-rw-r--r-- 1 jboss root  503987 May 23 20:05 keycloak.trace.db
drwxr-xr-x 2 jboss root    4096 Jul  5  2020 timer-service-data
drwxr-xr-x 3 jboss root    4096 Jul  5  2020 tx-object-store

上手くいっていそうなので、http://work.hogeserver.hogeddns.jpにアクセスして、動作を確かめた。

イメージを公式のものに差し替える

すぐに最新バージョンで試したいところだけれどもここは我慢。
まずは、公式にある現在と同じバージョン(10.0.2)のイメージからコンテナを生成し、問題なく動作することを確認しよう。

まずは、コンテナを削除する。

$ sudo docker-compose rm

docker-compose.ymlを書き換える。

version: "3.9"
services:

  keycloak:
    image: quay.io/keycloak/keycloak:10.0.2
    container_name: keycloak
    restart: always
    user: "1000"
    ports:
      - 8081:8080
    environment:
      PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      container: oci
      TZ: Asia/Tokyo
      KEYCLOAK_VERSION: 10.0.2
      JDBC_POSTGRES_VERSION: 42.2.5
      JDBC_MYSQL_VERSION: 8.0.19
      JDBC_MARIADB_VERSION: 2.5.4
      JDBC_MSSQL_VERSION: 7.4.1.jre11
      LAUNCH_JBOSS_IN_BACKGROUND: 1
      PROXY_ADDRESS_FORWARDING: "true"
      JBOSS_HOME: /opt/jboss/keycloak
      LANG: en_US.UTF-8
    entrypoint:
      - /opt/jboss/tools/docker-entrypoint.sh
    command:
      - -b
      - 0.0.0.0
    volumes:
      - /var/keycloak/data:/opt/jboss/keycloak/standalone/data

※ポートは標準に戻るので、8080に戻している。

コンテナを作成して起動。

$ sudo docker-compose up

これで、http://work.hogeserver.hogeddns.jp:8081/ にアクセスしたところ、問題なく動作した。
コンテナをinspectしてみたところ、Imageはquay.io/keycloak/keycloak:10.0.2となっており、上手く動いたことが確認できた。

イメージを新しいバージョンの公式イメージに置き換える

さぁ、新しいバージョンのKeycloakのイメージに差し替えよう!

ここにイメージが置いてある。
RED HAT Quay.io / Keycloak

今日(2021/05/23)から17日前に13.0.0がリリースされている。1ヶ月前には12.0.4がリリースされていた。
どれを使うのが良いのか判断に迷うが、SECURITY SCANをPASSしていて問題が枯れていそうな12.0.4を適用してみることにした。

コンテナを停止して、docker-compose.ymlを書き換える。

…
  keycloak:
    image: quay.io/keycloak/keycloak:12.0.4

コンテナを起動してみる。

$ sudo docker-compose up

イメージを見てみる。

$ sudo docker image ls
REPOSITORY                  TAG                 IMAGE ID       CREATED         SIZE
keycloak                    latest              7d67d3c96204   4 hours ago     780MB
quay.io/keycloak/keycloak   12.0.4              356dd8b00093   4 weeks ago     690MB
quay.io/keycloak/keycloak   10.0.2              20e7923ebde7   10 months ago   687MB

イメージが増えていることが確認できる。

http://work.hogeserver.hogeddns.jp:8081/ にアクセスしてログインし、サーバー情報を見たところ、12.0.4になっている。

12.0.4のイメージをinspectしてみたところ、環境変数が変わっていることが分かった。修正しなければ。
本来は先にイメージをPullし、環境変数を反映させてからdocker-compose upすべきなのだろう。ま、今回は動いたから良し。

docker-compose.yml

version: "3.9"
services:

  keycloak:
    image: quay.io/keycloak/keycloak:12.0.4
    container_name: keycloak
    restart: always
    user: "1000"
    ports:
      - 8081:8080
    environment:
      PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      container: oci
      TZ: Asia/Tokyo
      KEYCLOAK_VERSION: 12.0.4
      JDBC_POSTGRES_VERSION: 42.2.5
      JDBC_MYSQL_VERSION: 8.0.22
      JDBC_MARIADB_VERSION: 2.5.4
      JDBC_MSSQL_VERSION: 8.2.2.jre11
      LAUNCH_JBOSS_IN_BACKGROUND: 1
      PROXY_ADDRESS_FORWARDING: "true"
      JBOSS_HOME: /opt/jboss/keycloak
      LANG: en_US.UTF-8
    entrypoint:
      - /opt/jboss/tools/docker-entrypoint.sh
    command:
      - -b
      - 0.0.0.0
    volumes:
      - /var/keycloak/data:/opt/jboss/keycloak/standalone/data

修正後にupする。

$ sudo docker-compose up -d

※もう、これでコンテナの調整を終わらせるので、-dで環境変数の変更を反映させつつ、非同期でコンテナを起動する。

さぁ、最終コーナー。
過去記事で置いたkeytabを置き直す。

$ sudo chown 1000:0 temp.keytab
$ sudo chmod 660 temp.keytab
$ sudo docker cp -a temp.keytab keycloak:/opt/jboss/keycloak/standalone/configuration/

過去の記事で置いた拡張機能も置き直す。

$ sudo chown 1000:0 user-role-validator.jar
$ sudo chmod 664 user-role-validator.jar
$ sudo docker cp -a user-role-validator.jar keycloak:/opt/jboss/keycloak/standalone/deployments/

念のため、中に入って、狙い通りにファイルが置かれているか確認したところ、グループが上手く反映できていなかった…修正しておく。

$ sudo docker exec -u 0 -it keycloak /bin/bash --login
# ls -l /opt/jboss/keycloak/standalone/configuration/temp.keytab
-rw-rw---- 1 jboss 1000 842 Jun 27  2020 /opt/jboss/keycloak/standalone/configuration/temp.keytab
# ls -l /opt/jboss/keycloak/standalone/deployments/
-rw-rw-r-- 1 jboss 1000 7258 May  4 19:56 /opt/jboss/keycloak/standalone/deployments/user-role-validator.jar

# chown jboss:root /opt/jboss/keycloak/standalone/configuration/temp.keytab
# chown jboss:root /opt/jboss/keycloak/standalone/deployments/user-role-validator.jar

これで更新完了!

さいごに

まだ、自由自在とはいかない。

とはいえ、コンテナ間の連携ってどうなっているのか、永続化って何なのか、イメージをアップデートすることって何なのか、というところが分かってきた気がする。
このレベルでもある程度の運用はできそうな予感。

もう少し理解しておきたいのは、EntorypointとかCommand、aptが入っていないイメージで色々と自由にやるためにはどうしたらいいのか、というあたり。
分かってくると、だいぶ運用レベルが高められる気がする。

広告

コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他