8
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

KeycloakとGitLab Gitea CodiMD Wiki.js GROWI Mattermost rocket.chat Wekan TAIGA PENPOT NextCloudを連携してnginx-proxyで配信するSSOなWeb開発環境をdocker-composeで構築する

Last updated at Posted at 2021-03-19

image.png

いつの日かクラウドサービス使用不可案件が降ってくると信じて。1

概要

  • 選んで使える静的Webサイト/テンプレート開発用ブラウザアプリスイート
  • 数人~十数人程度での使用を想定
  • KeycloakでSSO化
  • nginx-proxyを使ってリバースプロキシの設定もdocker-compose.ymlに持たせる
  • SSL対応(自己署名にも対応)
  • アプリは原則として日本語対応のもので、できるだけ初期設定も日本語にする
  • 既製イメージを利用し自分ではDockerfileを書かない
  • イメージは今後も安定してリリースが継続されそうなものを選ぶ
  • 極力dockerリソースには名前をつける

成果物

  • スモークテストのみ実施
  • インストール手順等はリポジトリ内の docs/INSTALL_ja.md に概ね書いてあるため、本稿では方針や試行錯誤した点を扱う

作業環境

  • OS: RHEL8互換(今回はOL8)
    • SELinuxは切っておく
    • 作業はrootで行う
    • 一部のシェルスクリプトはRHEL8互換でないディストロでは動かないかも
  • CPU: 4コア
  • メモリ: 16GB
    • 8GB以上推奨(メモリ消費の多いものを使わないなら少なくても可)
  • ストレージ: 500GB (SSD)
    • 全て入れるとイメージだけで16GB強使用する
  • dockerとdocker-compose

対応アプリケーション

名称 種別
Keycloak SSO
GitLab Gitプラットフォーム
Gitea Gitプラットフォーム
CodiMD Markdownエディタ
Wiki.js wiki
GROWI wiki
Mattermost チャットツール
rocket.chat チャットツール
Wekan カンバン
TAIGA プロジェクト管理
PENPOT デザインプロトタイピング
NextCloud クラウドストレージ
  • 追加検討中
    • SynapseまたはDendrite+Element: Matrixサーバ+クライアント
    • Mailu: 全部入りメール環境
    • dnsmasq: DNSサーバ(踏み台構築用)
  • 選外
    • Zulip: Postgresに専用パッケージを入れる必要がある
    • OpenProject: SSO対応が有償版のみ
    • Restyaboard: SSO対応が有償版のみ, 日本語が微妙

全導入イメージ一覧

名称 種別 Port Project Name Alias Depends on Auth
Keycloak SSO Auto keycloak kc pg ID/Pass
GitLab Gitプラットフォーム Auto gitlab pg redis SAML
Gitea Gitプラットフォーム Auto gitea pg OIDC
CodiMD Markdownエディタ Auto codimd pg SAML
Wiki.js wiki Auto wikijs pg es SAML
GROWI wiki Auto growi mongo redis es SAML
Mattermost チャットツール Auto mattermost mm pg GitLab
rocket.chat チャットツール Auto rocketchat rc mongo SAML
Wekan カンバン Auto wekan mongo OIDC
TAIGA プロジェクト管理 Auto taiga pg rmq GitLab
PENPOT デザインプロトタイピング Auto penpot pg redis GitLab
NextCloud クラウドストレージ Auto nextcloud nc pg SAML
pgAdmin PostgreSQL WebUI Auto pgadmin pga pg
phpMyAdmin MariaDB WebUI Auto phpmyadmin pma maria
mongo-express MongoDB WebUI Auto mongo_express me mongo
RedisInsight Redis WebUI Auto redisinsight ri redis
ElasticHQ Elasticsearch WebUI Auto elastichq eshq es
PostgreSQL RDBMS 5432 postgres pg
MariaDB RDBMS 3306 mariadb maria
MongoDB NoSQL 27017 mongo
Redis KVS 6379 redis
Elasticsearch 全文検索 9200 elasticsearch es
RabbitMQ メッセージキューイング 5672 rabbitmq rmq
nginx-proxy Reverse Proxy 80,443 proxy
MailCatcher ダミーSMTPサーバ Auto mailcatcher smtp
Scope Docker WebUI 4040 scope
Portainer Docker WebUI 9000 portainer

使用バージョン/リポジトリ

