この CookBook では、intra-mart WebPlatform 7.2 の Docker の作成手順について紹介しています。
レシピ
- ベースイメージの作成
- intra-mart WebPlatform 7.2 の Docker イメージを作成します
- 実行します
1. ベースイメージの作成
CentOS 5.11 を使用します。
Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# 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 というタグでビルドします。
1 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
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
1 2 3 4 5 6 7 8 9 |
#!/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
1 2 3 4 |
#!/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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/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 というタグでビルドします。
1 |
docker build -t myiwp:7.2.0 . |
http.xml.tmpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
<!-- - 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
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?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. 実行します
1 2 3 4 5 6 7 8 |
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 をすぐに準備できます。
是非ご活用ください。