Docker で Hackage Mirror Server を構築する
どうも僕です。
最近、Hackage 調子悪いですね。
こうも落ちてばかりいると業務に支障をきたしてしまいます。
多くの場合は sandbox 使い回しでなんとかなるのかも知れませんが、新規パッケージ、サーバーから最新版を落としたい場合には辛いものがあります。
なので今回は Dockerを使って Hackage Server を内部に構築する話をしたいと思います。
もちろん本家からミラーリングも行います。
Hackage Server のイメージをビルドする
Hackage Server (Hackage2)のソースは公開されており、githubにあります。
hackage-server
まずはcloneしてきましょう。
$ git clone https://github.com/haskell/hackage-server.git
$ cd hackage-server
このままビルドしてしまいたいところなのですが、新しい ghc (haskell-platform) ではうまくビルドできません。
どうも haskell-platform 2013 が前提のようです。
少し古めの環境というのもありますし、環境を構築するのにいろいろと気をつかうのも大変です。
なので今回は Docker を使ってビルド、および起動まで行います。
リポジトリ内を見ればわかりますが、既に Dockerfile が用意されています。
みんな考えることは同じようです:)
一応既に DockerHub にもイメージがあがっているのですが、これは内容が古くうまくミラーができません。
(zsol/hackage-serverは0.3)
そのため最新版の Hackage Server をビルドする必要があります。
この記事を書いた時点では 0.4.3 です。
基本的には用意されている Dockerfile でイメージを作成すれば良いだけですが、今回は少しアレンジしています。
from zsol/haskell-platform-2013.2.0.0
env HOME /home/haskell
# dependencies
run sudo apt-get update && sudo apt-get -y dist-upgrade
run sudo apt-get -y install unzip libicu48 libicu-dev
run cabal update
run curl -LO https://github.com/haskell/hackage-server/archive/master.zip
run unzip master.zip
workdir /home/haskell/hackage-server-master
run cabal install --only-dependencies
run cabal configure && cabal build
volume ["/home/haskell/hackage-server-master/state"]
cmd echo "Binaries are in ./dist/build/hackage-*"
オリジナル版ではパッケージデータをホストにマウントするVOLUMEがないので追加しています。
この Dockerfile を使ってイメージを作成しましょう。
$ sudo docker build -t="hackage-server" .
....
....
実行すると hackage-server のソースのダウンロードからビルドまでを行ってくれます。
結果、hackage-server というタグのイメージが出来上がります。
Hackage Server のイメージを起動
それでは Hackage Server を起動してみましょう。
起動スクリプト(run-docker.sh)もリポジトリ内にあります。
#!/bin/sh
set -e
ADMIN_USER=admin
ADMIN_PASS=admin
BUILD_RUN_TIME=30
BUILD_INTERVAL=5
DOCKER_IMAGE=hackage-server
server_id=$(sudo docker run -d -p 8080 ${DOCKER_IMAGE} sh -c "./dist/build/hackage-server/hackage-server init --static-dir=datafiles --admin=\"${ADMIN_USER}:${ADMIN_PASS}\" ; ./dist/build/hackage-server/hackage-server run --static-dir=datafiles")
server_ip=$(sudo docker inspect $server_id | grep IPAddress | cut -d'"' -f4)
server_local_port=$(sudo docker port $server_id 8080)
sleep 2 # TODO: poll until web server comes up
sudo docker run -d ${DOCKER_IMAGE} sh -c "echo -e \"${ADMIN_USER}\n${ADMIN_PASS}\" | ./dist/build/hackage-build/hackage-build init http://${server_ip}:8080; ./dist/build/hackage-build/hackage-build build --run-time=${BUILD_RUN_TIME} --interval=${BUILD_INTERVAL} --continuous"
echo "You can access your local hackage at http://localhost:${server_local_port}"
DOCKER_IMAGEはビルドしたイメージ名を設定します。
管理者ユーザーなどは任意で変更して下さい。
また、ミラーした結果をコンテナ外に永続化したい場合には-v
で上記の Dockerfile で設定した VOLUME のパスを設定して下さい。
$ ./run-docker.sh
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You can access your local hackage at http://localhost:0.0.0.0:xxxxx
実行するとコンテナIDとURL(ポート番号)が表示されます。
ブラウザでアクセスして Hackage の画面が表示されるか確認しましょう。
Hackage をミラーリングする
起動しただけの状態ではアップロードはできるかも知れませんが、パッケージも何もありません。
このままでは意味がないので Hackage をミラーリングしましょう。
まず、ミラーを行うため、ミラーグループにユーザーを追加します。
次にミラーリングツールを取得、設定します。
hackage-serverのリポジトリにはミラーリングするためのツール hackage-mirror も含まれています。
これを使用してミラーリングを行います。ミラーリングはコンテナ外から行います。
hackage-mirror も hackage-server 同様にコンテナ内にビルドされています。
そのため、コンテナ内から hackage-mirror を取得します。
先ほどのコンテナIDを使用し、コンテナ内からコピーします
sudo docker cp xxxxxxxxxxx:/home/haskell/hackage-server-master/dist/build/hackage-mirror/hackage-mirror ~/tmp/
使い方は hackage-mirror のヘルプを見れば大体わかります
次にミラーリング設定ファイルを記述します。
http://hackage.haskell.org/
http://admin:admin@localhost:xxxxxx
ミラー元、ミラー先を記述してあるだけのシンプルな設定です。
ミラー先には先ほど立てた Hackage Server のURLを指定します。
あとはこのファイルを指定し、hackage-mirror を実行するだけです。
$ ./hackage-mirror ./mirror.cfg
44823 packages to mirror.
mirroring 3d-graphics-examples-0.0.0.0
mirroring 4Blocks-0.1
mirroring 4Blocks-0.2
...
...
実行し、しばらくするとミラーリングが始まります。
ミラーリングされたパッケージからWebの方にも表示されます。