in the mythosil

Rhythm & Biology.

WildFly: デプロイ時のnameとruntime-nameの役割

WildFlyへのCLIツールを利用したデプロイ時に--nameオプションと--runtime-nameオプションがあり、それぞれが何を意味しているのか分からなかったため、実験しつつ調べてみました。

まずはヘルプを読む

ざっくり把握した内容

  • nameはユニークでなければならない
  • 明示的に指定されなければ、ファイル名(war)がそのままnameになる
  • runtime-nameはユニークである必要はない
  • runtime-nameが重複している場合、どれか一つしか起動できない
[standalone@localhost:9990 /] deploy --help
SYNOPSIS

    deploy ((file_path | --url=deployment_url)
               [--script=script_name] [--name=deployment_name]
               [--runtime-name=deployment_runtime_name]
               [--force | --disabled] [--unmanaged])
           | --name=deployment_name
           [--server-groups=group_name (,group_name)* | --all-server-groups]
           [--headers={operation_header (;operation_header)*}]

DESCRIPTION

  Deploys the application designated by the file_path or enables an already
  existing but disabled in the repository deployment designated by the name
  argument. If executed w/o arguments, will list all the existing deployments.

ARGUMENTS
...(中略)...

 --name            - the unique name of the deployment. If the file path
                     argument is specified the name argument is optional with
                     the file name been the default value. If the file path
                     argument isn't specified then the command is supposed to
                     enable an already existing but disabled deployment, and in
                     this case the name argument is required.

 --runtime-name    - optional, the runtime name for the deployment. This will
                     form the basis for such things as default Java EE
                     application and module names. This would typically be the
                     same as --name, and if not specified the value used for
                     --name will be used. In some cases users may wish to have
                     two deployments with the same 'runtime-name' (e.g. two
                     versions of "example.war") both available in the management
                     configuration, in which case the deployments would need to
                     have distinct 'name' values but would have the same
                     'runtime-name'. Within an individual server, only one
                     deployment with a given 'runtime-name' can deployed.
                     However, multiple deployments with the same 'runtime-name'
                     can exist in the configuration, so long as only one is
                     enabled.

...(略)...

サンプルアプリケーション

2つのごく単純なアプリケーション(war)を用意

  • app-a.war: 「Hello, A」と表示
  • app-b.war: 「Hello, B」と表示

何もオプションを指定せずデプロイ

NAMERUNTIME-NAMEはどちらもそのままwarファイル名となります。
アプリケーションにアクセスする際も、warファイル名がURLに含まれます(suffixは除く)。

[standalone@localhost:9990 /] deploy app-a.war
[standalone@localhost:9990 /] deployment-info
NAME      RUNTIME-NAME PERSISTENT ENABLED STATUS 
app-a.war app-a.war    true       true    OK     
app-b.war app-b.war    true       true    OK

アンデプロイする時はNAME(=warファイル名)を指定します。
ファイルは残してdisabled状態にしたい場合は、--keep-contentオプションを付けます。

この状態でアクセスすると、どちらも「404 - Not Found」と表示されます。

[standalone@localhost:9990 /] undeploy app-a.war
[standalone@localhost:9990 /] undeploy app-b.war --keep-content
[standalone@localhost:9990 /] deployment-info 
NAME      RUNTIME-NAME PERSISTENT ENABLED STATUS  
app-b.war app-b.war    true       false   STOPPED

--nameオプションを指定してデプロイ

hoge.warにすると/hogeでアクセス出来るようになります。

[standalone@localhost:9990 /] deploy app-a.war --name=A.war
[standalone@localhost:9990 /] deploy app-b.war --name=B.war
[standalone@localhost:9990 /] deployment-info 
NAME  RUNTIME-NAME PERSISTENT ENABLED STATUS 
A.war A.war        true       true    OK     
B.war B.war        true       true    OK

アンデプロイは自分で指定したNAMEでやります。

[standalone@localhost:9990 /] undeploy A.war
[standalone@localhost:9990 /] undeploy B.war

--runtime-nameオプションを指定してデプロイ

どちらもapp.warというruntime-nameで起動しようとしてみます。

