SpringBootアプリをjibでDocker化する

Google製のJavaをdocker化してくれるアプリでSpringBootのデモアプリをDocker化する

buildscript {
    ext {
        springBootVersion = '2.0.3.RELEASE'
    }
    repositories {
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath "gradle.plugin.com.google.cloud.tools:jib-gradle-plugin:0.9.8"
    }
}

group = 'net.kosasaki.example'
version = '0.0.1-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'com.google.cloud.tools.jib'

dependencies {
        compile('org.springframework.boot:spring-boot-starter-webflux')
        compile('org.springframework.boot:spring-boot-starter-thymeleaf')
        compileOnly('org.projectlombok:lombok:1.18.0')
        compile 'mysql:mysql-connector-java:6.0.6'  
}

jib {
        from {
                image = 'adoptopenjdk/openjdk8:alpine-slim'
        }
        to {
                image = 'sample/jib-demo-app'
        }
        container {
                jvmFlags = ['-Xms512m', '-Xdebug']
                mainClass = 'net.kosasaki.example.WebApplication'
                args = []
                ports = ['8080/tcp']
                useCurrentTimestamp = true
        }

}

build.gradleはこんな感じ。

$ ./gradlew jibDockerBuild

docker images でイメージを確認する

$ docker images
REPOSITORY                                                         TAG                 IMAGE ID            CREATED             SIZE
sample/jib-demo-app                                                latest              891911ccd0de        About a minute ago   133MB

イメージ作成できてました。簡単すぎる。

イメージを実行して確認する

$ docker run --rm -it -p 8080:8080 --name jib-demo-app sample/jib-demo-app  
Picked up JAVA_TOOL_OPTIONS: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.3.RELEASE)

2018-08-05 16:18:36.344  INFO 1 --- [           main] net.kosasaki.example.WebApplication      : Starting WebApplication on 115367cada6f with PID 1 (/app/classes started by root in /)

確認できたので、OKとする

実にカンタン。これからはコンテナの世界ですねー。

にしても、alpine-slimで133MBとかJavaはサイズが大きいなー。
Java11とかでサイズ小さくなるといいなー。

Javaアプリをdocker化してくれるjibを環境ごとに分岐する

Java(Spring)アプリをdocker化してくれるんだけど、環境ごとに分けたいことはあるので、パラメータを切り替えられるようにする。

buildscript {
    ext {
        springBootVersion = '2.0.3.RELEASE'
                jibVersion = "0.9.8"
    }
    repositories {
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath "gradle.plugin.com.google.cloud.tools:jib-gradle-plugin:${jibVersion}"
    }
}

apply plugin: 'org.springframework.boot'
apply plugin: 'com.google.cloud.tools.jib'
    dependencies {
        compile('org.springframework.boot:spring-boot-starter-webflux')
        compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    }

/**
* jibの設定 ifで分岐する
*/
    if(project.build == 'product') {
        jib {
            from {
                image = 'adoptopenjdk/openjdk8:alpine'
            }
            to {
                image = 'sample/jib-demo-product-app'
            }
            container {
                jvmFlags = ['-Xms512m', '-Xdebug']
                mainClass = 'com.example.demo.DemoApplication'
                args = []
                ports = ['8080/tcp']
            }

        }
    } else {
        jib {
            from {
                image = 'adoptopenjdk/openjdk8:alpine'
            }
            to {
                image = 'sample/jib-demo-app'
            }
            container {
                jvmFlags = ['-Xms512m', '-Xdebug']
                mainClass = 'com.example.demo.DemoApplication'
                args = []
                ports = ['8080/tcp']
            }

        }
    }

上記のように設定し、gradleコマンドをキックするときに、引数を渡してあげればいい

$ ./gradlew -Pbuild=product

=================
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
sample/jib-demo-product-app   latest              4fe1925bb902        48 years ago        220MB

こんな感じで作成される。 48years ago ってでてるけど、なんなんだろ。まぁCREATEDだからいいか

他にもjibのタスク呼び出しとかあるが、JibExtensionとかいろいろ呼ぶの面倒そうなので、逃げでもある

dockerのmysqlでCan’t create/write to file ‘/var/lib/mysql/is_writable’

Macでmysqlをdockerを動かしてるとこんなのがでていた。どうやらpermissionが原因らしく、下記をセットすると動作したので、一旦メモ

下記でエラー

services:
  db-data:
    container_name: mysql-data
    image: busybox
    volumes:
      - ./volume-data/mysql:/var/lib/mysql:rw

  web:
    image: nginx:1.13.12-alpine
    ports:
      - "8080:80"

  db:
    container_name: mysql-db
    image: mysql:5.7
    volumes_from: 
      - db-data
    environment: 
      MYSQL_ROOT_PASSWORD: spring_boot_root
    ports:
        - "3306:3306"

dbのところで、user: "100:50"を追加する

services:
  db-data:
    container_name: mysql-data
    image: busybox
    volumes:
      - ./volume-data/mysql:/var/lib/mysql:rw

  web:
    image: nginx:1.13.12-alpine
    ports:
      - "8080:80"

  db:
    container_name: mysql-db
    image: mysql:5.7
    user: "1000:50"
    volumes_from: 
      - db-data
    environment: 
      MYSQL_ROOT_PASSWORD: spring_boot_root
    ports:
        - "3306:3306"

