DockerでApicurio Studioをホスティングした


Apicurio Studio使ってますか。
私は先日使い始めました。
まだ良くわかっていません。

Dockerでホスティングしたのですが、
その道が想像以上に険しかったので、あとに続く人のために遺しておきます。

Apicurio Studioとは?

Apicurio Studio(アピクリオ・スタジオ)はApicurioプロジェクトのひとつで、
OSSのOpenAPI設計ツールです。
OpenAPIのツールといえばSwaggerが有名ですが、
複数人で作業するとなると有料プランを利用しないといけません。
Swagger以外にもツールはあるそうですが、結構有料のものばかり(くわしくはこちら)。
業務ならまだしも、趣味開発では支出を避けたいところです。

そこで、OSSのApicurio Studioを知りました。
無料というだけでなく、WebのGUIベースの操作で設計できるのも魅力じゃないでしょうか。
モックやテストといった機能はまだなくて後日追加予定らしいですが、タダなら試してみる価値はあると思います。
活発さはぼちぼちです。

運用方法

Apicurio Studioを使うには次の3つの方法があります。

  1. 公式がお試し用として配信しているLiveバージョンを使う
  2. ローカルマシンでホスティングする
  3. Dockerでホスティングする

2はダウンロードしてすぐ使えるスクリプト込の「クイックスタート」が楽だと思います。
3もdocker-composeを簡単に実行できるスクリプトがGitHubにあります。

本格運用するなら2か3でしょうが、私はサーバー群をdocker-composeで運用しているので、Apicurio StudioもDockerで立てようと思います。
さらに、上記で述べたGitHubで公開されているスクリプトではDBやらURLの融通が聞かないので、自前でやろうと思います。

ちなみに、公式ドキュメントはあまり親切ではありません。
Dockerイメージのページにある説明も簡素なもので、結構試行錯誤しました。
現状動いているので大丈夫だとは思いますが、なにか間違っていればコメントでご指摘いただけると幸いです。

アーキテクチャ

Apicurio StudioをDockerで運用するには、アーキテクチャの理解が不可欠です。
1サービスとは思えない構造で、4つのイメージから成っています。

図はOpenShiftと書いてありますが、Dockerでも同じです。

図内の表記 イメージ名 役割
Angular based UI application, Apicurio Studio UI Component apicurio-studio-ui フロントエンド
Apicurio Studio API Component apicurio-studio-api バックエンド
Apicurio Studio WebSocket Component apicurio-studio-ws 編集画面の同期用WebSocket
KEYCLOAK apicurio-studio-auth ユーザー認証

この構成にならってもいいんですが、
この中のapicurio-studio-authはDBがH2限定なんで、KEYCLOAKは別途イメージから作ろうと思います。
よって、今回作るのは以下のような構成になります。

イメージ コンテナ名
postgres pg
nginx deploy
jboss/keycloak keycloak
apicurio/apicurio-studio-ui apicurio-ui
apicurio/apicurio-studio-api apicurio-api
apicurio/apicurio-studio-ws apicurio-ws

ドメインはこの記事ではexample.comとします。

docker-composeの設定

以下のdocker-compose.ymlファイルでコンテナを起動します。
起動時にDBの初期化があるので、pgを先に起動し、設定したあとで他のコンテナを起動します。

docker-compose.yml
version: '3'                                              

services:
    pg:
        image: postgres
        restart: always
        environment:
            POSTGRES_USER: xxxx
            POSTGRES_PASSWORD: xxxxxx
        volumes:
            

    deploy:                                               
        image: nginx                                      
        restart: always                                   
        ports:
            - 80:80
            - 443:443
        volumes:
            

    keycloak:
        image: jboss/keycloak
        restart: always
        environment:
            DB_VENDOR: postgres
            DB_ADDR: pg
            DB_PORT: 5432
            DB_DATABASE: keycloak
            DB_USER: xxxx
            DB_PASSWORD: xxxxxx
            KEYCLOAK_USER: admin
            KEYCLOAK_PASSWORD: XXXXXX
        volumes:
            

    apicurio-api:
        image: apicurio/apicurio-studio-api
        restart: always
        environment:
            APICURIO_KC_AUTH_URL: https://keycloak.example.com/auth/
            APICURIO_HUB_STORAGE_JDBC_TYPE: postgresql9
            APICURIO_DB_DRIVER_NAME: postgresql
            APICURIO_DB_CONNECTION_URL: jdbc:postgresql://pg:5432/apicurio
            APICURIO_DB_USER_NAME: xxxx
            APICURIO_DB_PASSWORD: xxxxxx
            APICURIO_DB_INITIALIZE: "true"
            APICURIO_HUB_STORAGE_JDBC_INIT: "true"
        depends_on:
            - pg
            - apicurio-ws

    apicurio-ws:
        image: apicurio/apicurio-studio-ws
        restart: always
        environment:
            APICURIO_KC_AUTH_URL: https://keycloak.example.com/auth/
            APICURIO_HUB_STORAGE_JDBC_TYPE: postgresql9
            APICURIO_DB_DRIVER_NAME: postgresql
            APICURIO_DB_CONNECTION_URL: jdbc:postgresql://pg:5432/apicurio
            APICURIO_DB_USER_NAME: xxxx
            APICURIO_DB_PASSWORD: xxxxxx
            APICURIO_DB_INITIALIZE: "true"
            APICURIO_HUB_STORAGE_JDBC_INIT: "true"
        depends_on:
            - pg

    apicurio-ui:
        image: apicurio/apicurio-studio-ui
        restart: always
        environment:
            APICURIO_KC_AUTH_URL: https://keycloak.example.com/auth/
            APICURIO_UI_HUB_API_URL: https://apicurio-api.example.com
            APICURIO_UI_EDITING_URL: wss://apicurio-ws.example.com
        depends_on:
            - pg
            - apicurio-api
            - apicurio-ws