[standalone@localhost:9990 /] deploy app-a.war --runtime-name=app.war
[standalone@localhost:9990 /] deployment-info 
NAME      RUNTIME-NAME PERSISTENT ENABLED STATUS 
app-a.war app.war      true       true    OK     
[standalone@localhost:9990 /] deploy app-b.war --runtime-name=app.war
{"JBAS014653: Composite operation failed and was rolled back. Steps that failed:" => {"Operation step-1" => "JBAS018785: There is already a deployment called app-a.war with the same runtime name app.war"}}

app-b.warのほうは、runtime-nameがかぶってしまったため、デプロイ失敗しました。
この状態で http://localhost:8080/app/ にアクセスすると「Hello, A」と表示されます。

次に、app-a.wardisabled状態に変えて、app-b.warをデプロイしてみます。

[standalone@localhost:9990 /] undeploy app-a.war --keep-content
[standalone@localhost:9990 /] deploy app-b.war --runtime-name=app.war
[standalone@localhost:9990 /] deployment-info 
NAME      RUNTIME-NAME PERSISTENT ENABLED STATUS  
app-a.war app.war      true       false   STOPPED 
app-b.war app.war      true       true    OK

この状態で http://localhost:8080/app/ にアクセスすると「Hello, B」という表示に変わっています。

まとめ

  • nameは管理上利用する名称
    • デプロイ・アンデプロイ時のコマンドの引数として与える
    • ユニークでなければならない
  • runtime-nameはURLの一部となる
    • ユニークである必要はない
    • 同一のruntime-nameのものは、どれか1つしかデプロイ状態にできない

WildFly 8.1.0.Finalのインストールからアプリケーションのデプロイまで

環境

インストール

ダウンロードしてきて展開するだけ

$ curl -LO http://download.jboss.org/wildfly/8.1.0.Final/wildfly-8.1.0.Final.tar.gz
$ tar xvfz wildfly-8.1.0.Final.tar.gz

起動

standalone.shを実行するだけ

$ cd wildfly-8.1.0.Final/bin
$ ./standalone.sh
...(略)...
01:37:43,003 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-6) JBAS017519: Undertow HTTP listener default listening on /127.0.0.1:8080
01:37:43,463 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-4) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS]
01:37:43,558 INFO  [org.jboss.as.server.deployment.scanner] (MSC service thread 1-4) JBAS015012: Started FileSystemDeploymentService for directory /Users/tabira/local/app/wildfly-8.1.0.Final/standalone/deployments
01:37:44,038 INFO  [org.jboss.ws.common.management] (MSC service thread 1-6) JBWS022052: Starting JBoss Web Services - Stack CXF Server 4.2.4.Final
01:37:44,132 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management
01:37:44,133 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
01:37:44,134 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.1.0.Final "Kenny" started in 5951ms - Started 184 of 233 services (81 services are lazy, passive or on-demand)

http://localhost:8080/ にアクセスして「Welcome to WildFly 8. Your WildFly 8 is running.」と出たらOK

設定

CLIツールを利用する

今回は、アクセスログの有効化を行ってみる

管理コンソールにつなぐ

$ ./jboss-cli.sh
You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.
[disconnected /] connect

--connect or -cオプションを付けて起動すると、つないだ状態でプロンプトを出してくれる

アクセスログの有効化設定

[standalone@localhost:9990 /] /subsystem=undertow/server=default-server/host=default-host/setting=access-log:add
{"outcome" => "success"}

アクセスログに関する設定確認

[standalone@localhost:9990 /] /subsystem=undertow/server=default-server/host=default-host/setting=access-log:read-resource
{
    "outcome" => "success",
    "result" => {
        "directory" => expression "${jboss.server.log.dir}",
        "pattern" => "common",
        "prefix" => "access_log",
        "rotate" => true,
        "suffix" => ".log",
        "worker" => "default"
    }
}

設定の再読み込み

[standalone@localhost:9990 /] :reload
{
    "outcome" => "success",
    "result" => undefined
}

サンプルアプリケーション

wildfly-sample-appというプロジェクトを作成

$ mvn archetype:generate -DgroupId=com.mythosil -DartifactId=wildfly-sample-app -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
$ cd wildfly-sample-app
$ vim src/main/webapp/index.jsp
<html>
  <head>
    <title>Hello, Wildfly!</title>
  </head>
  <body>
    <h1>It Works!!</h1>
  </body>
