JenkinsからWildFlyへのリモートデプロイ(pom.xmlの更新)
前回は、Jenkinsサーバーが乗っているDockerコンテナから、WildFlyが動作しているアプリケーションサーバー用Dockerコンテナへのコンテナ間接続をやりました。 begirama.hatenablog.com
JenkinsからWildFlyへのリモートデプロイはWildFly Maven Pluginというのがあって、MavenからWildFlyへのデプロイ、アンデプロイ、インスタンスの起動停止が行えるようです。
WildFly Maven Plugin - Plugin Documentation
deployに関する詳細なリファレンスは下記。 WildFly Maven Plugin - wildfly:deploy
公式サイトではないですが、リモートサーバーへデプロイする際のpom.xmlの例はこちら。 Configuring Maven WildFly plugin
実際のpom.xmlのデプロイ部分はこんな感じ。
<plugin> <groupId>org.wildfly.plugins</groupId> <artifactId>wildfly-maven-plugin</artifactId> <version>1.1.0.Alpha1</version> <executions> <execution> <id>deploy</id> <phase>install</phase> <goals> <goal>deploy</goal> </goals> <configuration> <hostname>apppot_runtime1.7</hostname> <port>9990</port> <name>apppot-1.7-ci-jenkins.war</name> <username>{username}</username> <password>{password}</password> <filename>apppot-1.7-ci-jenkins.war</filename> </configuration> </execution> </executions> </plugin>
deployタスクのconfigurationとして、次を指定しています。
- hostname: Docker Linkした結果、hostsに定義されたホスト名を指定します。
apppot_runtime1.7
- port: WildFlyの管理ポートを指定。アプリケーションサーバーコンテナで、管理ポートをexposeしています
- name: デプロイする名前。warの拡張子を付けてないとだめ。付けてない場合、デプロイタスク自体は成功するけど、WildFly側でいろいろ認識されていなくて動かなかった。特にエラーもでないから調査に時間かかった。
- username: WildFlyにログインするためのアカウント
- password: WildFlyにログインするためのパスワード
- filename: デプロイするwarファイルを指定しています
すごくはまったのは、[ERROR] JBREM000200: Remote connection failed: javax.security.sasl.SaslException: Authentication failed: the server presented no authentication mechanisms
のエラー。
いろなサイトを参考にして、nameだけ指定して、usernameは使っていませんでした。この時に、上のエラーが発生していました。逆にusernameのみを指定しても同じエラーが発生しました。結局、usernameとnameの両方を指定することで、解消しました。参考にしたサイトの人たちはなんで成功していたんだろう・・・。
認証で、こけると何でもこのエラーになるみたいです。
2015/08/21追記
WildFlyの古いバージョンだと、ネイティブ用のポートを使ってデプロイしていて、それだとusernameが不要のようです。 最新のWildFlyだと管理ポートのプロトコルはHTTPで、その場合、usernameが必要なようです。 それで古い記事を参考にしていると駄目だったんだな。
JenkinsからWildFlyへのリモートデプロイ(DockerコンテナのLink)
自社製品のAppPotの開発、運用環境は次のような構成になっています。
- 自社クラウド本番環境:クラウド運用しているバージョンのみ
- 自社クラウドテスト環境:クラウド運用しているバージョンのみ
- 自社クラウド開発環境:クラウド運用しているバージョンのみ
- 自社CI環境:製品バージョンごとに存在
- 受託プロジェクト開発開発:プロジェクトごとに存在
バージョンごとに環境を立てるのは大変なので、自社CI環境と受託プロジェクト開発環境はDockerコンテナ上で運用しています。常にすごい負荷がかかっているわけではないので、小規模なさくらインターネットのサーバーで3〜5つくらいのコンテナが動作しています。
このうち、CI環境の一部だけはJenkinsを使ったビルド、デプロイ、テストのプロセスが自動で回っています。この一部というのは、Jenkinsと同居しているアプリケーションサーバーのみ。 なぜかというと、コンテナ間の連携をちゃんとやる時間が無かったから・・。
というわけで、コンテナ間の連携、JenkinsからのWildFlyへのリモートデプロイをできるようにするのが、本エントリの目標です。
Dockerコンテナ間連携
まだしばらく同一サーバー内でのコンテナ間連携で行けそうなので、--link
を使います。
https://docs.docker.com/docker/userguide/dockerlinks/#communication-across-links
今回の場合はJenkinsサーバーコンテナから、アプリケーションサーバーコンテナへリンクします。
アプリケーションサーバーの起動
--name
オプションで、apppot_runtime1.7
という名前でコンテナを起動させています。
docker run -it --expose 9181 -p 9181:8080 -p 9991:9990 --name apppot_runtime1.7 rsogo/wildfly8:v1 /bin/bash
Jenkinsサーバーコンテナの起動
--link
オプションで、apppot_runtime1.7
という名前のコンテナをリンクさせています。
docker run -it --expose 8081 -p 8081:8080 --name jenkins --link apppot_runtime1.7:apppot_runtime1.7 rsogo/jenkins:v5 /bin/bash
コンテナIDでもリンクで指定することはできますが、コンテナIDはコンテナの起動の度に変わります。 上のような起動スクリプトはシェルとして用意しておきたいと思いますので、コンテナIDより、コンテナ名を定義しておいた方が便利です。
Jenkinsサーバーコンテナでのhostsファイル、環境変数の確認
apppot_runtime1.7
がhostsファイルに追加されていることが分かります。
# cat /etc/hosts 172.17.0.71 cfc8c054ccf8 127.0.0.1 localhost 172.17.0.69 apppot_runtime1.7 9b5ee14ff469
env
コマンドを実行した結果、環境変数にアプリケーションサーバーコンテナが公開しているポートごとに次のような環境変数が定義されています。
APPPOT_RUNTIME1.7_PORT_8080_TCP_ADDR=172.17.0.69 APPPOT_RUNTIME1.7_PORT=tcp://172.17.0.69:22 APPPOT_RUNTIME1.7_PORT_22_TCP_PORT=22 APPPOT_RUNTIME1.7_PORT_22_TCP_ADDR=172.17.0.69 APPPOT_RUNTIME1.7_PORT_22_TCP=tcp://172.17.0.69:22 APPPOT_RUNTIME1.7_PORT_9181_TCP_PORT=9181 APPPOT_RUNTIME1.7_PORT_22_TCP_PROTO=tcp APPPOT_RUNTIME1.7_PORT_8080_TCP_PORT=8080 APPPOT_RUNTIME1.7_PORT_9990_TCP=tcp://172.17.0.69:9990 APPPOT_RUNTIME1.7_PORT_9080_TCP_PORT=9080 APPPOT_RUNTIME1.7_PORT_9181_TCP_PROTO=tcp APPPOT_RUNTIME1.7_PORT_8080_TCP=tcp://172.17.0.69:8080 APPPOT_RUNTIME1.7_PORT_8080_TCP_PROTO=tcp APPPOT_RUNTIME1.7_PORT_9080_TCP_PROTO=tcp APPPOT_RUNTIME1.7_PORT_9990_TCP_ADDR=172.17.0.69 APPPOT_RUNTIME1.7_PORT_9080_TCP_ADDR=172.17.0.69
この状態で、Jenkinsサーバーコンテナから以下のコマンドを実行することで、JenkinsサーバーからWildFlyのポートにアクセスできることを確認できます。
# curl http://apppot_runtime1.7:8080 <!-- ~ JBoss, Home of Professional Open Source. ~ Copyright (c) 2011, Red Hat, Inc., and individual contributors 略
次は、JenkinsサーバーからWildFlyへリモートデプロイします。
Mule ESBまとめ
Mule ESB 3.7のDatabase Connectorを試す2(INSERT)
先日、Muleを使ってOracle Databaseにアクセスするための設定の記事を書きました。
今回は、JSONで受け取って、Oracle DBにInsertするまでを書きます。
前回のSELECTだけやるフローを改良しています。
まず、HTTPメソッドに応じて動かすフローを分けています。
GETメソッドで動かすフロー
<flow name="GetFlow"> <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="Recieve HTTP request" allowedMethods="GET"/>
中身は前回のフローとほぼ同様で、データベースに対してSELECT文を発行して、結果をJSONにして返します。
レスポンスのサンプルはこんな感じ。
[ { "VALUE": "foo", "NAME": "SATO" }, { "VALUE": "bar", "NAME": "SUZUKI" } ]
POSTメソッドで動かすフロー
<flow name="PostFlow" doc:name="PostFlow"> <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="Recieve HTTP request" allowedMethods="POST"/>
中身の処理は
デバッグ用にTransformerの前後でPayloadの中身をログにダンプ
<logger doc:name="Log the payload" level="INFO" message="About to echo #[message.payload]"/>
変換前後のログの出力結果はこんな感じ。
INFO 2015-08-06 08:51:47,892 [[database_update].HTTP_Listener_Configuration.worker.01] org.mule.api.processor.LoggerMessageProcessor: About to echo org.glassfish.grizzly.utils.BufferInputStream@386d562 INFO 2015-08-06 08:51:47,973 [[database_update].HTTP_Listener_Configuration.worker.01] org.mule.api.processor.LoggerMessageProcessor: About to echo [{VALUE=foo, NAME=SATO}, {VALUE=bar, NAME=SUZUKI}]
JSONをObjectに変換
この時の変換先のクラスはjava.util.ArrayList
ということを指定しています。
今回は、この後でループ処理をやるためにArrayListに変換していますが、<byte-array-to-string-transformer doc:name="Convert Byte Array to String"/>
とかで、一つのStringオブジェクトに変換してもOK。
<json:json-to-object-transformer returnClass="java.util.ArrayList" doc:name="JSON to Object"/>
INSERTの発行
リクエストに含まれる件数分ループで回しつつ、Insert文を発行。
<foreach collection="#[message.payload]" doc:name="For Each"> <db:insert config-ref="Oracle_Configuration" doc:name="Database"> <db:parameterized-query><![CDATA[INSERT INTO TEST(NAME, VALUE) VALUES (#[payload.NAME], #[payload.VALUE])]]></db:parameterized-query> </db:insert> </foreach>
マニュアル
あんまり読んで無いけど、JDBC周りのリファレンス。
JDBC Transport Reference - Current Mule Documentation
HTTPリスナでリクエストを受け付けるところはこのマニュアルを読んでおけばOK。
HTTP Listener Connector - Current Mule Documentation
Payloadからの値の取り方について
あと、これも参考にした。
JSON Payload ingested into MySQL database using Mule ESB - Stack Overflow
Mule ESB 3.7 メッセージ変換
使えるメッセージ変換の機能は下記のマニュアルを参照。
- 用意されている変換機能
Objectと、JSON、XMLの変換なんかは自動でやってくれる。 いざとなったらJavaやGroovyも呼び出せる。
Transformers - Current Mule Documentation
MEL (Mule Expression Language)
MELというXMLベースの独自言語が用意されていて、メッセージの要素にアクセスしたり、値を評価しての条件分岐とか書ける。
概要はこっちのマニュアルを読んで、
Mule Expression Language MEL - Current Mule Documentation
どんな機能が用意されているからは、こっちのリファレンスを見ればOK。 Mule Expression Language Reference - Current Mule Documentation
後はサンプルを見て、感じをつかむのが早い。
デプロイすると、No suitable driver found
が原因のjava.sql.SQLException
が発生する。
Muleを再起動すると解消する。DB接続が絡んでいない場合は、起動中のホットデプロイができているので、DB接続がらみで何かあるのかも知れない。要調査。
org.mule.module.db.internal.domain.connection.ConnectionCreationException: java.sql.SQLException: Cannot get connection for URL jdbc:oracle:thin:CMN/CMDB01@localhost:1521:aaa : No suitable driver found for jdbc:oracle:thin:aaa/aaa@localhost:1521:aaa (java.sql.SQLException). Message payload is of type: LinkedHashMap
Mule ESB 3.7のDatabase Connectorを試す1(設定とSELECT)
デプロイ
mule-config.xmlをappsの下に作ったdatabaseフォルダに置きます。
$ pwd /Users/rsogo/work/mule-standalone-3.7.0/apps/database $ ls mule-config.xml
デプロイ時ログ
おぉ、成功。
******************************************************************************************************* * - - + APPLICATION + - - * - - + DOMAIN + - - * - - + STATUS + - - * ******************************************************************************************************* * default * default * DEPLOYED * * database * default * DEPLOYED * *******************************************************************************************************
JDBC Driverの配置
- Database Driverになにもやってない状態で
http://localhost:8081/
にアクセスすると次のようなエラーがでた。
org.mule.module.db.internal.domain.connection.ConnectionCreationException: java.sql.SQLException: Error trying to load driver: oracle.jdbc.Driver : oracle.jdbc.Driver (java.sql.SQLException). Message payload is of type: NullPayload
Oracle Database 12c Release 1 JDBC Driver Downloads
自分の環境はJDK1.7を使っているので、ojdbc7.jar
。
{MULE_HOME}/lib/user/
配下に置く。
$ ls lib/user/ README.txt mule-tests-functional-3.7.0.jar xmlunit-1.5.jar junit-4.11.jar ojdbc7.jar
StackOverflowかどこかに{MULE_HOME}/lib/mule/
に置けって言っている人がいるけど、それだと動かなかった。
- DriverはOKで、コネクションが確立できない場合のログ。
org.mule.module.db.internal.domain.connection.ConnectionCreationException: java.sql.SQLException: Cannot get connection for URL jdbc:oracle:thin:{User}/{Password}@localhost:{SID} : No suitable driver found for jdbc:oracle:thin:{User}/{Password}@localhost:{SID} (java.sql.SQLException). Message payload is of type: NullPayload
実行
Muleを実行しているマシンのhttp://locahost:8081/
にアクセスしてみる。
上手く行っていると、データベースに検索した結果がJSONに変換されたレスポンスが見られる。
続きを次のエントリで書いています。 begirama.hatenablog.com
Mule ESB 3.7起動
Mule 3.7がリリースされているので、そちらを試してみたいと思います。
Mule 3.7のダウンロード
以前のエントリでは、Enterprise版のダウンロードページにしか行けずに、そちらで検証していました。 Enterprise版ではトライアル期間が終わると次のようなエラーが出て、起動できなくなります。
ERROR 2015-08-04 16:22:59,527 [main] com.mulesource.licm.impl.TrueLicenseHelper: Couldn't validate license key! Invalid license
Community Editionのダウンロードはこちらで行けそう。
Muleの起動
ダウンロードしたファイルを解凍。
$ unzip mule-standalone-3.7.0.zip
実行ファイルがあるところまで移動して、
$ cd mule-standalone-3.7.0/bin/ $ ls additional.groovy launcher.bat mule launcher launcher.conf mule.bat
muleコマンドを実行
$ ./mule
起動ログ
$ ./mule MULE_HOME is set to /Users/rsogo/work/mule-standalone-3.7.0 Running in console (foreground) mode by default, use Ctrl-C to exit... MULE_HOME is set to /Users/rsogo/work/mule-standalone-3.7.0 Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 Running Mule... --> Wrapper Started as Console Launching a JVM... Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 Starting the Mule Container... Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved. WARNING - Unable to load the Wrapper's native library because none of the following files: libwrapper-macosx-x86-64.dylib libwrapper-macosx-universal-64.dylib libwrapper.dylib could be located on the following java.library.path: /Users/rsogo/work/mule-standalone-3.7.0/bin/%LD_LIBRARY_PATH% /Users/rsogo/work/mule-standalone-3.7.0/lib/boot Please see the documentation for the wrapper.java.library.path configuration property. System signals will not be handled correctly. INFO 2015-08-04 16:46:04,937 [WrapperListener_start_runner] org.mule.module.launcher.MuleContainer: ********************************************************************** * Mule ESB and Integration Platform * * Version: 3.7.0 Build: 725cbc8a * * MuleSoft, Inc. * * For more information go to http://www.mulesoft.org * * * * Server started: 15/08/04 16:46 * * JDK: 1.7.0_71 (mixed mode) * * OS: Mac OS X (10.10.4, x86_64) * * Host: Ryohei-no-MacBook-Pro.local (192.168.11.5) * ********************************************************************** INFO 2015-08-04 16:46:04,941 [WrapperListener_start_runner] org.mule.module.launcher.coreextension.DefaultMuleCoreExtensionManager: Initializing core extensions INFO 2015-08-04 16:46:04,941 [WrapperListener_start_runner] org.mule.module.launcher.coreextension.DefaultMuleCoreExtensionManager: Starting core extensions INFO 2015-08-04 16:46:04,955 [WrapperListener_start_runner] org.mule.module.launcher.DefaultArchiveDeployer: ================== New Exploded Artifact: default INFO 2015-08-04 16:46:04,963 [WrapperListener_start_runner] org.mule.module.launcher.MuleSharedDomainClassLoader: Using domain dir /Users/rsogo/work/mule-standalone-3.7.0/domains/default for domain default INFO 2015-08-04 16:46:05,013 [WrapperListener_start_runner] org.mule.module.launcher.MuleDeploymentService: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Started domain 'default' + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ INFO 2015-08-04 16:46:05,020 [WrapperListener_start_runner] org.mule.module.launcher.DefaultArchiveDeployer: ================== New Exploded Artifact: default INFO 2015-08-04 16:46:05,044 [WrapperListener_start_runner] org.mule.module.launcher.application.DefaultMuleApplication: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + New app 'default' + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ INFO 2015-08-04 16:46:09,459 [WrapperListener_start_runner] org.mule.module.launcher.MuleDeploymentService: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Started app 'default' + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ INFO 2015-08-04 16:46:09,462 [WrapperListener_start_runner] org.mule.module.launcher.DeploymentDirectoryWatcher: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Mule is up and kicking (every 5000ms) + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ INFO 2015-08-04 16:46:09,533 [WrapperListener_start_runner] org.mule.module.launcher.StartupSummaryDeploymentListener: ********************************************************************** * - - + DOMAIN + - - * - - + STATUS + - - * ********************************************************************** * default * DEPLOYED * ********************************************************************** ******************************************************************************************************* * - - + APPLICATION + - - * - - + DOMAIN + - - * - - + STATUS + - - * ******************************************************************************************************* * default * default * DEPLOYED * *******************************************************************************************************