これで無事起動できた

docker pull で エラー “unauthorized: incorrect username or password”

Macでdocker pull したらエラーでたので、みてみたら、docker loginしてないとエラーになるもよう。
こんな感じのエラーになります。

 docker pull eclipse/che
Using default tag: latest
Error response from daemon: Get https://registry-1.docker.io/v2/eclipse/che/manifests/latest: unauthorized: incorrect username or password
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username (xxxxxx@sample.com): ${userid} // not mail address.
Password:

メールアドレスではなく、IDを入れる必要がある

試しになんでもいいので、pullしてみる。

$ docker pull eclipse/che
Using default tag: latest
latest: Pulling from eclipse/che
81033e7c1d6a: Pull complete
d7997e9f83cc: Pull complete
8f7158332f19: Pull complete
2f43f448d593: Pull complete
3abd9239cc20: Pull complete
d18a65a65c17: Pull complete
eef917a3ee63: Pull complete
eea77ae01b48: Pull complete
Digest: sha256:571a4542fe4db3530bc716219a846de88120c7299da1d59f5d0aa3956a458e7c
Status: Downloaded newer image for eclipse/che:latest

普通にpullできたらログイン成功

docker-compose でportsが反映されない問題…

docker-composeでportsの設定が反映されない問題がでて、悩んでたのですが、実はコマンド間違えだということがわかりました。
しかし、絶対また同じことをする自信があるので、備忘録

こんなdocker-compose.yamlがあります。

version: "3"
services: 
  # activemq
  activemq:
    build: .
    image: activemq:5.5.2
    container_name: activemq
    ports:
      - "1883:1883"
      - "5672:5672"
      - "8161:8161"
      - "61613:61613"
      - "61614:61614"
      - "61616:61616"

ports設定を6つしたいのです。これを間違ったコマンドで起動します

$ docker-compose run -d activemq 
$ docker ps 
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                                                                    NAMES
88f158290f09        activemq:5.5.2            "/bin/sh -c './bin..."   3 seconds ago       Up 1 second         1883/tcp, 5672/tcp, 8161/tcp, 61613-61614/tcp, 61616/tcp    

このように・・・ポートがコンテナ側しかあかないのです。これでなんでかなー?ってなってました。
docker-composeの場合は、runは使わずにupを使いましょう

下記、正しいコマンド

$ docker-compose up -d 
$ docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                         NAMES
d58e6db65202        activemq:5.5.2      "/bin/sh -c './bin..."   5 seconds ago       Up 3 seconds        0.0.0.0:1883->1883/tcp, 0.0.0.0:5672->5672/tcp, 0.0.0.0:8161->8161/tcp, 0.0.0.0:61613-61614->61613-61614/tcp,0.0.0.0:61616->61616/tcp   activemq

これで、ホスト側とコンテナ側でのポートフォワーディングができています。

dockerはプロセスがforegroundじゃないと起動とともに終了する

備忘録です。
人が作ったイメージばっかり作って、たまに自分でイメージ作って起動しようとすると「うっ。。」ってなるので、メモ。

  • shell scriptでループを回す方法
  • supervisordを入れる方法

shell scriptでループ回す方法

一番簡単なのは、これ

# foreground.sh #

#!/bin/sh

while true 
do
  sleep 1000
done
# Dockerfile

FROM alpine

ADD foreground.sh /etc/foreground.sh
CMD /etc/foreground.sh

これかいて

$ docker build -t sample-alpine .
$ docker run -d --rm --name sample-alpine

これで落ちなくなる。まぁでも大変。

supervisord入れておく方法

supervisordというpythonのツールを入れておく

こんな感じになります。

# DockerFile #
FROM alpine:latest

MAINTAINER Kohei Sasaki <kohei.sasaki.a@gmail.com>

# python2 install
RUN apk update && apk add python2 && apk add py2-pip
# supervisord install
RUN pip install supervisor==3.3.3 && echo_supervisord_conf > /etc/supervisord.conf
# servisord start non daemon mode
CMD supervisord --nodaemon --configuration /etc/supervisord.conf

githubにファイル置いておきます!

github

Dockerでエラー(Failed to load unit ‘HGCM’ (VERR_SSM_UNEXPECTED_DATA)

Dockerを起動したときにVBoxManage: error: Failed to load unit ‘HGCM’ (VERR_SSM_UNEXPECTED_DATA)エラーがでた。

$ docker-machine start default
Starting "default"...
Unable to start the VM: /usr/local/bin/VBoxManage startvm default --type headless failed:
VBoxManage: error: Failed to load unit 'HGCM' (VERR_SSM_UNEXPECTED_DATA)
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component ConsoleWrap, interface IConsole

Details: 00:00:01.921594 Power up failed (vrc=VERR_SSM_UNEXPECTED_DATA, rc=NS_ERROR_FAILURE (0X80004005))

virtualbox managerを起動して、見てみると power off ではなくて saved になってる。
おそらくこれかなと思いmanagerからvmを右クリックなりのメニューでDisgard save status をクリックして再度 docker-machineコマンドを入力する。

無事起動。

よかったよかった。