Day-to-day the memorandum

やったことのメモ書きです。

Dockerイメージを作ってみる

前回までに書いた以下2つのエントリのDockerイメージを作ってみたいと思います。
Spring Webfluxを触ってみた - Day-to-day the memorandum
Reactを触ってみた - Day-to-day the memorandum

はじめに

Spring WebfluxのほうはJib使ってCircleCIからDockerhubにpushするようにし、
ReactのほうはDockerhubのAutobuildで作って行きたいと思います。

Jibを使ってDockerイメージを作る

まずSpring WebfluxのほうのDockerイメージを作っていきたいと思います。

version

$ java --version
java version "11" 2018-09-25
Java(TM) SE Runtime Environment 18.9 (build 11+28)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11+28, mixed mode)

$ mvn --version
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00)
Maven home: D:\apache-maven-3.6.0-bin\apache-maven-3.6.0\bin\..
Java version: 11, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk-11
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

Dockerhubのリポジトリを作る

Dockerhubにリポジトリを作ります。
今回はリポジトリ名は「spring-webflux-demo」にしました。
https://hub.docker.com/r/kkasai/spring-webflux-demo/

pom.xmlに追記する。

今回はJibを使うのでpom.xmlを書いていきます。
基本的に以下のCircleCIのブログに従っていきます。
Dockerizing Java apps with CircleCI and Jib - CircleCI

pom.xmlは以下のように

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
・・・
    <properties>
        <build.number>000</build.number>
        <commit.hash>local-build</commit.hash>
        <build.user>local-build</build.user>
        <build.repo>local-build</build.repo>
        <circle.workflow.guid>local-build</circle.workflow.guid>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>jib-maven-plugin</artifactId>
                <version>0.10.0</version>
                <configuration>
                    <from>
                        <image>openjdk:11-jdk-slim</image>
                    </from>
                    <to>
                        <image>registry.hub.docker.com/kkasai/spring-webflux-demo:latest</image>
                    </to>
                    <container>
                        <jvmFlags>
                            <jvmFlag>-Dbuild.number=${build.number}</jvmFlag>
                            <jvmFlag>-Dcommit.hash=${commit.hash}</jvmFlag>
                            <jvmFlag>-Dbuild.user=${build.user}</jvmFlag>
                            <jvmFlag>-Dbuild.repo=${build.repo}</jvmFlag>
                            <jvmFlag>-Dcircle.workflow.guid=${circle.workflow.guid}</jvmFlag>
                        </jvmFlags>
                        <ports>
                            <port>8080</port>
                        </ports>
                    </container>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
</project>

Jibの設定をしているconfigurationtoimageに先ほど作ったDockerhubのリポジトリを書きます。
ブログと違うところはfromにJava11のイメージを指定しています。

続いて、ブログに書いてある通り、mvnコマンドでMavenのMasterパスワードを暗号化して、
それを使ってDockerhubのパスワードを暗号化します。

mvn --encrypt-master-password
Master password:
#ここの出力結果は後で使います。

mvn --encrypt-password
Password: #Dockerhubのパスワードを入力する
{ZEHDjQD9xc4HYlbLeLU2Qft9BOQ1+bQ2gaJUuWLr6bE=}

Dockerhubのユーザ情報などを記述したファイルを.mvn/wrapper/settings.xmlに作っておきます。

<?xml version="1.0" encoding="UTF-8" ?>

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <servers>
        <server>
            <id>registry.hub.docker.com</id>
            <username>kkasai</username>
            <password>{ZEHDjQD9xc4HYlbLeLU2Qft9BOQ1+bQ2gaJUuWLr6bE=}</password>
        </server>
    </servers>
</settings>

passwordのところに先ほどおこなったDockerhubのパスワードを暗号化した値を入れておきます。

CircleCIのプロジェクトを作成する

CircleCIのプロジェクトを作っていきます。
ログイン後 Add Projectsからspring-webflux-demoSet Up Projectをクリックし、
Operating SystemLinuxLanguageMaven(Java)を選択します。
そうすると下のほうにCircleCIの設定ファイルのサンプルが出てくるので、これをコピーして.circleci/config.ymlを作っていきます。

# Java Maven CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-java/ for more details
#
version: 2
jobs:
  build:
    docker:
    # specify the version you desire here
    - image: circleci/openjdk:11-jdk

    # Specify service dependencies here if necessary
    # CircleCI maintains a library of pre-built images
    # documented at https://circleci.com/docs/2.0/circleci-images/
    # - image: circleci/postgres:9.4

    working_directory: ~/repo

    environment:
      # Customize the JVM maximum heap limit
      MAVEN_OPTS: -Xmx3200m

    steps:
    - checkout

    # Download and cache dependencies
    - restore_cache:
        keys:
        - v1-dependencies-{{ checksum "pom.xml" }}
        # fallback to using the latest cache if no exact match is found
        - v1-dependencies-

    - run: mvn dependency:go-offline

    - save_cache:
        paths:
        - ~/.m2
        key: v1-dependencies-{{ checksum "pom.xml" }}