</html>
$ mvn package

デプロイ

$ ./jboss-cli.sh -c
[standalone@localhost:9990 /] deploy wildfly-sample-app.war
[standalone@localhost:9990 /] deployment-info 
NAME                   RUNTIME-NAME           PERSISTENT ENABLED STATUS 
wildfly-sample-app.war wildfly-sample-app.war true       true    OK

http://localhost:8080/wildfly-sample-app/ にアクセスすると「It Works!!」と表示される

アンデプロイ

[standalone@localhost:9990 /] undeploy wildfly-sample-app.war

終了

Ctrl+Cでも終了できるが、せっかくなのでCLIツールを使ってみる

$ ./jboss-cli.sh -c --command=:shutdown
{"outcome" => "success"}

参考資料

Dockerでapacheを動かす

Dockerのコンテナでapacheを動かすまでのメモ

環境

ファイル構成

vagrant$ find .
.
./Dockerfile
./htdocs
./htdocs/index.html

vagrant$ cat htdocs/index.html
<!DOCTYPE html>
<html>
  <body>
    <h1>Hello Docker!</h1>
  </body>
</html>

Dockerfile

  • ubuntu:12.04ベース
  • aptでapache2をインストール
  • ホストのhtdocsディレクトリの中身をコンテナの/var/www配下に転送
  • 80番ポートをexpose
  • コンテナ起動時にapacheを起動
FROM ubuntu:12.04

MAINTAINER mythosil

RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y install apache2

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2

ADD ./htdocs /var/www

EXPOSE 80

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

イメージ作成

"apache"という名前でイメージ作成

vagrant$ docker build -t apache .

(vagrantユーザをdockerグループに入れてあるのでsudo不要)

コンテナ起動

ホストの8080番ポートからコンテナの80番ポートへリダイレクト

vagrant$ docker run -p 8080:80 -d apache

apacheへアクセス

vagrantで起動したubuntuのIPは192.168.33.10としています。

osx$ curl http://192.168.33.10:8080/
<!DOCTYPE html>
<html>
  <body>
    <h1>Hello Docker!</h1>
  </body>
</html>

vagrantで起動しているUbuntuを通してコンテナ内のapacheへアクセスできました。

ログの取り出し

vagrant$ docker ps -l
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                  NAMES
19ac2f09725a        apache:latest       /usr/sbin/apache2 -D   34 minutes ago      Up 34 minutes       0.0.0.0:8080->80/tcp   ecstatic_fermat
vagrant$ docker cp 19ac2f09725a:/var/log/apache2 .
vagrant$ ls apache2
access.log  error.log  other_vhosts_access.log

コンテナ停止

vagrant$ docker stop 19ac2f09725a

参考

さくらVPS(CentOS6.4)でDockerを使う

Docker 0.7からaufs以外のstorage driverがサポートされてCentOSでもDockerが使えるようになりました。
aufsがサポートされていなければ、起動時にdevicemapperを利用してくれるとのことです。devicemapperもサポートされていなければvfsを利用。

CentOSにはepel使って簡単にインストールできるようになったので、さくらVPSで使ってみました。

# CentOSのバージョンは6.4
$ cat /etc/redhat-release
CentOS release 6.4 (Final)

インストール・起動

epelリポジトリが登録されていればyum一発で入ります。

$ sudo yum -y install docker-io
$ sudo service docker start

centosイメージを取得

$ sudo docker pull centos
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              6.4                 539c0211cd76        8 months ago        300.6 MB (virtual 300.6 MB)
centos              latest              539c0211cd76        8 months ago        300.6 MB (virtual 300.6 MB)

mysql-serverをインストール(失敗)

Dockerfileを書いてmysql-serverをインストールしてみます。

$ cat Dockerfile
FROM centos
RUN yum -y install mysql-server
$ sudo docker build -t mysql-server .
...(省略)...
Error: Cannot retrieve repository metadata (repomd.xml) for repository: base. Please verify its path and try again
Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os error was
14: PYCURL ERROR 6 - "Couldn't resolve host 'mirrorlist.centos.org'"
Error build: The command [/bin/sh -c yum -y install mysql-server] returned a non-zero code: 1

