intra-martが起動するDockerコンテナを作成する。alpineで。

# 概要

[intra-martが起動するDockerコンテナを作成する](http://qiita.com/myyasuda/items/9507018483dd6f8728fc) にinspire the nextされ、ムシャクシャしてやってみた。

[intra-mart](http://www.intra-mart.jp/) の環境をDockerコンテナ上に構築します。

軽量と噂のalpineで。ubuntuならapt-getでresinが入るご時世なのにね。

今回目指すイメージは以下のような感じです。
- 「/imart/login」で、作成したテナント管理者でログインできるところまでを確認します。
-  imart.warは、外から渡せるようにします。
-  データベースは別に立てたコンテナのものを利用します。
-  Webサーバ（Apacheとか）は用意しません。
-  IMBoxとIM-ContentSearchは入れないものとします。(CassandraやSolrが必要なため）

試した各アプリケーションのバージョンです。

| application | version | 説明  |
|:-------------|---------:|:------|
| Resin Pro | 4.0.48 | 本家が配布しているものを利用します。|
| OpenJDK   | 1.8.0_92 | apkでインストールされるものを利用します。|
| intra-mart | 8.0.13(Maxima) | 2016 Springを利用します。|	
| PostgreSQL | 9.5.3 | DockerHubで配布されているlatestを利用します。|

**注1 [システム要件](http://www.intra-mart.jp/download/product/iap/iap_release_note/texts/support_environment/index.html)を100%満たしていないが、そこは不問とする。割り切った関係が大事です。**


**注2　本家のresin-proにはlicenseが含まれていないため、自分でlicenseを入れる必要があります。入れなくても３０日ぐらいは動くらしい**

**注3 Oracleじゃなきゃダメなintra-mart上で動くアプリケーションは、見なかったことにする。**

# 事前に用意しておくもの

- imart.war
- postgresのjdbcドライバ (postgresql-9.4.1208.jar)

[intra-mart Accel シリーズ TRY版 ダウンロード](http://www.intra-mart.jp/download/try/accel/)からIM-Jugglingツールをダウンロードして、
warファイルを作成します。

手順の詳細は、[インスパイア元](http://qiita.com/myyasuda/items/9507018483dd6f8728fc)に記載があるので、そちらを参照されたい。

## resin-web.xmlについて

preparedStatementCacheQueriesの値を0とか8とか小さい値にしていないと、テナントのセットアップ時にエラーが出て泣けることになります。

[本家のマニュアル](http://www.intra-mart.jp/download/product/iap/setup/iap_setup_guide/texts/create_war/configuration_file_datasource.html#common-postgresql)では、20を指定している例が提示されているけど、これだとエラーになった。

参考　[intra-martのテナント環境セットアップ時にjava.sql.SQLExceptionが発生したときの対策](http://qiita.com/myyasuda/items/4e656b3de993690db68a)

```xml

<database jndi-name="jdbc/default">
		<driver>
			<type>org.postgresql.Driver</type>
			<url>jdbc:postgresql://postgres:5432/iap_db</url>
			<user>imart</user>
			<password>imart</password>
			<init-param>
				<param-name>preparedStatementCacheQueries</param-name>
				<param-value>8</param-value>
			</init-param>
		</driver>
		<max-connections>20</max-connections>
		<prepared-statement-cache-size>8</prepared-statement-cache-size>
	</database>
```

# Dockerビルド用のファイルを作成


## Dockerfile

以下のようなDockerfileを書きました。
javaさえあればいいんだろ、という甘い考えは、resinのmakeの段階で打ち砕かれます。
また、jni.hもmake時に必要です。なので、resinのmake後に、必要でなくなったタイミングでapk delで消します。（ダイエットのため）

[alpineのサイト](https://pkgs.alpinelinux.org/packages)で、必要とされるファイル、それが含まれるパッケージを探します。

```Dockerfile

FROM alpine:3.4

ENV RESIN_VERSION 4.0.48
ENV RESIN_HOME /opt/resin-pro-${RESIN_VERSION}
ENV JAVA_HOME /usr/lib/jvm/java-1.8-openjdk

RUN apk add --virtual=build-dependencies --no-cache g++ libstdc++ linux-headers make wget ca-certificates && \
    apk add --no-cache openjdk8 && \
    ALPINE_GLIBC_BASE_URL="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" && \
    ALPINE_GLIBC_PACKAGE_VERSION="2.23-r3" && \
    ALPINE_GLIBC_BASE_PACKAGE_FILENAME="glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    ALPINE_GLIBC_BIN_PACKAGE_FILENAME="glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    ALPINE_GLIBC_I18N_PACKAGE_FILENAME="glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    wget \
        "https://raw.githubusercontent.com/andyshinn/alpine-pkg-glibc/master/sgerrand.rsa.pub" \
        -O "/etc/apk/keys/sgerrand.rsa.pub" && \
    wget \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
    apk add --no-cache \
        "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
    \
    rm "/etc/apk/keys/sgerrand.rsa.pub" && \
    /usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 C.UTF-8 || true && \
    echo "export LANG=C.UTF-8" > /etc/profile.d/locale.sh && \
    \
    apk del glibc-i18n && \
    \
    rm "/root/.wget-hsts" && \
    rm \
        "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME"

ENV LANG=C.UTF-8

RUN wget http://caucho.com/download/resin-pro-${RESIN_VERSION}.tar.gz -P /usr/local && \
    cd /usr/local && \
    tar xvzf resin-pro-${RESIN_VERSION}.tar.gz && \
    rm -f resin-pro-${RESIN_VERSION}.tar.gz && \
    cd resin-pro-${RESIN_VERSION} && \
    ./configure --prefix=/opt/resin-pro-${RESIN_VERSION} --enable-64bit && \
    make && \
    make install && \
    rm -rf /usr/local/resin-pro-4.0.48 && \
    ln -s /opt/resin-pro-${RESIN_VERSION} /opt/resin && \
    apk del build-dependencies 

    
EXPOSE 8080

ENTRYPOINT ["/opt/resin/bin/resinctl"," -server", "app-0", " start-with-foreground"]


```

本当はresin.propertiesなどを適切に編集する必要があるけど、動作確認レベルではなくても何とかなります。
割り切って先に進むことにします。


## Dockerイメージのビルド

Dockerビルドを実行しイメージを作成します。

```
docker build -t imart-base:4.0.48 .
```

# PostgreSQLの準備

## イメージの取得＆起動

```
docker run --name postgres -d -e PGPASSWORD=postgres -e POSTGRES_USER=postgres -p 5432:5432 postgres:latest
```

現時点でのlatestは9.5.3とのこと。

## intra-martが接続するロールの作成

[データベースとログインロールの作成](http://www.intra-mart.jp/download/product/iap/setup/iap_setup_guide/texts/install/common/database.html#id6)を参照して、ロールを作ります。

今回はPostgreSQLもコンテナなので、こんな感じでやってみました。

まず、コンテナに接続。

```
docker exec -it postgres bash
```

PostgreSQLにつないで。

```
psql -U postgres
```

ロールとデータベースを作る。

```
postgres=# CREATE ROLE imart WITH LOGIN PASSWORD 'imart';
CREATE ROLE

postgres=# CREATE DATABASE iap_db OWNER imart ENCODING 'utf8';   
CREATE DATABASE
```


# resinのコンテナを起動する

まず、事前に用意したファイルが以下のようにあると仮定します。

- /home/intramart/war/*.war (IM-Jugglingで作成したwarファイル)
- /home/intramart/lib/*.jar (JDBCドライバ）

これをdocker runするときにマウントして渡すことにします。

先に立てたPostgreSQLは--linkで渡しておきます。
```
docker run -it -d --name intra -p 8080:8080 --link postgres:postgres -v /home/intramart/war/:/opt/resin/webapps -v /home/intramart/lib/:/opt/resin/webapp-jars imart-base:4.0.48
```

しばらくすると、warファイルの展開がなされ、resinが起動します。


# テナントセットアップとログインの確認

以下にアクセスすると、初期設定画面が出てきます。ウィザードに従って進みます。
```
http://<Dockerのホスト>:8080/imart/system/login
```

この後、システム管理者でログインすると、以下のような画面になります。

![システム管理者ホーム.png](https://qiita-image-store.s3.amazonaws.com/0/111676/ea5159f6-7184-255b-0e5e-9a2e90c9fe41.png)


以下にアクセスし、テナント管理者でもログインできることを確認します。

```
http://<Dockerのホスト>:8080/imart/login
```
![ポータル.png](https://qiita-image-store.s3.amazonaws.com/0/111676/cf470c39-8f56-9122-8bbd-2551d82320d2.png)




# おまけ


Resinの入ったコンテナのイメージサイズ

| 場所 | サイズ |
|:--|--:|
|Ubuntu(ビルドしている環境) | 337.3MB |
|Gitlab Registry | 123 MB |

DockerのホストはUbuntu 16。　もう少し削れるかもしれない。

![Container Registry.png](https://qiita-image-store.s3.amazonaws.com/0/111676/0bd246a1-4e4b-7d3c-971c-fe93ec2bf30c.png)