intra-mart WebPlatform 7.2 の Docker を作成する
この CookBook では、intra-mart WebPlatform 7.2 の Docker の作成手順について紹介しています。
レシピ
- ベースイメージの作成
- intra-mart WebPlatform 7.2 の Docker イメージを作成します
- 実行します
1. ベースイメージの作成
CentOS 5.11 を使用します。
Dockerfile
FROM centos:centos5.11
EXPOSE 22
ENV DEBIAN_FRONTEND noninteractive
# CentOS-Base.repo
COPY CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo
# yum
RUN yum clean all && yum -y update
# locale
RUN yum reinstall -y glibc-common
RUN localedef -i ja_JP -f UTF-8 ja_JP.utf8
RUN touch /etc/sysconfig/i18n
RUN echo 'LANG="ja_JP.UTF-8"' >> /etc/sysconfig/i18n
ENV LANG ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
# timezone
RUN yum install -y tzdata
RUN echo 'ZONE="Asia/Tokyo"' > /etc/sysconfig/clock
RUN echo 'UTC=false' >> /etc/sysconfig/clock
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
# tools
RUN yum groupinstall -y 'Development Tools'
RUN yum install -y wget curl vim emacs tar unzip mlocate perl ssh openssh-server openssl-devel
# root passwd
RUN bash -c 'echo "root:password" | chpasswd'
# ssh
RUN sed -i -e "s/#PasswordAuthentication yes/PasswordAuthentication yes/g" /etc/ssh/sshd_config
RUN sed -i -e "s/#PermitRootLogin yes/PermitRootLogin yes/g" /etc/ssh/sshd_config
RUN sed -i -e "s/UsePAM yes/UsePAM no/g" /etc/ssh/sshd_config
RUN updatedb
CMD /etc/init.d/sshd restart && /bin/bash
CentOS-Base.repo
# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client. You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the
# remarked out baseurl= line instead.
#
#
[base]
name=CentOS-$releasever - Base
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
baseurl=http://vault.centos.org/5.11/os/x86_64/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
#released updates
[updates]
name=CentOS-$releasever - Updates
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
baseurl=http://vault.centos.org/5.11/updates/x86_64/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras
baseurl=http://vault.centos.org/5.11/extras/x86_64/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus
baseurl=http://mirror.centos.org/centos/5.11/centosplus/x86_64/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
#contrib - packages by Centos Users
[contrib]
name=CentOS-$releasever - Contrib
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contrib
baseurl=http://mirror.centos.org/centos/5.11/contrib/x86_64/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
[libselinux]
name=CentOS-5 - libselinux
baseurl=http://vault.centos.org/5.11/centosplus/x86_64/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
includepkgs=libselinux*
ロケールを ja_JP, タイムゾーンを Asia/Tokyo に変更し、root/password で ssh 接続ができるように設定します。
また、そのままでは yum が利用できないため、リポジトリの参照先を http://vault.centos.org に変更しています(CentOS-Base.repo)。
参考:Yum update error on CentOS 5.6
mycentos:5.11 というタグでビルドします。
docker build -t mycentos:5.11 .
2. intra-mart WebPlatform の Docker イメージを作成します
先ほど作成したベースイメージを利用します。
jdk-6u45-linux-x64.bin を事前にダウンロードしておきます。
entrykit_0.4.0_Linux_x86_64.tgz を事前にダウンロードしておきます。
iWP 7.2 の setup.jar も事前に準備しておきます。
また、事前に java -jar setup.jar -s iwp7.2.0.install
を実行して保存したサイレントインストール用のファイル(iwp7.2.0.install)を準備しておきます。
サイレントインストールについては intra-mart WebPlatform をサイレントインストールする方法を参照してください。
さらに、以下のように data-source.xml, http.xml を事前に用意しておきます。
Dockerfile
FROM mycentos:5.11
EXPOSE 22 8080 9009
ENV DEBIAN_FRONTEND noninteractive
# yum
RUN yum -y update && yum clean all
RUN yum -y upgrade && yum -y update && yum clean all
# JDK
COPY jdk-6u45-linux-x64.bin /jdk-6u45-linux-x64.bin
COPY setup_jdk.sh /setup_jdk.sh
RUN chmod u+x /setup_jdk.sh
RUN /setup_jdk.sh
RUN rm -f /setup_jdk.sh
ENV JAVA_HOME /usr/local/java/jdk
ENV PATH /usr/local/java/jdk/bin:$PATH
RUN echo 'JAVA_HOME=/usr/local/java/jdk' >> /root/.bashrc
RUN echo 'PATH=$PATH:/usr/local/java/jdk/bin' >> /root/.bashrc
RUN rm -f /jdk-6u45-linux-x64.bin
# iwp
COPY iwp7.2.0.install /iwp7.2.0.install
COPY setup.jar /setup.jar
COPY setup_iwp.sh /setup_iwp.sh
RUN chmod u+x /setup_iwp.sh
RUN /setup_iwp.sh
RUN rm -f /setup_iwp.sh
COPY data-source.xml /usr/local/imart/conf/data-source.xml
COPY http.xml.tmpl /usr/local/imart/conf/http.xml.tmpl
# JDBC Driver
RUN curl -L -C - -O https://jdbc.postgresql.org/download/postgresql-8.4-703.jdbc4.jar
RUN mv /postgresql-8.4-703.jdbc4.jar /usr/local/imart/lib/postgresql-8.4-703.jdbc4.jar
# entrykit
COPY entrykit_0.4.0_Linux_x86_64.tgz /entrykit_0.4.0_Linux_x86_64.tgz
RUN tar zxvf /entrykit_0.4.0_Linux_x86_64.tgz
RUN mv /entrykit /usr/local/bin/
RUN entrykit --symlink
RUN rm -f /entrykit_0.4.0_Linux_x86_64.tgz
COPY run.sh /run.sh
RUN chmod +x /run.sh
RUN updatedb
ENTRYPOINT [ "render", "/usr/local/imart/conf/http.xml", "--" ]
CMD [ "/run.sh" ]
細かいセットアップはシェルスクリプトに逃がし、Dockerfile からはそれを実行するようにします。
これにより、Dockerfile をシンプルにでき、かつイメージ容量の削減にもつながります。
http.xml ファイルに PostgreSQL への接続情報を環境変数で受け取れるようにします。
そのための処理を entrykit の render 機能で実現しています。
http.xml の元となるファイルを /usr/local/imart/conf/http.xml.tmpl に COPY コマンドでコピーし、ENTRYPOINT にて render しています。
こうすることで、docker run 時に entrykit の render を動かし、/usr/local/imart/conf/http.xml.tmpl を元に /usr/local/imart/conf/http.xml を生成します。
setup_jdk.sh
#!/bin/sh
chmod u+x /jdk-6u45-linux-x64.bin
/jdk-6u45-linux-x64.bin
rm -f /jdk-6u45-linux-x64.bin
mkdir -p /usr/local/java
mv jdk1.6.0_45 /usr/local/java/jdk1.6.0_45
ln -s /usr/local/java/jdk1.6.0_45 /usr/local/java/jdk
Java 1.6.0_45 のセットアップスクリプトです。
setup_iwp.sh
#!/bin/sh
java -jar /setup.jar -f /iwp7.2.0.install
sed -i -e "s/<option>/<option>-Xdebug -Xrunjdwp:transport=dt_socket,address=9009,server=y,suspend=n /g" /usr/local/imart/conf/imart.xml
iWP 7.2.0 のセットアップスクリプトです。
サイレントインストールファイル(iwp7.2.0.install)を利用してサイレントインストールを行います。
また、Java のリモートデバッグをポート 9009 で開放するためのオプションを追加で設定しています。
iwp7.2.0.install
1
3
y
n
y
/usr/local/java/jdk
/usr/local/imart
1
1
4
4
127.0.0.1
127.0.0.1
8080
8080
8080
49152
APP:127.0.0.1:8080
128
2048
y
y
事前に java -jar setup.jar -s iwp7.2.0.install
にてサイレントインストール用のファイルを作成します。
IP アドレスは docker run 時に決まるため、サイレントインストール時には 127.0.0.1 を指定します。
docker run 時に実行する run.sh ファイルにて、設定ファイル中の 127.0.0.1 を実際のコンテナの IP アドレスに置き換える処理を入れています。
run.sh
#!/bin/bash
/etc/init.d/sshd restart
IP=$(ip addr show eth0 | perl -n -e 'if (m/inet ([\d\.]+)/g) { print $1 }')
sed -i -e "s/127\.0\.0\.1/${IP}/g" /usr/local/imart/conf/http.xml
sed -i -e "s/127\.0\.0\.1/${IP}/g" /usr/local/imart/conf/imart.xml
touch /usr/local/imart/bin/alone.log
java -cp /usr/local/imart/bin/imart.jar -Xms16m -Xmx128m jp.co.intra_mart.bin.server.ServerController -lonely >> /usr/local/imart/bin/alone.log 2>&1 < /dev/null &
tail -F /usr/local/imart/bin/alone.log
docker run 時に実行するスクリプトです。
sshd と iWP を起動しています。
また、http.xml と imart.xml にインストール時に指定した IP アドレス 127.0.0.1 を、Docker コンテナ実行時の IP アドレスに置換しています。
myiwp というタグでビルドします。
docker build -t myiwp:7.2.0 .
http.xml.tmpl
<!--
- Resin 3.1 configuration file.
-->
<resin xmlns="http://caucho.com/ns/resin"
xmlns:resin="http://caucho.com/ns/resin/core">
<!-- for jaxb -->
<system-property javax.xml.bind.JAXBContext="com.sun.xml.bind.v2.ContextFactory"/>
<!-- for StAX -->
<system-property javax.xml.stream.XMLEventFactory="com.ctc.wstx.stax.WstxEventFactory"/>
<system-property javax.xml.stream.XMLInputFactory="com.ctc.wstx.stax.WstxInputFactory"/>
<system-property javax.xml.stream.XMLOutputFactory="com.ctc.wstx.stax.WstxOutputFactory"/>
<!--
- Logging configuration for the JDK logging API.
-->
<log name="">
<handler type="jp.co.intra_mart.common.platform.log.handler.JDKLoggingOverIntramartLoggerHandler"/>
</log>
<!--
- 'info' for production
- 'fine' or 'finer' for development and troubleshooting
-->
<logger name="com.caucho" level="info"/>
<logger name="com.caucho.sql.spy" level="fine"/>
<logger name="com.caucho.java" level="config"/>
<logger name="com.caucho.loader" level="config"/>
<!--
- For production sites, change dependency-check-interval to something
- like 600s, so it only checks for updates every 10 minutes.
-->
<dependency-check-interval>2s</dependency-check-interval>
<!--
- You can change the compiler to "javac", "eclipse" or "internal".
-->
<javac compiler="javac" args="-g -source 1.5"/>
<cluster id="app-tier">
<!-- sets the content root for the cluster, relative to server.root -->
<root-directory>.</root-directory>
<server-default>
<!--
- Configures the minimum free memory allowed before Resin
- will force a restart.
-->
<memory-free-min>1M</memory-free-min>
<!-- Maximum number of threads. -->
<thread-max>256</thread-max>
<!-- Configures the socket timeout -->
<socket-timeout>65s</socket-timeout>
<!-- Configures the keepalive -->
<keepalive-max>128</keepalive-max>
<keepalive-timeout>15s</keepalive-timeout>
</server-default>
<!-- define the servers in the cluster -->
<server id="APP:127.0.0.1:8080" address="127.0.0.1">
<cluster-port port="6800" secure="false"/>
<http port="8080" secure="false"/>
</server>
<!--
- Defaults applied to each web-app.
-->
<web-app-default>
<prologue>
<!--
- Enable EL expressions in Servlet and Filter init-param
-->
<allow-servlet-el>true</allow-servlet-el>
</prologue>
<!--
- Sets timeout values for cacheable pages, e.g. static pages.
-->
<cache-mapping url-pattern="/" expires="5s"/>
<cache-mapping url-pattern="*.gif" expires="60s"/>
<cache-mapping url-pattern="*.jpg" expires="60s"/>
<cache-mapping url-pattern="*.png" expires="60s"/>
<!--
- for security, disable session URLs by default.
-->
<session-config>
<session-timeout>10</session-timeout>
<session-max>4096</session-max>
<enable-cookies>true</enable-cookies>
<enable-url-rewriting>true</enable-url-rewriting>
<reuse-session-id>false</reuse-session-id>
<cookie-secure>true</cookie-secure>
</session-config>
<!--
- For security, set the HttpOnly flag in cookies.
-->
<cookie-http-only>true</cookie-http-only>
<!--
- Some JSP packages have incorrect .tld files. It's possible to
- set validate-taglib-schema to false to work around these packages.
-->
<jsp>
<validate-taglib-schema>true</validate-taglib-schema>
<el-ignored>false</el-ignored>
<fast-jstl>true</fast-jstl>
<fast-jsf>false</fast-jsf>
<ignore-el-exception>true</ignore-el-exception>
<is-xml>false</is-xml>
<precompile>true</precompile>
<recompile-on-error>false</recompile-on-error>
<require-source>false</require-source>
<session>true</session>
<velocity-enabled>false</velocity-enabled>
</jsp>
</web-app-default>
<!-- includes the app-default for default web-app behavior -->
<resin:import path="${resin.home}/conf/app-default.xml"/>
<!--
- Sample database pool configuration
-
- The JDBC name is java:comp/env/jdbc/test
-
- For Oracle
<database>
<jndi-name>jdbc/oracle</jndi-name>
<driver>
<type>oracle.jdbc.pool.OracleConnectionPoolDataSource</type>
<url>jdbc:oracle:thin:@localhost:1521:dbname</url>
<user>username</user>
<password>password</password>
</driver>
<prepared-statement-cache-size>8</prepared-statement-cache-size>
<max-connections>20</max-connections>
<max-idle-time>30s</max-idle-time>
</database>
- For SQL Server
<database>
<jndi-name>jdbc/sqlserver</jndi-name>
<driver>
<type>com.microsoft.sqlserver.jdbc.SQLServerDriver</type>
<url>jdbc:sqlserver://localhost:1433;DatabaseName=dbname</url>
<user>username</user>
<password>password</password>
<init-param>
<param-name>SelectMethod</param-name>
<param-value>cursor</param-value>
</init-param>
</driver>
<prepared-statement-cache-size>8</prepared-statement-cache-size>
<max-connections>20</max-connections>
<max-idle-time>30s</max-idle-time>
</database>
- For DB2
<database>
<jndi-name>jdbc/db2</jndi-name>
<driver>
<type>com.ibm.db2.jcc.DB2Driver</type>
<url>jdbc:db2://localhost:50000/dbname</url>
<user>username</user>
<password>password</password>
</driver>
<prepared-statement-cache-size>8</prepared-statement-cache-size>
<max-connections>20</max-connections>
<max-idle-time>30s</max-idle-time>
</database>
- For PostgreSQL
<database>
<jndi-name>jdbc/postgres</jndi-name>
<driver>
<type>org.postgresql.Driver</type>
<url>jdbc:postgresql://localhost:5432/dbname</url>
<user>username</user>
<password>password</password>
</driver>
<prepared-statement-cache-size>8</prepared-statement-cache-size>
<max-connections>20</max-connections>
<max-idle-time>30s</max-idle-time>
</database>
-->
<database>
<jndi-name>jdbc/postgres</jndi-name>
<driver>
<type>org.postgresql.Driver</type>
<url>{{ var "PG_URL" | default "jdbc:postgresql://localhost:5432/dbname" }}</url>
<user>{{ var "PG_USER" | default "username" }}</user>
<password>{{ var "PG_PASSWORD" | default "password" }}</password>
</driver>
<prepared-statement-cache-size>8</prepared-statement-cache-size>
<max-connections>20</max-connections>
<max-idle-time>30s</max-idle-time>
</database>
<!--
- Configures the persistent store for single-server or clustered
- in Resin professional.
-->
<!--
<resin:if test="${resin.professional}">
<persistent-store type="jdbc">
<init>
<data-source>jdbc/sessionDB</data-source>
</init>
</persistent-store>
</resin:if>
-->
<!--
- Default host configuration applied to all virtual hosts.
-->
<host-default>
<!--
- With another web server, like Apache, this can be commented out
- because the web server will log this information.
-->
<access-log path="log/access.log"
format='%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"'
rollover-period="1W"/>
<!-- creates the webapps directory for .war expansion -->
<web-app-deploy path="webapps"/>
<!-- creates the deploy directory for .ear expansion -->
<ear-deploy path="deploy">
<ear-default>
<ejb-server>
<config-directory>WEB-INF</config-directory>
</ejb-server>
</ear-default>
</ear-deploy>
</host-default>
<!-- configures the default host, matching any host name -->
<host id="" root-directory=".">
<!--
- configures an explicit root web-app matching the
- webapp's ROOT
-->
<web-app id="/" root-directory="webapps/ROOT"/>
<web-app id="/imart" root-directory="${resin.home}/doc/imart" redeploy-mode="manual">
<!--
<session-config>
<use-persistent-store>true</use-persistent-store>
<always-save-session>true</always-save-session>
<save-mode>after-request</save-mode>
</session-config>
-->
</web-app>
</host>
</cluster>
</resin>
事前に iWP 7.2.0 をインストールしそのインストール先のフォルダから http.xml を http.xml.tmpl としてコピーします。
さらに、199行~210行目に PostgreSQL で接続するためのデータベース接続先を定義します(この CookBook の Docker では PostgreSQL のみ対応することとします)。
行数 | 環境変数 | 説明 |
---|---|---|
203 | PG_URL | PostgreSQL データベースへの接続先 URL の情報を、PG_URL 環境変数として受け取るようにしています。 |
204 | PG_USER | PostgreSQL データベースへの接続先ユーザの情報を、PG_USER 環境変数として受け取るようにしています。 |
205 | PG_PASSWORD | PostgreSQL データベースへの接続先ユーザのパスワードの情報を、PG_PASSWORD 環境変数として受け取るようにしています。 |
docker run 時に -e オプションにて PG_URL, PG_USER, PG_PASSWORD 環境変数を指定してもらう作りとしています。
そのため、http.xml ファイルの199行~210行目を追加し、環境変数に応じて設定値を変更する処理を行っています。
設定ファイル中にこのように記載することで entrykit の render 実行時に環境変数の値に置き換えることができます。
data-source.xml
<?xml version="1.0" encoding="UTF-8"?>
<data-source>
<system-data-source>
<connect-id>default</connect-id>
<resource-ref-name>java:comp/env/jdbc/postgres</resource-ref-name>
</system-data-source>
<group-data-source>
<login-group-id>default</login-group-id>
<resource-ref-name>java:comp/env/jdbc/postgres</resource-ref-name>
</group-data-source>
</data-source>
java:comp/env/jdbc/postgres
を設定済みの data-source.xml を用意します。
3. 実行します
docker run -it \
-p 8080:8080 \
-p 9009:9009 \
-p 2222:22 \
-e PG_URL=jdbc:postgresql://mypostgresql.example.com:5432/iwp \
-e PG_USER=imart \
-e PG_PASSWORD=imart \
myiwp:7.2.0
この CookBook のコンテナは、PostgreSQL のみ対応しています。
PostgreSQL を別途用意し、docker run 時の PG_URL, PG_USER, PG_PASSWORD 環境変数にその接続情報を渡します。
上記の例では、mypostgresql.example.com:5432 の DB=iwp, user=imart, password=imart を利用します。
また、コンテナは root/password で ssh 接続ができるようになっています。
あくまで検証用の Docker としてこのように設定しているため、セキュリティにはご注意ください。
このように、Docker イメージ化するだけで、検証用の iWP をすぐに準備できます。
是非ご活用ください。