wercker は最近人気のクラウド型 CI ツールで、 docker イメージ上で CI を動かすことができるのが直感的で分かりやすいですし、github の private リポジトリでも無料で連携することができるのが個人的にはありがたいです。
個人的にもいくつかの言語で使用していますが、ここでは wercker 上で Java プログラムをビルドする一連の流れを書いていこうと思います。
ユースケース
ここでは、以下のユースケースにもとづいて、実際の設定例を記述します。
- Java のプロジェクトを Maven で管理し、CI を実施。
- clean && package
- sonar:sonar
- CI 済みの環境を docker image に登録
- 今回は Amazon ECR
Workflows
今回は以下のようにしています。
- build
- wercker 起動時に最初に実行される pipeline。今回は特別な処理をせずに、メッセージの表示などを行っている
- maven
- maven に関する様々な処理を実施
- 成功 / 失敗時に Slack に通知
- docker (master のみ)
- docker image の ECR への push を実施
Pipeline: build
デフォルトの pipeline なのでそのまま残していて、ちょっとしたメッセージを出しているだけです。実際には後続の処理において必要なファイルの作成やコピーなどがあればこちらで行うことになります。
box: busybox
build:
steps:
- script:
name: echo
code: |
echo " ${WERCKER_GIT_REPOSITORY}"
Pipeline: maven
maven を実行します。java と maven コマンドが使えるように box には maven を指定しています。
maven:
box: maven:3.5.2-jdk-8-alpine
steps:
- java/maven:
goals: clean package
cache_repo: true
- java/maven:
goals: sonar:sonar
maven_opts: -Dsonar.host.url=${SONAR_URL} -Dsonar.login=${SONAR_LOGIN_KEY}
cache_repo: true
- script:
name: copy to output
code: |
cp target/sada4j-*.jar $WERCKER_OUTPUT_DIR/sada4j.jar
after-steps:
- slack-notifier:
url: ${SLACK_WEBHOOK_URL_NOTIFY}
channel: ${SLACK_ROOM_NOTIFY}
notify_on: failed
username: wercker maven notify
ここで実行していることについて、要点をピックアップします。
java/maven step を用いた maven の実行
wercker にはあらかじめ maven 実行用の Step が定義されており、maven 実行時には step に java/maven を指定してあげると、maven の実行環境を自動的に構築してくれます。
指定可能なオプションなど詳細は以下のドキュメントを参照ください。
https://github.com/wercker/step-maven
環境変数の使用
worcker では環境変数を使用することができます。
http://devcenter.wercker.com/docs/environment-variables
Environment のレベルは以下の三種が定義できるようになっています。必要に応じて設定のスコープを調整する形になります。
- Organization Level
- Application Level
- Pipeline Level
なお wercker が標準でサポートしている環境変数は以下になります。
http://devcenter.wercker.com/docs/environment-variables/available-env-vars
$WERCKER_OUTPUT_DIR への実行結果の保存
wercker では CI プロセスが docker container 上で行われることもあって、異なる Pipeline 間では通常はファイルが引き継がれません。
後続の Pipeline でもファイルを使用可能にする場合は、 ${WERCKER_OUTPUT_DIR}
で指定されているディレクトリにファイルを置く必要があります。
上記の例では、後続の docker image 生成処理のために、docker image に含めるファイル群を ${WERCKER_OUTPUT_DIR}
に設置しています。
after-steps による Slack 通知
after-steps を使用すると Pipeline 中の処理が正しく動いてもそうでなくても必ず実行される Step を定義することが出来ます。
上記例では、 slack-notifier step を使用して Slack の通知を行っています。
slack-notifier の場合は notify_on: failed
と記述しておくと step の処理が fail になった時のみ通知を送ることができます。
Pipeline: docker
docker image を Amazon ECR に push をします。
Wercker では internal/docker-push という step を用いることで、任意の docker image を docker repository に push することが出来ます。
wercker の公式ドキュメントでは以下の docker repository についての例が記述されていますが
- Docker Hub
- Quary.io
- Google Container Registry
ここでは ECR への push の仕方を例示しています。
docker:
box: openjdk:8-jdk-alpine
steps:
- internal/docker-push:
aws-access-key: ${AWS_ACCESS_KEY_ID}
aws-secret-key: ${AWS_SECRET_ACCESS_KEY}
aws-region: ${AWS_REGION}
aws-registry-id: ${AWS_REGISTRY_ID}
aws-strict-auth: false
repository: sada4j
tag: latest
ports: 8080
working-dir: ${WERCKER_SOURCE_DIR}
entrypoint: java -jar sada4j.jar
汎用的な話
wercker による docker push は、Dockerfile を用いた docker build の定義を記述することは出来ません。
以下のようなルールで docker image が作られます。
- box として指定された docker image が base image となる
- box 上に置かれたファイルがまとめて ADD or COPY される
- box 上の状態がそのまま docker Image となると思ったほうが良いかも
- 以下のコマンド指定は、wercker.yml の中で明示的に記述する必要がある
- CMD
- ENTRYPOINT
- EXPOSE
- ENV
- VOLUME
- AUTHOR
指定可能なオプションの詳細については以下を参照ください。
http://devcenter.wercker.com/docs/steps/internal-steps#docker-push
上記のような仕様となっているため、運用上は以下のようなことに配慮する必要があります。
- box 上に存在する不要なファイルを取り除く
- 一番手っ取り早いのは、今回の例のようにパッケージングと docker push を別の Pipeline で定義し、必要最低限のファイルだけ ${WERCKER_OUTPUT_DIR} 経由で渡すようにすることです。
- Dockerfile / docker-compose.yml との住み分け
- 「Can I Build Dockerfiles?」 「Currently, no.」 http://devcenter.wercker.com/docs/faq/can-i-build-dockerfiles
- なので基本的に二重記述になります。うまい解決策はないものか…
Amazon ECR 固有の話
ECR に push する場合は、以下の値を設定します。
- aws-access-key
- aws-secret-key
- aws-region
- aws-registry-id
- 数字のアカウント ID です。
- repository (option)
- tag (option)
credential 情報は wercker.yml に直に書くのは好ましくないので、wercker の環境変数に設定することになります。
以上で、ひととおりユースケースどおり Java のビルドから docker repository への push まで行えるようになると思います。
その他の Tips
wercker-cli
wercker が他の CI SaaS とくらべて圧倒的に勝っていると感じているのが、local 環境で動作確認を行うために使えるツールの充実です。
wercker には wercker-cli というコマンドラインツールが提供されており、サーバー上での挙動をローカル環境でも再現し実行することが出来ます。
$ wercker build --pipeline maven
--> No Docker host specified, checking: /var/run/docker.sock
--> Executing pipeline
--> Running step: setup environment
Pulling from library/openjdk: latest
Digest: sha256:9745ed74401b23fb845b4eb7ae07ecb7dc2d40bece6bdb089975a20f76766401
Status: Image is up to date for openjdk:latest
--> Copying source to container
--> Running step: wercker-init
--> Running step: maven
02:19:34: Hello from the Maven Wercker Step
(snip.)
また、Wercker サーバーに対するビルドの指示など、後述の API で行えることと同等のことも実施可能になっています。
詳しくは以下のサイトや、コマンドのヘルプ等を参照ください。
http://www.wercker.com/cli
なお、現在のところ OSX 版と Linux 版のみ提供されています。
API
以下の API が提供されています。Application の設定や、ビルドの指示などが行なえます。
http://devcenter.wercker.com/docs/api/endpoints
Wercker Source IP
CI / CD フローの都合上、Wercker と特定の社内ツールを結合して使用しなければいけないケースが発生することがあります。
その際は、 Wercker の Source IP アドレスを指定して特定の IP のみ接続許可をするような事が対応としては可能です。
以下のような形で Wercker の Source IP アドレスが公開されているので、参考までに。
https://s3.amazonaws.com/status.wercker.com/worker_ips/production/public.json
ECR に登録されている docker image を box で使用する
wercker.yml の box 指定箇所で以下のように書きます。
box:
id: <docker image name>
aws-access-key: ${AWS_ACCESS_KEY_ID}
aws-secret-key: ${AWS_SECRET_ACCESS_KEY}
aws-region: ${AWS_REGION}
repository: <docker image name>
aws-registry-id: ${AWS_REGISTRY_ID}