CI(継続的インテグレーション)をはじめる上で、テストビルドする環境は毎回リセットされる方が都合が良いです。余計なデータが残っていたためにテストに失敗したり、逆に成功したりと言った不正確性のが残るのはよくありません。

そこで登場したCIサーバがDroneです。Dockerを使ってテスト環境を毎回構築、破棄してくれます。しかもDroneのCI環境構築についてもDockerを使って簡単にできます。ぜひ新しいCIサーバとしてチェックしてください。

なおDroneはWebサービスも提供しており、オープンソースのプロジェクトについては無料、5つのプライベートプロジェクトチェックで25ドル/月からとなっています。

Droneのトップページ
Droneのトップページ

Droneのインストール

今回はさくらのクラウドを使ってCoreOSを立ち上げています。

ログインしたら joaodubas/docker-droneio をpullします。

$ git pull https://github.com/joaodubas/docker-droneio.git
$ cd docker-droneio
$ ls -al
total 24
drwxr-xr-x 1 core core  106 Nov 18 17:13 .
drwxr-xr-x 1 core core  126 Nov 18 17:02 ..
drwxr-xr-x 1 core core  122 Nov 18 17:02 .git
-rw-r--r-- 1 core core  706 Nov 18 17:02 Dockerfile
-rw-r--r-- 1 core core 1083 Nov 18 17:02 LICENSE
-rw-r--r-- 1 core core 3336 Nov 18 17:02 README.md
-rw-r--r-- 1 core core   18 Nov 18 17:02 REPOSITORY
-rw-r--r-- 1 core core    9 Nov 18 17:02 TAG
-rw-r--r-- 1 core core  274 Nov 18 17:13 drone.toml

このまま立ち上げるとユーザ登録ができない(open=falseになっています)ので、drone.tomlを編集します。編集後は以下の通りです。

$ cat drone.toml 
[database]
driver="sqlite3"
datasource="/var/lib/drone/drone.sqlite"


[registration]
open=true

[github]
client = "GITHUB_CLIENT_KEY"
secret = "GITHUB_SECRET_KEY"
[worker]
nodes=[
  "unix:///var/run/docker.sock",
  "unix:///var/run/docker.sock"
]

今回は対象になるリポジトリとしてGitHubを指定しています。この場合、クライアントキーとシークレットキーを生成します。

New OAuth Applicationへ飛び、新しいアプリケーションを作成します。

  • Application name は任意です。
  • Homepage URL はサーバのIPアドレスを指定しています。例) http://133.242.21.16:8080
  • Authorization callback URL はHomepage URLと同じにしておきます。例) http://133.242.21.16:8080

これで登録すると、次のように Client ID と Client Secret が生成されますので、drone.toml のclient/secretにそれぞれ設定します。

DroneはGitHubの他、GitHub Enterprise、Gitlab、Gogs、Bitbucketに対応しています。

Droneの立ち上げ

設定ファイルの編集が終わったらDockerをビルドします。

$ docker build -t moongift:drone .

名称(moongift:drone)は適当に設定してください。ビルドが終わるとコンテナイメージが確認できます。

$ docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
moongift                 drone               aa16c298af3a        About an hour ago   333.1 MB

では立ち上げます。hostnameは適当に変更してください。

$ docker run -d --name droneio \
--hostname 133.242.21.16 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
-p 8080:8080 \
moongift:drone

これでサーバのIPアドレス:8080でDroneが立ち上がります。

リポジトリの指定

まず http://サーバのIPアドレス:8080/ にアクセスします。

Droneログイン画面
Droneログイン画面

GitHubと出ていますのでクリックしてOAuth認証してください。

コールバックで戻ってくるとリポジトリの指定になります。ACTIVATEをクリックするとリポジトリがDroneの監視対象になります。

Droneダッシュボード
Droneダッシュボード

一覧からの指定もできます。

リポジトリ一覧
リポジトリ一覧

ここから選択してリポジトリの登録が完了です。この時点でコミットフックなど、必要な設定が完了しています。

