冥冥乃志

ソフトウェア開発会社でチームマネージャをしているエンジニアの雑記。アウトプットは少なめです。

follow us in feedly

Tutumのプライベートレジストリにプッシュしてみる

ちょっと前ですがこんなことをやったので続きです。

mao-instantlife.hatenablog.com

Tutumのプライベートレジストリ

Dockerのライフライクル管理に関する機能については前回触れましたが、各ユーザに対してアカウントごとに10個 *1 のプライベートレジストリが登録できます。Docker Hubだと無料枠で一つだけなので、どちらかというと仕事向けに試すにはTutumの方がありがたかったりします。プライベートレジストリに登録したイメージはサービスを作るときに利用可能です。

ちなみに、サードパーティレジストリからもリンクさせることが可能ですが、Docker Hub以外にアカウント持っていないので今回は使っていません。

support.tutum.co

本サービスに移った段階ではよくわかりませんが、beta版のアカウントはそのままfree Developerプランに移行するとあるので、おそらくはこのくらいの数になるのではないかと思います。リポジトリ数とノード数、スタック数あたりで課金が変わってくるのではないかと。

もちろん docker login も可能なので、空リポジトリ作って外部からpushしたりすることもできます。アカウント作成時に設定したパスワードは、このプライベートジレストリにアクセスするためのパスワードです。

ローカルからプライベートレジストリにpushする

最終的にはCircleCIでイメージビルドをしてpushしますが、まずはローカルで手動交えながら同じことをしてみましょう。

gradle-docker-plugin でハマる

まずは、Spring Bootのドキュメントにあった gradle-docker プラグインではなく gradle-docker-plugin を使ってみました。が、今回の用途では色々問題があって断念。

github.com

  • 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であればタスクが反映されます。教えて偉い人。。。

urlhttpsプロトコルに変えればいけるのですが、dockerホストのURLをリテラルにしたくないので面倒になってしまいました。

最後のやつが一番の問題で、この正規表現だとリポジトリ名に / が使えないんですよ。ということはDocker Hubにpushするようなイメージも作れないはずなんですよね。その後にタグを指定し直す想定なのでしょうか?

という諸々面倒なだけな感じになったので、公式のドキュメントに従うことにしました。

gradle-docker プラグインを使う

spring.io

イメージのビルドまでは公式の通りでうまくいきますが、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になります。

アプリケーション名とバージョンについては applicationNametagVersion という変数で設定の書き換えが用意されていますが、groupについては存在しない模様。そのため、 group tutum/shinsukeabe と変更しました。

環境変数にTutumのレジストリアクセスに必要な情報をセットしてビルドを実行してみましょう。

$ docker login -e $TUTUM_EMAIL -u $TUTUM_USERNAME -p $TUTUM_PASSWORD $TUTUM_URL
$ gradle build buildDocker

pushできました。

f:id:mao_instantlife:20151117165409p:plain

f:id:mao_instantlife:20151117165420p:plain

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できました。

f:id:mao_instantlife:20151117165438p:plain

f:id:mao_instantlife:20151117165459p:plain

要改善なところ

  • プラグインのGlobal configurationに registry を指定するための項目があるが、リポジトリ名生成で反映されている感じがしないので確認してみる
  • Dockerfileにバージョン入ってるのではまりそう。プラグインからDockerfile生成できるはずなのでもうちょっと頑張る
  • buildタスクはテストが走るので、今の circle.yml だとテストが2回走る。build時はテストトラップしたい

最初のやつは試しかけてたんですが、buildDockerタスクが突然無言になったのでちょっと後日に回します。それ以外のやつは単に今回面倒くさくなっただけです。

*1:2015年11月17日ベータ版現在