i-Vinci TechBlog
株式会社i-Vinciの技術ブログ

war ファイルをタブレット端末で動作確認せよの巻

皆さんこんにちは。

モンスタハンターサンブレイクの攻略で忙しい i-Vinci 下位です。
日々寝る間も惜しんで狩りに励んでおります。爆撃機を落とすのは楽しいなぁ

さて、ここは技術ブログの場なので狩りの話ばかりしている訳にも行きません。
本日は war ファイルの動作確認で困った話をお届けします。

war ファイルとは

war ファイルとは、Java で構築された Web アプリケーションをパッケージ化したものです。
Web アーカイブファイルとも呼ばれています。

色々端折って言えば、war と アプリケーションサーバーがあれば、Web アプリケーションが公開可能です。
※詳細はこちらを参照。

やりたいこと

本日の目的です。

war ファイルの動作確認をしないといけません。
war ファイルを Web アプリとして展開するにはアプリケーションサーバーが必要です。

ついでにタブレットでの動作確認も必要です。

こんな時はオープンソースの強い味方、tomcat 先生 を頼ります。
Docker を使用してさくっと環境構築してしまいましょう。

さくっと war ファイルを展開する

tomcat 公式はDocker イメージを配布しています。是非利用しましょう。

こんな感じのディレクトリツリーを作成します。

tomcat
└── demo-0.0.1-SNAPSHOT.war

デプロイコマンドを実行します。
下記ディレクトリに war を配置すれば Web アプリケーションを展開してくれるそうです。素敵ですね!

/usr/local/tomcat/webapps/

下記コマンドでさくっとデプロイします。

docker run --rm -it -v $PWD/tomcat/demo-0.0.1-SNAPSHOT.war:/usr/local/tomcat/webapps/demo.war -p 8080:8080 tomcat:9

PC画面

おーけー。デプロイできました。
今回の検証 war はカメラ機能を使用した Web アプリケーションの様ですね。

因みにですが localhost は自端末専用です。タブレットはアクセスできません。
Docker の p(publish) オプションで指定したポートは外部公開されるので、稼働端末 IP にタブレットで接続しましょう。

こんな感じ
http://${端末IP}:8080/demo

これで稼働確認終わりですね。定時退社は固い。そう思ったそこの貴方。
ところがどっこいタブレット端末だとカメラが動きません。なんでや!

タブレット

タブレットだと動かない事案

タブレット端末だと動きませんでした。
期待通りに動作しなかった以上、次にやるべきことは決まりましたね。
そう、残業申請原因調査です。

いきなり答えですが、安全なコンテキスト専用の JavascriptAPI を使用しているから、になります。
参考:MediaDevices.getUserMedia

カメラは HTTPS でないと許可できない、ということです。えーそんなぁ。
(※localhost は特例として許可されているドメインになります。)

まぁでも知らない間に盗撮とかされたら怖いですし、使用の前提条件を固めるのは良いことですね。はい。

安全なコンテキストを突破せよ

ではタブレットで動作確認する為の方策を考えましょう。
相手が別 PC なら hosts を書き換えて終わりですが、タブレットは root 昇格でもしないと無理です。
簡単な検証で高級文鎮錬成のリスクを負うのは誰も望んでいません。

ということで、今回取る手段はこちらです。

  1. 自環境向けのなんちゃって HTTPS 証明書を作成
  2. HTTPS 証明書を tomcat に組み込み
  3. tomcat で HTTPS ポートを開放

では作業開始です。

自環境向けのなんちゃって HTTPS 証明書を作成

HTTPS を使うには証明書が必要です。
今回は動作検証だけをしたいので、使い捨ての自己証明書を使います。

keytool コマンドで作成しましょう。
入力情報は今回に限り適当です。

keytool -genkeypair -keyalg RSA -keypass testtest -storepass testtest -keystore keystore.jks

入力イメージ

keytool がありません。と空を仰ぐそこの貴方。
Docker 先生を信じるのです。Docker 先生に用意できない環境はありません。多分。

# tomcatコンテナの中にkeytoolが入っているので流用しちゃいましょう。
# 下記コマンドでworkディレクトリをマウント、workの中でkeytoolコマンドを使えばホストに成果物をもってこれます
docker run --rm -it -v $PWD/work:/work --workdir /work tomcat:9 bash

# ワンライナーで差をつけたい貴方には此方。
docker run --rm -it -v $PWD/work:/work --workdir /work tomcat:9 keytool -genkeypair -keyalg RSA -keypass testtest -storepass testtest -keystore keystore.jks

HTTPS 証明書を tomcat に組み込み

前項で作成した証明書を tomcat に組み込みます。
server.xml を書きましょう。そして Docker 環境上の tomcat に上書きします。

元ファイルは Docker 環境の下記ディレクトリから回収します。

/usr/local/tomcat/conf/server.xml

下記コマンドでクリップボードに複写しましょう。

# mac
docker exec -it ${tomcat-container-id} cat /usr/local/tomcat/conf/server.xml | pbcopy

# windows
docker exec -it ${tomcat-container-id} cat /usr/local/tomcat/conf/server.xml | clip

# linux -> xselをうまく使いましょう

取得した XML を編集します。
まずは追加する行です。

<!-- Server->Serviceの階層に一行記載を追加してください。-->
<!-- keystore*の属性は前項で入力したものと合わせる必要があります。 -->
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystorePass="testtest" keystoreFile="/ca/keystore.jks" />

追加した後の全体像です。
尚、tomcat コンテナより取得できる XML からコメントを除外したものになります。

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

    <!-- ここが追加先です。 -->
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystorePass="testtest" keystoreFile="/ca/keystore.jks" />

    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>

tomcat で HTTPS を開放

準備は整いました。
最後に tomcat で HTTPS を開放します。

前項で作成したファイルを Docker 環境に反映させましょう。
ディレクトリツリーを作ります。

tomcat
├── demo-0.0.1-SNAPSHOT.war
├── keystore.jks
└── server.xml

tomcat 起動・デプロイです。

docker run --rm -it -v $PWD/tomcat/demo-0.0.1-SNAPSHOT.war:/usr/local/tomcat/webapps/demo.war -v $PWD/tomcat/keystore.jks:/ca/keystore.jks -v $PWD/tomcat/server.xml:/usr/local/tomcat/conf/server.xml -p 8080:8080 -p 8443:8443 tomcat:9

HTTPS で表示できるようになりました。(加工が面倒なので一時的にカメラを OFF にしています)
タブレットも良さそうです。素晴らしい。
※仮想タブレットでは自己証明書サイトの表示ができなかったので Chrome の入った端末で検証。

pc-picture2

tablet-picture

まとめ

無事、war ファイルの動作確認を行うことができました。
今回は HTTPS 必須の API が含まれていたので難航しましたが、普通の war ファイルなら tomcat コンテナ 1 つで完結します。

皆さんも Docker 使いましょう!

以上、war ファイルの動作確認で困った話でした。

Docker 販促記事になったような気もするけどたぶん気のせい。