リポジトリの登録完了画面
リポジトリの登録完了画面

こちらは詳細設定です。

詳細設定画面
詳細設定画面

設定の中に環境変数の指定があります。パスワードやトークン、シークレットトークンなどはこちらにYAML形式で書いておけるようになっています。そのほかGitHubへアクセスするための公開鍵や、README.mdに記述するビルドステータスバッチのスニペットも表示されています。

Droneの環境変数設定
Droneの環境変数設定

試してみる

まずリポジトリの中に .drone.yml というファイルを作成します。これがDroneの設定ファイルです。例えば以下のような記述になります。

image: go1.3
git:
  path: github.com/drone/drone
env:
  - GOROOT=/usr/local/go
  - PATH=$PATH:$GOROOT/bin:$GOPATH/bin
script:
  - sudo apt-get -y install zip libsqlite3-dev sqlite3 rpm 1> /dev/null 2> /dev/null
  - gem install fpm
  - rbenv rehash
  - make deps
  - make test
  - make test_postgres
  - make test_mysql
  - make packages
services:
  - postgres
  - mysql
notify:
  email:
    recipients:
      - brad@drone.io
  gitter:
    room_id: $$GITTER_ROOM
    token: $$GITTER_KEY
    on_started: false
    on_success: true
    on_failure: true

publish:
  s3:
    acl: public-read
    region: us-east-1
    bucket: downloads.drone.io
    access_key: $$AWS_KEY
    secret_key: $$AWS_SECRET
    source: packaging/output/
    target: $DRONE_BRANCH/
    recursive: true
    when:
      owner: drone

$$ではじまるものは先ほどの設定画面で定義した環境変数が使われます。

まずimageでDockerのコンテナイメージを指定しています。さらにリポジトリ、セットアップ用のスクリプトになります。サービスはデータベースで、MySQL/PostgreSQL/RabbitMQ/Redis/memcached/Cassandra/Couchdb/MongoDBなどが指定できます。これらのシステムと連携する場合に指定します。

さらにnotifyでテスト成功または失敗時の通知先を指定します。メール、Gitter、Slack、HipChat、Flowdock、IRC、WebHookが指定可能です。例えばSlackの指定は次のようになります。

notify:
  slack:
    username: foo
    token: c90f0e53d4973302fe0b6159488423d6
    team: bar
    channel: baz
    on_started: false
    on_success: true
    on_failure: true

publishはテストが成功した時のデプロイ先になります。Amazon S3、Swift、PyPI、NPM、Docker、GitHubが指定可能です。パッケージを作ってリリースと言った形を想定しています。

ビルド結果。新しいビルドが走ると通知されます。
ビルド結果。新しいビルドが走ると通知されます。

ファイルを作ったら後はGitでpushすれば自動的にテストが実行されます。初回はコンテナイメージの取得があるので若干時間がかかります。その結果もDrone上で確認が可能です。

テスト状況が表示されます。
テスト状況が表示されます。

Dockerコンテナ

Droneでは公式Dockerコンテナイメージを配布しています。

  • Dart
  • Erlang
  • Go
  • Haskell
  • Node
  • PHP
  • Python
  • Ruby

が用意されており、今後Java(Clojure、Scala、Groovy)、Perl、Rustなどが追加予定となっています。これらのスクリプトをベースにすればDroneのテストは容易になりますが、設定ファイル(.drone.yml)上でscriptがあまり多いと実行に時間がかかるようになると思われます。公式コンテナイメージをベースとしつつ、カスタマイズしたコンテナイメージを用意するのが良いのではないでしょうか。


テストのたびに環境を構築、破棄するというのはとてもDockerらしい使い方だと思います。データベースとディレクトリを変えるだけでは分からない、余計なライブラリの関連性で不具合を起こしたり、本番環境とテスト環境の差異を最小限にとどめられるようになるのではないでしょうか。

Jenkinsに比べるとまだまだ機能が不足している感はありますが、今後主流になっていくであろう仮想環境を使ったCIサーバとして注目ではないでしょうか。

Continuous Integration · drone.io