#    # run tests!
#    - run: mvn integration-test

    - run: cp .mvn/wrapper/settings.xml ~/.m2/settings.xml
    - run: echo "<settingsSecurity><master>${maven_security_master}</master></settingsSecurity>" > ~/.m2/settings-security.xml
    - run:
        name: Publish Docker image with Jib
        command: |
          mvn compile jib:build -B -DskipTests=true \
            -Dbuild.number=${CIRCLE_BUILD_NUM} \
            -Dcommit.hash=${CIRCLE_SHA1} \
            -Dcircle.workflow.guid=${CIRCLE_WORKFLOW_ID} \
            -Dbuild.user=${CIRCLE_PROJECT_USERNAME} \
            -Dbuild.repo=${CIRCLE_PROJECT_REPONAME}

コピーしたものから変えているところはJavaのイメージを8から11のイメージに変えています。
あとはtestのところをコメントアウトしています。
testのところから下はCircleCIのブログと一緒です。

設定ファイルはこんな感じであとはCircleCIのプロジェクトのsettingsからEnvironment Variables
Nameにmaven_security_masterValueに先ほど行ったMavenのMaster Passwordを暗号化した値を設定します。

これでgit pushするとCircleCIのジョブが実行されDockerhubにDockerイメージができていると思います。

AutobuildでDockerイメージを作る

続いて、ReactのほうのDockerイメージを作っていきたいと思います。
CircleCIでbuildして、そのbuildしたものを使ってイメージを作りたいと思います。

CircleCIの設定を書く

先ほどと同様にAdd Projectsからreact-demoSet Up Projectをクリックし、
Operating SystemLinuxLanguageNodeを選択します。
その後、下のCircleCIの設定ファイルのサンプルをコピーして.circleci/config.ymlを作っていきます。

# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2
jobs:
  build:
    docker:
    # specify the version you desire here
    - image: circleci/node:8.12

    # Specify service dependencies here if necessary
    # CircleCI maintains a library of pre-built images
    # documented at https://circleci.com/docs/2.0/circleci-images/
    # - image: circleci/mongo:3.4.4

    working_directory: ~/repo

    steps:
    - checkout

    # Download and cache dependencies
    - restore_cache:
        keys:
        - v1-dependencies-{{ checksum "package.json" }}
        # fallback to using the latest cache if no exact match is found
        - v1-dependencies-

    - run: yarn install

    - save_cache:
        paths:
        - node_modules
        key: v1-dependencies-{{ checksum "package.json" }}

#    # run tests!
#    - run: yarn test

    - run: yarn build

    - run: tar zcvf build.tar.gz build

    - store_artifacts:
        path: build.tar.gz

コピーしたものから変えているところはNodeのイメージを7.10から8.12のイメージに変えています。
あとはtestのところをコメントアウトしています。

そこから下はbuildをして成果物をtar.gzで圧縮し、圧縮したものをstore_artifactsで保存しています。

これでgit pushするとCircleCIのジョブが実行されると思います。

Dockerhubのリポジトリを作る

「react-demo」という名前でDockerhubのリポジトリを作っていきます。
今回は、DockerhubのAutobuildを使いたいので、CreateからCreate Automated Buildをクリックします。
Githubを選択して、あとはreact-demoのリポジトリをクリックするだけです。

Dockerfileを書く

Dockerfileを書いていきます。

FROM debian:stretch AS build

RUN apt update && \
    apt install -y curl \
                   jq

RUN curl https://circleci.com/api/v1.1/project/github/kkasai/react-demo/latest/artifacts?filter=successful \
    | jq 'map(select(.["path"] == "home/circleci/repo/build.tar.gz"))' \
    | jq '.[0]["url"]' \
    | xargs curl -o /tmp/build.tar.gz

RUN tar zxvf /tmp/build.tar.gz -C /tmp


FROM nginx:1.15.6-alpine

COPY --from=build /tmp/build /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

CircleCIのジョブの結果の情報をJsonで返してくれるAPIがあるのでそれを叩いて、store_artifactsのURLを取得してダウンロードしています。
(これがやりたかったためだけにbuildした成果物を圧縮して保存し、取ってきてnginxで動かすということをしています。)

これでgit pushするとDockerhubのAutobuildが実行されると思います。

動かしてみる

作ったイメージを使って動かしてみたいと思います。

version

$ docker --version
Docker version 18.09.0, build 4d60db4

$ docker-compose --version
docker-compose version 1.23.1, build b02f1306

docker-composeファイルの作成

docker-composeファイルを作っていきます。

version: "3"
services:

  db:
    image: mongo:4.1.3

  back:
    image: kkasai/spring-webflux-demo
    environment:
      - SPRING_DATA_MONGODB_HOST=db
      - SPRING_DATA_MONGODB_PORT=27017
      - SPRING_DATA_MONGODB_DATABASE=sample
    ports:
      - "8080:8080"
    depends_on:
      - db

  front:
    image: kkasai/react-demo
    ports:
      - "80:80"

忘れていそうですがSpringでMongoの設定をしていていました。
上記のように環境変数で上書きできるので、上書きしておきます。
設定が読まれる順番については以下のサイトに書いてあります。
https://docs.spring.io/spring-boot/docs/2.0.5.RELEASE/reference/html/boot-features-external-config.html

実行

$ docker-compose up -d

http://localhostにアクセスすると前回作ったものが見れると思います。

さいごに

githubリポジトリです。
一応docker-composeのリポジトリも作っておきました。
github.com
react-demoのほうはv2.0というTagをうっておきました。
github.com
spring-webflux-demoのほうはv3.0というTagをうっておきました。
github.com