postgreSQLの設定

keycloakとApicurio Studioで使うデータベースを作成しておきます。

データベースの作成
create database keycloak;
create database apicurio;

nginxの設定

Apicurio StudioはJavaScriptでAPIやWebSocketにアクセスするので、
複数のコンテナすべてのポートをホストのポートとバインドする必要があります。
でもそんなにいくつもポートを使っていると、何番が何だったとか、ポートフォワーディングの設定が大変なので、
リバースプロキシを挟んでおきます。
nginxコンテナの80と443だけをホストとバインドし、すべてのWeb通信はnginxを通します。

リバースプロキシを設定して、docker-compose.yml内に記述したURLでそれぞれアクセスできるようにします。
※常時SSL設定などは省略しています。

nginx_apicurio.conf
# keycloak
server {
    listen       443 ssl;
    listen [::]:443 ssl;
    server_name  keycloak.example.com;

    location / {
        include /etc/nginx/params/proxy_params;
        proxy_pass https://keycloak:8443;
    }
}

# ui
server {
    listen       443 ssl;
    listen [::]:443 ssl;
    server_name  apicurio.example.com;

    location / {
        include /etc/nginx/params/proxy_params;
        proxy_pass http://apicurio-ui:8080;
    }

    location /studio {
        return 301 https://$host;
    }
}

# api
server {
    listen       443 ssl;
    listen [::]:443 ssl;
    server_name  apicurio-api.example.com;

    location / {
        include /etc/nginx/params/proxy_params;
        proxy_pass http://apicurio-api:8080;
    }
}

# ws
server {
    listen       443 ssl;
    listen [::]:443 ssl;
    server_name  apicurio-ws.example.com;

    location / {
        include /etc/nginx/params/proxy_params;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://apicurio-ws:8080;
    }
}

Keycloakの設定

Keycloakはシングルサインオンを提供するOSSです。
予めアプリケーションを登録しておき、
アプリケーションからKeycloakにリダイレクト、認証したらKeycloakからアプリケーションにリダイレクトすることで、ログイン情報を認証します。

Keycloakにアプリケーションを登録するには、realmと呼ばれるプロジェクトのようなもの、clientと呼ばれるアプリケーションを作成する必要があります。
設定項目が多くて大変なので、設定済みのものを拝借しましょう。

apicurio-studio-authからの設定エクスポート

上記apicurio-studio-authイメージには諸々設定済みのKeycloakが用意されています。
なので、apicurio-studio-authイメージでコンテナを起動し、Apicurioのrealm情報をエクスポートし、今回用意したKeycloakにインポートすればいいです。

まずはコンテナを起動します。
8080ポートに接続できるようにし、管理画面へのログイン情報を環境変数で渡しておきます。

コンテナの起動
docker run -it -p 8080:8080 \
-e "APICURIO_KEYCLOAK_USER=admin" \
-e "APICURIO_KEYCLOAK_PASSWORD=admin" \
-e "APICURIO_UI_URL=https://apicurio.example.com/" \
apicurio/apicurio-studio-auth

起動したら、ブラウザでhttp://localhost:8080/auth/にアクセスしてログインします。
上記コマンドで起動した場合、ID:admin、password:adminでログインします。
左上でApicurioが選択されていることを確認し、最下部のExportをクリックします。

(一応)2つの項目をONにし、Exportを押します。
しばらくするとjsonファイルがダウンロードできます。

realmのインポート

先程ダウンロードしたjsonを今回用意するKeycloakにインポートします。
コンテナが起動したら、ブラウザでhttps://keycloak.example.com/auth/にアクセスし、ログインします。

「Master」というデフォルトのrealmが選択されているはずなので、「Add realm」から先程のjsonをインポートします。

ログインできるよう設定

ログインページの形式を決めます。

設定完了(のはず)

https://apicurio.example.comにアクセスすると、ログイン画面が表示されます。

ユーザー登録をするとログインできます。
APIの追加、編集をしてみて、動けば成功です。
失敗しててもめげずに、あれこれいじってみてください。
ブラウザのコンソール、各コンテナのログを見れば解決できると思います。

間違えても簡単にやり直せます。Dockerならね。