名称 Tag Version Override Repository Tags
Keycloak latest 12.0.4 config quay.io Link
GitLab latest 13.9.3-ce.0 dockerhub Link
Gitea 1 1.13.4 dockerhub Link
CodiMD latest 2.3.2 dockerhub Link
Wiki.js 2 2.5.191 dockerhub Link
GROWI latest-nocdn 4.2.12-nocdn dockerhub Link
Mattermost latest 5.32.1 dockerhub Link
rocket.chat latest 3.12.1 dockerhub Link
Wekan latest v5.05 quay.io Link
TAIGA latest 6.x source dockerhub
PENPOT latest 1.3.0-alpha-1 source dockerhub
NextCloud 21-apache 21.0.0-apache (21.0.0.18) config dockerhub Link
pgAdmin latest 5.0 dockerhub Link
phpMyAdmin latest 5.1.0-apache dockerhub Link
mongo-express latest 0.54.0 dockerhub Link
RedisInsight latest 1.10.0 dockerhub Link
ElasticHQ latest v3.5.6 dockerhub Link
PostgreSQL 13-alpine 13.2-alpine dockerhub Link
MariaDB 10 10.5.9 dockerhub Link
MongoDB 4-bionic 4.4.4-bionic dockerhub Link
Redis 6-alpine 6.2.1-alpine dockerhub Link
Elasticsearch 6.8.14 6.8.14 elasticsearch Link
RabbitMQ 3-management-alpine 3.8.14-management-alpine dockerhub Link
nginx-proxy alpine 0.8.0 source dockerhub Link
MailCatcher latest dockerhub Link
Scope latest_release 1.13.1 dockerhub Link
Portainer alpine 1.24.1-alpine dockerhub Link

docker-composeプロジェクト構築

共通方針

プロジェクト名・サービス名・コンテナ名

  • プロジェクト名は必ず.envの COMPOSE_PROJECT_NAME で明示的に指定し、ディレクトリ名と一致させる
    • ハイフン・アンダースコア使用不可
  • プロジェクト内のメインとなるコンテナのサービス名とコンテナ名も違和感がなければ合わせる
  • container_nameは明示的に指定する
  • hostnameに転用する関係でcontainer_nameにはアンダースコア使用不可

hostname

  • 明示的に指定する
  • aliasがあるものは [alias]-server 、ないものは [container_name]-server を原則とする
  • アンダースコア使用不可

ports, expose

  • expose にコンテナ側のポートを指定する
  • コンテナ間ネットワークに繋がったnginx-proyxで配信するため ports は使用しない

volumes

  • 一方的にコンテナに送り込むファイル・ディレクトリは <project_root>/mount に配置する
    • オーバーライド用の設定ファイルや鍵など
    • git管理内とする
  • ホストとコンテナ双方で編集するか、ホストから頻繁に参照するディレクトリは <project_root>/volumes に配置する
    • 設定など
    • git管理外とする(雛形などがあるならgit管理内の別の場所に用意しておく)
  • 通常閲覧も編集もしないものは docker volume で予め作成しておく
    • データベースのデータディレクトリなど
    • 命名は [project_name]-<purpose> を原則とする
  • 勝手にvolumeが作られる場合は docker inspect して mounts の内容を確認する

networks

  • 原則として全てのコンテナはbridgeネットワーク docker.internal に繋げておく
  • 個別に必要な場合は名前をつける
    • ハイフン使用不可

logging

  • 標準では無制限のため理由がなければ予防的措置として全てのサービスに下記を設定しておく
logging:
  options:
    max-size: "10m"
    max-file: "3"

extra_hosts

  • テレメトリっぽいものや不要な外部アクセスを 192.0.2.0 に向けて遮断
  • KeycloakのアドレスをサーバのローカルIPに向ける
    • コンテナ内部からKeycloakへのアクセスを外に出さず、かつSSLでも通るように

ホスト上でのdocker-composeの操作

専用のMakefileを使用する。詳しくはMakafileのREADME参照。
もちろん普通にdocker-composeコマンドを打っても構わない。

コンテナ作成後はScopeやPortainerでブラウザ上から操作。

カテゴリ毎の方針

データベース等

PostgreSQL, MariaDB, MongoDB, Redis, RabbitMQ, ElasticSearch

  • コンテナ間ネットワークでのみ使用
  • rootユーザーはユーザー名 root パスワード root とする
    • PostgreSQL, MariaDB, MongoDB, RabbitMQで設定
  • Mongo, Redis, ElasticSearchは認証なし
  • 初期化は inidb.d を使用して初回起動時に自動で行う
    • RabbitMQはdocker-composeを使った初期化方法が分からないためWebUIから行う
    • RedisとElasticSearchは初期化不要
    • MongoDBはrocket.chatがレプリケーションを必要とするため独立した初期化処理が必要(シェルスクリプトで対応)

データベース用WebUI

pgAdmin, phpMyAdmin, mongo-express, RedisInsight, RabbitMQ (Built-in), ElasticHQ

  • ローカルネットワークからのアクセスのみ許可する
  • 具体的には 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 からのアクセスのみ許可
    • environmentに NETWORK_ACCESS=internal と書いておくとnginx-proxyが自動でやってくれる

サーバ

nginx-proxy, MailCatcher

  • 特に設定することはない

モニタリング

Scope, Portainer

  • nginx-proxyの管理下には置かない
  • ポート 40409000 をファイアーウォールで適切に制限する
  • ブラウザ経由でコンテナにフルアクセスできるため絶対に外部に公開しないこと

アプリケーション

