これまでサービスで使うCPANモジュールの管理と言えばrpm/debパッケージが主流だと思いますが、最近ではperlbrewで使いたいバージョンのperlをインストールすることもあり、rpm/debでは対応できなくなってきています。

perlbrewのperlに対してプロジェクトが依存しているCPANモジュールを入れる際、

$ perlbrew switch perl-5.12.3
$ cd /path/to/MyProj
$ perl Makefile.PL
$ cpanm --installdeps .

などと cpanm —installdeps が使えます。

しかし、これではサーバを新規セットアップするたびに、最新のモジュールが入ることになりサーバ間でモジュールのバージョンの差異が生まれる可能性があります。

そこで対応策として考えられるのが開発サーバで—installdepsを実行し、perlbrewのディレクトリごと本番サーバにrsyncする方法です。しかしこの方法はOSのアーキテクチャ変更やメジャーバージョンの変更、ディストリビューションの変更に弱いという問題があります。もしアーキテクチャが変更された場合は本番サーバ、開発サーバの両方用意してperlbrewとCPANモジュールを入れ直す必要がありますが、その際に元の開発サーバと同じバージョンのモジュールが入る保証はありません。

そこで、プロジェクトが依存しているCPANモジュール(とそのCPANモジュールが依存しているモジュール)を全てローカルにダウンロードし、プロジェクトのディレクトリ内で外部依存が無いCPANの部分ミラーを作成し、cpanmでそのミラーだけからモジュールをインストールするという手段を考えました。

まず、DarkPAN(CPAN for intranet) の管理ツールであるOrePANをインストールします。変更がまだあるので自分のforkから

$ cpanm https://github.com/kazeburo/OrePAN/tarball/master

これで、orepan.pl と orepan_index.pl というのが入ります。このコマンドでローカルのCPANミラーのindexを生成できます。

次に、依存モジュールのdownloadだけを行うオプションを追加したcpanmを持ってきます。適当patchなので、これも自分のforkから

$ curl -LO https://github.com/kazeburo/cpanminus/raw/master/cpanm > cpanm
$ chmod +x ./cpanm

このcpanmを使って依存モジュールのダウンロードを行います

$ cwd
/path/to/MyProj
$ perl Makefile.PL
$./cpanm --dpan=./cpan --installdeps .
--> Working on .
Configuring /path/to/MyProj ... OK
==> Found dependencies: Router::Simple::Sinatraish, Tiffany, Module::Find
--> Working on Router::Simple::Sinatraish
Fetching http://search.cpan.org/CPAN/authors/id/T/TO/TOKUHIROM/Router-Simple-Sinatraish-0.02.tar.gz ... OK
Configuring Router-Simple-Sinatraish-0.02 ... OK
Copy to /path/to/MyProj/cpan/authors/id/T/TO/TOKUHIROM/Router-Simple-Sinatraish-0.02.tar.gz
--> Working on Tiffany
Fetching http://search.cpan.org/CPAN/authors/id/T/TO/TOKUHIROM/Tiffany-0.03.tar.gz ... OK
Configuring Tiffany-0.03 ... OK
Copy to /path/to/MyProj/cpan/authors/id/T/TO/TOKUHIROM/Tiffany-0.03.tar.gz
..

extlibにモジュールを導入する際は、-l や -L オプションも一緒に使います

$./cpanm -l extlib —dpan=./cpan —installdeps .

./cpanディレクトリにCPANと同じディレクトリ構造で依存モジュールのダウンロードしていきます。インストールはされません

$ find ./cpan -name "*.tar.gz" 
./cpan/authors/id/C/CR/CRENZ/Module-Find-0.10.tar.gz
./cpan/authors/id/T/TO/TOKUHIROM/Router-Simple-Sinatraish-0.02.tar.gz
./cpan/authors/id/T/TO/TOKUHIROM/Tiffany-0.03.tar.gz

全てのダウンロードが終わったら、今度はindexを作成します。先ほどインストールしたOrePANを使います

$ orepan_index.pl --repository ./cpan
...
2011-02-03T17:24:45 [INFO] Save cpan/modules/02packages.details.txt.gz at /...

これでcpan/modules以下にindexファイルができ、CPANミラーの準備ができました。このミラーのディレクトリはVCSでプロジェクトと同様に管理してしまうのがよさげです。

このミラーからモジュールを導入する場合は

$ cpanm --mirror file:///path/to/MyProj/cpan --mirror-only --installdeps .

このようにmirrorとmirror-onlyのオプションを使います。これで外部にモジュールを取りにいくことはなく、ローカルのみから依存モジュールを一括で導入可能です。

もし、依存モジュールが増えたり、依存モジュールのバージョンが新しくなった場合は Makefile.PL を更新しもう一度 cpanmを動かします

$ vim Makefile.PL
$ perl Makefile.PL
$ ./cpanm --dpan=./cpan --installdeps .

今度は、cpanmがcpan/modulesディレクトリ中の02packages.details.txt.gzを読み込んで必要なモジュールだけダウンロードします。依存モジュールのどこかで明示的に書かれていない限り勝手にバージョンがあがってしまう事はありません。

そしてindexを再生成します

$ rm -f ./cpan/modules/02packages.details.txt.gz
$ orepan_index.pl --repository ./cpan

モジュールを減らす場合はcpan/authorディレクトリから削除して、同じ様にindexを作り直せば完了です

この方法の良い点として、おまけ的ですが、search.cpan.orgが止まっていたり、グローバルにアクセスできない場所でも問題なく依存モジュールがインストール可能であること、ダウンロードの手間が無いのでインストールがちょっと高速になることも挙げられます。

いかがでしょうかNe。

このブログ記事について

このページは、Masahiro Naganoが2011年2月 3日 17:38に書いたブログ記事です。

ひとつ前のブログ記事は「Plack::Builder::Conditionals をリリースしました」です。

次のブログ記事は「本当は難しいCPANモジュールのバージョン特定」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja