冥冥乃志

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

follow us in feedly

gradle-dockerプラグインでDockerfileをビルド時に生成する

前回の続き。要改善点を退治していきます。

mao-instantlife.hatenablog.com

【おさらい】要改善なところ

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

ビルド時にテストをスキップするところは、 circle.ymlbuildDocker タスク実行時に -x test つければ良いだけの話だったので、gradleもっと勉強しろ、で終了な話でした。

registry 項目でハマる

前回、

最初のやつは試しかけてたんですが、buildDockerタスクが突然無言になったのでちょっと後日に回します。

と書いていましたが、なんで無言になったんでしょうねえ。。。どうもローカルのdockerホストにはイメージが作られているみたいなので確認してみます。

$ docker images
REPOSITORY                                  TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
tutum.co/tutum-private-sample               1.3-SNAPSHOT        597ce97c7755        2 minutes ago       668.6 MB

shinsukeabe/tutum-private-sample            1.3-SNAPSHOT        e9804acf2a95        17 hours ago        668.6 MB
tutum.co/shinsukeabe/tutum-private-sample   1.0-SNAPSHOT        ea5233a18ba7        19 hours ago        668.6 MB
tutum.co/shinsukeabe/tutum-private-sample   1.1-SNAPSHOT        ea5233a18ba7        19 hours ago        668.6 MB
java                                        8                   de4a13c84f53        6 days ago          641.9 MB
java                                        latest              de4a13c84f53        6 days ago          641.9 MB

registrytutum.co と指定したときに無言になった後のイメージです。明らかに怪しい奴がいますね。。。 tutum.co/tutum-private-sample とか。期待していたのは registry/group の状態で生成されることだったのですが、 registry を指定するとリポジトリの生成時に group が無視されてしまうようです。つまりアプローチとしては以下のどちらか。

  • groupサーバ名/ユーザ名 にするか
  • registryサーバ名/ユーザ名 にするか

各設定の役割から考えたら明らかに後者ですね。とりあえず今のイメージ消してやってみると無言になることもなくうまくpushできました。どうやらリポジトリのユーザを指定できていない状態でpushしようとしていたからTutumに弾かれていたようです。というか1時間だんまりとかやめて、エラーで落として。

というわけで最終的なbuild.gradleは以下のような感じに。

group "shinsukeabe"
version '1.3-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
    registry = “${System.getenv()[’TUTUM_URL’]/shinsukeabe"
    baseImage 'java:8'
    volume "/tmp"
    addFile "${applicationName}-${version}.jar", "app.jar"
    runCommand "bash -c 'touch /app.jar'"
    entryPoint(["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"])
    doFirst {
        copy {
            from jar
            into stageDir
        }
    }
}

gradle-docker プラグインを使ってDockerfileを生成する

先ほどの build.gradle は、 gradle-docker プラグインを使ったDockerfileの生成にも対応しています。Dockerfileの各設定項目に対応するメソッドは用意されているので、ドキュメントを見ながら先に作ったDockerfileの項目とマッピングしただけです。

アプリケーションのjarファイルを addFile している箇所について相対パスも指定していないので少し補足。 gradle-docker プラグインでdockerコマンドを実行する際のワーキングディレクトリが build/docker で、そこにDockerfileが出力されます。 doFirst で実行しているコピーでビルドしたjarファイルがワーキングディレクトリである build/docker にコピーされるので、 addFile の指定はファイル名のみで構いません。

アプリケーションのjarファイル名は applicationName と定義済みのバージョンでbuild.gradeに定義した内容が生成されるようにしてます。なんかバージョンまで含めたjarファイル名が取得できそうな気がするけど、どれがそうなのかよくわかりませんでした。。。

なお、 entryPoint はリストが引数となるメソッドなのですが、カッコを省略すると読み込み専用フィールドへのアクセスと解釈されてビルド時にエラーになったためカッコをつけています。

よしよし、これでDockerfileは不要となりました。

まとめ

早くTutumの料金プランが発表にならないかなあ。Github -> CircleCI -> Tutumという流れが楽すぎる。

リポジトリです。ご査収ください。

github.com