Keycloak, GitLab, Gitea, CodiMD, Wiki.js, GROWI, Mattermost, rocket.chat, Wekan, TAIGA, PENPOT, NextCloud

  • 管理者アカウントはユーザー名 webmaster , パスワード Pa55w@rd , メールアドレス webmaster@<DOMAIN> とする
    • ものによっては admin が使えない → 統一しておきたいので webmaster としておく

その他

SSO

各アプリの認証方式と、「Keycloak上のユーザープロパティ/属性」と「アプリのユーザー情報」のマッピングについては事前調査の記事を参照のこと。

アプリケーション毎の設定方法についてはリポジトリの各アプリのディレクトリにある INSTALL_ja.md を参照のこと。

Gitea対策

上記の調査にある「Keycloakのユーザー属性に nickname が存在するとGiteaが問答無用で使おうとする問題」については、Giteaのソースを大幅に修正する以外に解決方法がなさそうなため、ユーザー属性には nickname を使用しないことにした。
表示名を格納するユーザー属性は displayName としてマッピングで対処する。

TAIGAのソース修正

TAIGAの公式Dockerイメージに同梱されているGitLab OAuth2用の taiga-contrib-gitlab-auth プラグインの実装に問題があり、Keycloakと連携するにはソースの修正が必要だった。

具体的にはrequests.postに渡すデータの型が param (クエリパラメータ)になっており、これを data に修正する。(該当箇所のソース

PENPOTのソース修正

PENPOTの使用しているhttp実装はhttpステータスコード307によるPOSTリクエストのリダイレクトに対応しておらず、Keycloakコンテナ上のGitLabのエンドポイントに対するアクセスをKeycloakのエンドポイントにリダイレクトすることができないため、ソースの修正が必要だった。

具体的にはハードコーディングされているGitLab OAuth2エンドポイントのパスを、KeycloakのOpenID Connectエンドポイントのものに書き換えればよい。(該当箇所のソース

SSL対応

nginx-proxyが各docker-compose.ymlのenvironmentを見てよしなにやってくれる。

各アプリケーションのenvironmentに記述するnginx-proxy用の設定項目のうち、SSLに関連する設定項目の有無を見て自動で構成してくれる模様。詳しい条件はconf出力用のテンプレートを読めば書いてある。

SHWでは SSL_POLICY の有無で分岐させている。

自己署名認証局

ホスト上で認証局の証明書を然るべきディレクトリに配置し update-ca-trust で登録すると、PEMだけでなくJavaやEDK2用のバイナリなど各種フォーマットのCAバンドルが自動で生成される。

生成したCAバンドルを必要に応じてコンテナにマウントすることで、既製イメージ内のOS、Python、Java等に任意の認証局を追加できる。( update-ca-certificates とか keytool -importcert -trustcacerts -file ca.crt -cacerts -storepass changeit -alias self-sign -noprompt とかやらなくて済む)

なお、証明書と鍵の作成には下記記事のものを使用した。

サーバの証明書と秘密鍵はnginx-proxyが使用するため、マウント用ディレクトリにコピーする。
一連の作業はシェルスクリプトで実行できるようにした。詳しくは setup/*selfsigncert.sh を参照のこと。

インストール用シェルスクリプト

サーバのローカルIP・ドメイン・SSLの使用有無・言語・タイムゾーンといった設定項目は関係するファイル全般に反映する必要があるが、対象が――

  • docker-compose.yml
  • volumesでマウントする各アプリ用の設定ファイルや修正を加えたソース
    • jsonとかphpとかpythonとかclojureとか色々
  • nginx-proxy用設定ファイルのファイル名
    • ドメイン名とファイル名を照合して取捨選択する仕組みのため

――と多岐に渡るため、予め設定部分を置換用文字列にしておき、シェルスクリプトで設定ファイルに従って置換する方法を採った。
処理の内訳は docs/INSTALL_ja.md に詳しく書いてある。

コンテナのタイムゾーン統一

イメージによって tzdata が入っていたり入っていなかったりするため、environmentで TZ=Asia/Tokyo を指定しても日本時間にならないものがある。
全てのコンテナに TZ=Asia/Tokyo を設定してdateコマンドを打ってみたところ、全34コンテナ中21個がJST、11個がUTC、2個がAsia(時刻はUTC)となった。

要はtzdataのAsia/Tokyo用のバイナリがコンテナ内に存在していればいい訳で、ホスト上の /usr/share/zoneinfo/Asia/Tokyo をそのまま read-only でコンテナにマウントすることにした。

docker-compose.yml

environment:
  - TZ=Asia/Tokyo
volumes:
  - /usr/share/zoneinfo/Asia/Tokyo:/usr/share/zoneinfo/Asia/Tokyo:ro

Asia/Tokyo は置換用文字列 <TZ> にしておき、インストール用シェルスクリプトの一括置換対象とする。

ToDo

  • アプリのUI上の時刻表示が日本時間になっているか確認する
  • docsの整備
  • production用に使用するバージョンを固定したものも欲しい
  1. Dockerもdocker-composeもなんならLinuxも初学者なので多少の粗はご容赦ください

8
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?