RSS

カテゴリー別アーカイブ: java

Jenkins、Sonatype nexus を Apache のリバースプロキシ経由で使う

Java開発をしているプロジェクトでは、CIにJenkins、Mavenリポジトリ管理にSonatype Nuxusを使っている人が多いと思います。
ていうか、使うとすごく開発効率上がるので使うべき。
で、私も両方使っているのですが、これらをApacheのバックで使う時微妙にはまることがあるのでその辺の話。

面倒が起きるのは、Apacheをフロントに置いてそのバックにJenkins、NexusをTomcatなどのJavaEEサーバにデプロイして動かす場合。
中でも、URLをいろいろ弄りたい場合。
例えば、http://example.com/foo/jenkins とか、標準の http://example.com/jenkins とは違うURLにした場合うまく動かない。
Tomcatとかに Jenkins とか Nexus の war を突っ込むと、/jenkins、/nexus というパスでアクセスできるようになる。
これを、http://example.com/foo/jenkins したければ、Apacheのリバースプロキシを設定します。
つまり、/foo/jenkins へのアクセスをTomcatの /jenkins にパスするという設定をします。
これ自体はApacheのmod_proxy設定を素直にやればいいのですが、リンクを踏んだとき /foo/jenkins じゃなく /jenkins に飛んじゃったり、Cookieが /jenkins に対して発行されて動作がおかしくなったりいろいろ問題が発生します。
その辺を解決するための設定が以下。

  • JenkinsのApache設定
  • ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass /foo/jenkins/ http://localhost:8080/jenkins/
    ProxyPassReverse /foo/jenkins/ http://localhost:8080/jenkins/
    Header edit Location ^http://example.com/jenkins/ http://example.com/foo/jenkins/
    <Proxy "http://localhost:8080/jenkins/*">
      Order Deny,Allow
      Allow from all
    </Proxy>
    
  • NexusのApache設定
  • ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass /foo/nexus/ http://localhost:8080/nexus/
    ProxyPassReverse /foo/nexus/ http://localhost:8080/nexus/
    ProxyPassReverseCookiePath /nexus /foo/nexus
    <Proxy "http://localhost:8080/nexus/*">
      Order Deny,Allow
      Allow from all
    </Proxy>
    

    Jenkinsは、クライアントに返すLocationヘッダを書き換えて正しいURLに飛ぶようにしてやります。
    Nexusは、Nexus自身の設定の中にURLの設定があるので、Locationヘッダをいじったりしなくてもいいのですが、Cookieが /nexus に対して発行されるのでログインができなかったりする。
    これを ProxyPassReverseCookiePath にマップを定義することで正しいパスに対して Cookie を設定します。

    意外とこの辺情報が見当たらなかったので、少しは役に立つかと思いまとめてみました。

     
    コメントする

    投稿者: : 2012/11/08 投稿先 java

     

    logbackを使う

    昔はJavaにおけるロギングフレームワークといえばcommons-logging、log4jあたりが鉄板でしたが、今はlogbackslf4jあたりが鉄板なのかなと。
    というわけで、logback+slf4jを使うための設定をまとめてみます。

    自分はMavenを使ってモジュールのBuildをしているのでMavenのコンフィグレーションです。
    まず、必要な依存性として以下を定義。

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${org.slf4j.slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-ext</artifactId>
      <version>${org.slf4j.slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
      <version>${org.slf4j.slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jul-to-slf4j</artifactId>
      <version>${org.slf4j.slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>${ch.qos.logback.logback.version}</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>${ch.qos.logback.logback.version}</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-access</artifactId>
      <version>${ch.qos.logback.logback.version}</version>
    </dependency>
    

    あと、commons-loggingやlog4jのライブラリが依存に入っていると競合して想定した動作をしてくれないため、これらのライブラリが使われていないことをチェックする定義を書きます。
    これは、maven enforcer プラグインの力を借ります。

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-enforcer-plugin</artifactId>
      <executions>
        <execution>
          <id>enforce-versions</id>
          <goals>
            <goal>enforce</goal>
          </goals>
          <configuration>
            <rules>
              <bannedDependencies>
                <searchTransitive>true</searchTransitive>
                <excludes>
                  <exclude>commons-logging</exclude>
                  <exclude>log4j:log4j</exclude>
                  <exclude>org.slf4j:1.5*</exclude>
                </excludes>
              </bannedDependencies>
            </rules>
            <fail>true</fail>
          </configuration>
        </execution>
      </executions>
    </plugin>
    

    もし、このプラグイン設定をして Build でエラーが出るようなら、mvn dependency:tree コマンドで依存ツリーを表示し、commons-logging などが無いか確認します。
    もし、使っているライブラリからの依存で読み込まれていたら、そのライブラリの dependency 定義で exclusion してやります。

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${org.springframework.spring.version}</version>
      <exclusions>
        <exclusion>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    

    これで、logback.xml を書いてやればOK。
    logback.xml の書き方はあちこちに参考になる記事がありますのでそちらを見てみてください。
    これで、変に依存ライブラリにログが吸い込まれたりすることもなく、ロギングコントロールを一本化できます。
    ログはデバッグの要なので、ロギングフレームワークもしっかり固めておきたいところ。

     
    コメントする

    投稿者: : 2012/09/09 投稿先 engineer, java

     

    m2eclipse + maven-enforcer-plugin で出るうざい警告を消す

    eclipseでm2eclipseを使っていると、こんな警告が出てくるときがあります。

    maven-enforcer-plugin (goal “enforce”) is ignored by m2e.

    これが出るのはプロジェクトに取り込んでいるMavenプロジェクトで、maven-enforcer-pluginを使っている時です。

    Javaのバージョン指定したりするのに、多くのプロジェクトで使ってるのではないでしょうか。

    これが出ているからと言って何かが動かなくなるといった不具合はないのですが、全てのpom.xmlに警告マークが付くので、精神衛生上よくありません。

    警告も残らず消したい人なもので。

    ということで、この警告を消すにはプロジェクトのpom.xmlのpluginManagementに以下のエントリを追加します。

    <plugin>
    <groupId>org.eclipse.m2e</groupId>
    <artifactId>lifecycle-mapping</artifactId>
    <version>1.0.0</version>
    <configuration>
    <lifecycleMappingMetadata>
    <pluginExecutions>
    <pluginExecution>
    <pluginExecutionFilter>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <versionRange>[1.0,)</versionRange>
    <goals>
    <goal>enforce</goal>
    </goals>
    </pluginExecutionFilter>
    <action>
    <ignore></ignore>
    </action>
    </pluginExecution>
    </pluginExecutions>
    </lifecycleMappingMetadata>
    </configuration>
    </plugin>
    

    これで警告は消えます。

    すっきり。

     
    コメントする

    投稿者: : 2011/12/03 投稿先 java

     

    プライベートなMavenリポジトリを立てる

    Mavenは、複数のリポジトリから依存ライブラリをかき集めてBuildすることができますが、もちろん自身が開発した物件をプロジェクト内だけで使うプライベートなMavenリポジトリでホストしてプロジェクトチーム内で共有することができます。

    リビジョン管理とこのようなリリースBuildのコントロールによって、テストなどのレポート、解析を効率よく進めることができます。

    立てる方法もやってみるとすごく簡単。

    • 必要なもの
      • Maven
      • scp でファイルを受けとってくれるサーバ (ftpとかでもいい)
      • Nexus か HTTPサーバ

    1. リポジトリとなるサーバを立てる

    まずリポジトリサーバを立てます。

    今回は、クライアントからリリース物件の転送を scp を使う方法で作ってみるので、Linuxで立てるのが楽です。

    まず、リポジトリのメンテナンスユーザを作ります。

    自分は、プロジェクト名のユーザを大体作ります。

    # sudo useradd necomimi
    

    次に、scp をするためにリポジトリとなるディレクトリを作成します。

    necomimi# mkdir /project/maven
    

    次に、Nexus を上げます。

    Nexus は、Mavenリポジトリのプロキシとしての役割りを果たしてくれて、外部のMavenリポジトリをキャッシュしてくれたりするのですごく便利です。

    今回のテーマであるプライベートリポジトリを立てるのに必須ではないのだけど、Mavenをがっつり使うのであればマストと言っていいツールです。

    Nexus と Hudson は、マスト。

    といっても、これは Nexus の war を Tomcat などの JEE サーバに配備するだけなので割愛。

    今使ってるプロジェクトでは、Jetty で運用しています。

    Nexus を立てて基本的な設定が済んだら、リポジトリの Add で Hosted Repository を追加します。

    この辺の画面見てください。

    これは、自前のプライベートリポジトリを立てる機能です。

    いくつか設定がありますが、ほとんどデフォルトでよくて、IDやNameは適当なものを入れて、Override Local Storage Location のところに上で作ったリポジトリ用のディレクトリを入力します。

    上の例だと、/project/maven

    これで保存したら終了。

    2. クライアントを設定する

    リリース作業を行なうクライアントの設定をします。

    リリース作業は、各開発者よりはリリースを管理するリリース担当者がやるので、その人の端末の設定になります。

    まずは、Mavenの設定にリポジトリサーバの認証情報などを設定します。

    いろいろやりかたはあるのですが、今回はssh-keyベースの認証で scp するようにします。

    まず、ssh-keyを作ります。

    既に作成済なら、それを使えばよいです。

    someone# ssh-keygen
    

    これで、~/.ssh に id_dsa (秘密鍵), id_dsa.pub (公開鍵)ができるので、id_dsa.pub の内容を1で作ったリポジトリサーバのリポジトリのメンテナンスユーザのホームの .ssh/authorized_keys に追記します。

    上の例だったら necomimi ユーザのファイルです。

    なければ作成してください。

    これは、パーミッションを600 にして勝手に書き替えられないようにしておいてください。

    次は、Mavenの設定にリポジトリサーバの情報を設定します。

    以下のように設定ファイルを書きます。

    • ~/.m2/settings.xml
    <servers>
    ...
    <server>
    <id>necomimi-repository</id>
    <username>necomimi</username>
    <privateKey>/home/someone/.ssh/id_dsa</privateKey>
    <filePermissions>664</filePermissions>
    <directoryPermissions>775</directoryPermissions>
    <configuration>
    <sshExecutable>/usr/bin/ssh</sshExecutable>
    <scpExecutable>/usr/bin/scp</scpExecutable>
    <sshArgs></sshArgs>
    </configuration>
    </server>
    </servers>
    

    これでクライアントの設定は完了。

    3. プロジェクトのpom.xmlの設定

    最後に、リリース対象となるプロジェクトのpom.xmlを設定します。

    設定すべきことは、リポジトリサーバの指定と、scp を実行してくれる拡張機能の設定です。

    拡張機能には ftp などもあるので、サーバの環境に合わせて変更してください。

    ここでは、詳しくは書きません。

    • pom.xml
    <project>
    ...
    <distributionManagement>
    <repository>
    <id>necomimi-repository</id>
    <url>scpexe://example.com/project/maven</url>
    </repository>
    </distributionManagement>
    <build>
    <extensions>
    <extension>
    <groupId>org.apache.maven.wagon</groupId>
    <artifactId>wagon-ssh-external</artifactId>
    <version>1.0-beta-6</version>
    </extension>
    </extensions>
    </build>
    ..
    </project>
    

    これで設定は完了。

    リリース作業は、

    someone# mvn deploy
    

    だけです。

    これで、リポジトリサーバの /project/maven 以下に、Mavenリポジトリにおなじみのディレクトリ構成とリリース物件である jar や チェックサムファイルなどが配備されているはずです。

    これを、Nexus の Hosted Repository 経由で参照できるので、プライベートなMavenリポジトリとして利用できます。

    Nexus を使わないのであれば、ApacheHTTPなどを立てて、リポジトリディレクトリを公開するだけでもOKです。

    この辺、大した時間かからないけど、方法を調べたりしてると意外に面倒でなかなか実行しないことが多いので、まとめてみました。

     
    コメントする

    投稿者: : 2011/01/27 投稿先 java