Tutumのプライベートレジストリにプッシュしてみる
ちょっと前ですがこんなことをやったので続きです。
mao-instantlife.hatenablog.com
Tutumのプライベートレジストリ
Dockerのライフライクル管理に関する機能については前回触れましたが、各ユーザに対してアカウントごとに10個 *1 のプライベートレジストリが登録できます。Docker Hubだと無料枠で一つだけなので、どちらかというと仕事向けに試すにはTutumの方がありがたかったりします。プライベートレジストリに登録したイメージはサービスを作るときに利用可能です。
ちなみに、サードパーティのレジストリからもリンクさせることが可能ですが、Docker Hub以外にアカウント持っていないので今回は使っていません。
本サービスに移った段階ではよくわかりませんが、beta版のアカウントはそのままfree Developerプランに移行するとあるので、おそらくはこのくらいの数になるのではないかと思います。リポジトリ数とノード数、スタック数あたりで課金が変わってくるのではないかと。
もちろん docker login
も可能なので、空リポジトリ作って外部からpushしたりすることもできます。アカウント作成時に設定したパスワードは、このプライベートジレストリにアクセスするためのパスワードです。
ローカルからプライベートレジストリにpushする
最終的にはCircleCIでイメージビルドをしてpushしますが、まずはローカルで手動交えながら同じことをしてみましょう。
gradle-docker-plugin
でハマる
まずは、Spring Bootのドキュメントにあった gradle-docker
プラグインではなく gradle-docker-plugin
を使ってみました。が、今回の用途では色々問題があって断念。
- spring-bootプラグインが1.3.0.RELEASEだとプラグインのdocker関連タスクが反映されない?
url
(dockerホストのURL)にtcpをサポートしてないのでdocker-machine
を使ってると環境変数からホスト名を直接持ってこれないrepository name component must match "[a-z0-9]+(?:[._-][a-z0-9]+)*”
とか言われる
docker関連タスクは1.2.7であればタスクが反映されます。教えて偉い人。。。
url
はhttpsプロトコルに変えればいけるのですが、dockerホストのURLをリテラルにしたくないので面倒になってしまいました。
最後のやつが一番の問題で、この正規表現だとリポジトリ名に /
が使えないんですよ。ということはDocker Hubにpushするようなイメージも作れないはずなんですよね。その後にタグを指定し直す想定なのでしょうか?
という諸々面倒なだけな感じになったので、公式のドキュメントに従うことにしました。
gradle-docker
プラグインを使う
イメージのビルドまでは公式の通りでうまくいきますが、pushで幾つか設定や変更が必要なことがありました。
Docker Hub以外のレジストリにpushするときのgroup名
以下のような build.gradle
のときにpushしてみたのですが、TutumのレジストリではなくDocker Hubにpushされてしまいました。
group 'shinsukeabe' version '1.0-SNAPSHOT' buildscript { ext { springBootVersion = "1.3.0.RELEASE" } repositories { mavenCentral() jcenter() } dependencies { classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" classpath 'se.transmode.gradle:gradle-docker:1.2' } } apply plugin: 'java' apply plugin: 'idea' apply plugin: 'spring-boot' apply plugin: 'docker' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: "${springBootVersion}" testCompile group: 'junit', name: 'junit', version: '4.11' } task buildDocker(type: Docker, dependsOn: build) { push true applicationName = jar.baseName dockerfile = file('src/main/docker/Dockerfile') doFirst { copy { from jar into stageDir } } }
これは、プラグインのリポジトリ名を以下のルールで生成しているから発生する現象です。
tag=group/applicationName:version
このとき、 group
にレジストリ名が指定されていない場合はデフォルトでDocker Hubになります。
アプリケーション名とバージョンについては applicationName
と tagVersion
という変数で設定の書き換えが用意されていますが、groupについては存在しない模様。そのため、 group tutum/shinsukeabe
と変更しました。
環境変数にTutumのレジストリアクセスに必要な情報をセットしてビルドを実行してみましょう。
$ docker login -e $TUTUM_EMAIL -u $TUTUM_USERNAME -p $TUTUM_PASSWORD $TUTUM_URL $ gradle build buildDocker
pushできました。
CircleCIからpushする
以下のような circle.yml
を作ってGithubにpushしたところ、イメージのデプロイ時にこけました。
machine: java: version: oraclejdk8 services: - docker deployment: hub: branch: master commands: - docker login -e ${TUTUM_EMAIL} -u ${TUTUM_USERNAME} -p ${TUTUM_PASSWORD} ${TUTUM_URL} - gradle build buildDocker
buildDockerタスクが作れないみたいです。CircleCIはGradle Wrapperがあるときは優先的にそちらを使うので、 gradle
ではなく gradlew
で実行しないと依存関係のあるライブラリがキャッシュされてない状態で動いてしまうようです。Gradle Wrapperを利用するように変更したらpushできました。
要改善なところ
- プラグインのGlobal configurationに
registry
を指定するための項目があるが、リポジトリ名生成で反映されている感じがしないので確認してみる - Dockerfileにバージョン入ってるのではまりそう。プラグインからDockerfile生成できるはずなのでもうちょっと頑張る
- buildタスクはテストが走るので、今の
circle.yml
だとテストが2回走る。build時はテストトラップしたい
最初のやつは試しかけてたんですが、buildDockerタスクが突然無言になったのでちょっと後日に回します。それ以外のやつは単に今回面倒くさくなっただけです。
*1:2015年11月17日ベータ版現在