CircleCI2.0で別コンテナのMySQLを使ったJavaアプリのCIを行う #CIrcleCI #docker

CircleCIは2.0は、docker imageベースになった。

JavaアプリをCIするときはCircleCIのJava用imageを使えばいいんだけど、テスト用DBとしてMySQLのコンテナを一緒に使うようにしてみた。

1.0のときはそのままMySQL使えたんだけどね。

config.yml

最終的にはこんな形になる

version: 2
jobs:
  build:
    working_directory: ~/my-project
    docker:
      - image: circleci/openjdk:8-jdk-browsers
      - image: mysql:5.7
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          MYSQL_DATABASE: sample
        command: [--character-set-server=utf8, --collation-server=utf8_general_ci, --default-storage-engine=innodb]

    steps:
      - checkout
      - run:
          name: Wait for db
          command: dockerize -wait tcp://localhost:3306 -timeout 1m
      
      # あとはプロジェクト毎に。。
      - run: ./mvnw clean integration-test

docker要素に複数のimageを書く

複数のdocker imageのコンテナを定義できる模様。

最初にビルド用のimageを書く。

今回だとjavaアプリケーションなので circleci/openjdk:8-jdk-browsers を使用する。

docker:
  - image: circleci/openjdk:8-jdk-browsers
  - image: mysql:5.7
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: yes
      MYSQL_DATABASE: sample
    command: [--character-set-server=utf8, --collation-server=utf8_general_ci, --default-storage-engine=innodb]

MySQLはDockerHubの公式 mysql:5.7 を使用する。

environment はコンテナで使用する環境変数を定義できる。--env に渡すものだと思っておけばよさそう。

MYSQL_ALLOW_EMPTY_PASSWORD はyesにしておくとPASSWORDなしアクセスが可能になる。

自分はテストのときはrootユーザPASSWORDなしで繋いでいるいるので設定した。

MYSQL_DATABASE を設定すると、起動時にその名前でDatabaseを作っておいてくれる。

create database を勝手にやっておいてくれる感じ。

commandで設定をカスタマイズする

MySQLのコンテナは --volume でマウントさせることでカスタマイズした設定ファイル( my.cnf 等)を読み込ませることができる。

ところがCircleCIではどうもMountできないらしく、docker cp しろみたいなことが書いてある。

https://circleci.com/docs/2.0/building-docker-images/#mounting-folders

さすがにめんどくさいなと思っていたら、MySQLのイメージは設定値を引数でも渡せるようになっていた。

yamlのcommand要素に書いておくと、起動時に渡してくれる。

大体デフォだと日本語が辛いのでUTF-8にしておく(ついでにstorageもinnodbに)。

command: [--character-set-server=utf8, --collation-server=utf8_general_ci, --default-storage-engine=innodb]

dockerize

コンテナを複数使っているので、DBが立ち上がる前にビルドが走るとエラーになってしまう。

dockrizeを使うことでDBが立ち上がるまで待つようにする。

      - run:
          name: Wait for db
          command: dockerize -wait` tcp://localhost:3306 -timeout 1m

公式ではdockerizeのインストールが必要な旨が書いてあるが、CircleCIの提供image(circleci/openjdk:8-jdk-browsers)を使っているからか、特に必要なかった。

独自のビルドimageを使っている場合は必要になりそう。インストールする場合は下記。

- run:
    name: install dockerize
    command: wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
    environment:
      DOCKERIZE_VERSION: v0.3.0

まとめ

  • CircleCI2.0では複数のdockerイメージが使える
  • environmentで環境変数を定義できる
  • commandで引数を渡せる
  • 必要に応じて、dockerizeでwaitする

しかし複数イメージなのに localhost でつなげるのは何でだろ。。

参考

su-kun1899.hatenablog.com