エラー・・・

コンテナが参照するDNSを変更

上記エラーについて深く追ってはいないのですが、DNSを変更すればうまく動きました。
考えられるやり方は2つ。

  • /etc/resolv.confを書き換えたイメージ作成してそれを利用
  • dockerサービス起動時のオプションでDNS指定

今回は後者でいきます。

# 起動時オプションを指定
$ cat /etc/sysconfig/docker
other_args="-dns 8.8.8.8"
# dockerサービス再起動
$ sudo service docker restart

mysql-serverをインストール(成功)

Dockerfileは全くいじる必要ありません。

$ sudo docker build -t mysql-server .
...(省略)...
Loaded plugins: fastestmirror
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package mysql-server.x86_64 0:5.1.71-1.el6 will be installed
...(省略)...
Complete!
 ---> 2e4d9c9867c3
Successfully built 2e4d9c9867c3

補足

Dockerfileで構築する場合("docker build"でやる場合)には、dockerサービスの起動時オプションでDNSを指定する必要があります。
"docker run"の場合は引数でDNSを指定できます。

$ sudo docker run -dns 8.8.8.8 -t centos ping -c 3 yahoo.co.jp

感想

VPSが貧弱だからか、それともaufsが使えないからなのか分からないのですが、コンテナ起動に時間がかかります・・・。

CentOS6.4ではstorage driverにvfsを使うようです。

$ sudo docker info
Containers: 1
Images: 2
Driver: vfs

選択文字列を検索するChrome Extension

選択文字列をキーバインド一発でYahooなりGoogleなりで検索する方法が無いかなと思って探してみたけれども、意外と見つからなかったので作ってしまいました。

Chromeのデフォルトの機能として、選択文字列を右クリックすれば検索するメニューが表示されますが、この1アクションさえも面倒くさいと感じる人は少なくないと思います。
他にも選択文字列を検索するextensionはありますが、検索エンジンを選択するポップアップが表示されたりと、結局1アクション余分なものしか見つかりませんでした。

今回作ったExtensionの機能はシンプルなもので、文字列を選択した状態で「Command+Enter」を押せば、新しいタブでYahooでの検索結果が表示されるというものです。

https://github.com/mythosil/chrome-selection-search

ファイル構成

  • chrome-selection-search/
    • manifest.json
    • selection-search.js
    • background.js

manifest.json

{
  "manifest_version": 2,
  "name": "Selection-Search",
  "description": "Search the selected words in a new tab",
  "version": "1.0",
  "background": {
    "persistent": false,
    "scripts": [ "background.js" ]
  },
  "content_scripts": [{
    "matches": [ "http://*/*", "https://*/*" ],
    "js": [ "selection-search.js" ]
  }]
}

タブ操作には通常パーミッションが必要となりますが、今回はchrome.tabs.createしか使わないため不要です。

selection-search.js

window.addEventListener('keydown', function(e) {
  if (e.metaKey && e.keyCode == 13) {
    var text = window.getSelection().toString();
    if (text.length > 0) {
      chrome.extension.sendMessage({ text: text }, function(response) {});
    }
  }
}, false);

macのCommandキーが押されていると、e.metaKeyがtrueとなります。
EnterキーのkeyCodeは13です。
この部分は好みのキーバインドに書き換えて使ってください。

background.js

chrome.extension.onMessage.addListener(function(req, sender, callback) {
  if (sender.tab) { // from a content script
    if (req.text !== undefined) {
      var url = encodeURI("http://search.yahoo.co.jp/search?ei=UTF-8&fr=crmas&p=" + req.text);
      var properties = { url: url };
      chrome.tabs.create(properties, function(tab) {});
    }
  }
});

補足

content script内ではchrome.tabsがundefinedとなっているため、backgroundにメッセージを投げてタブ操作をさせるというややこしいことをしています。
実際は、こんなまわりくどいことをしなくても、window.openを使えばbackground.jsは不要です。
メッセージパッシングを使ってみたかっただけです。

疑問

検索エンジンが決めうちになっていますが、Chromeのデフォルトで設定されている検索エンジンを使いたいです。これを取得するAPIはあるのでしょうか。