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

「最短で達成する 全体最適のプロジェクトマネジメント」を読んだ

最短で達成する 全体最適のプロジェクトマネジメント

最短で達成する 全体最適のプロジェクトマネジメント

上司の薦めで読んでみた。 プロジェクトマネジメントの本は久しぶり。

TOCを分かりやすく説明した本って感じになるのかな?

TOCクリティカルチェーンくらいしか読んだことないけど、いい意味で復習になったと思う。 絵が多かったりコンパクトに纏まっているのでサクッと読めるのもよい。

クリティカルチェーンは小説仕立てで読みやすかった記憶があるので、一緒に読むのもいいかも。

「小さく作って小さく(何度も)リリース」っていう価値観だとPart5だけ少し引っかかるところがあった。 この辺はソフトウェアにフォーカスしたものではないこともあるのかもしれない。

プロジェクトリーダーをやってみたけどうまくいかないとか、もっと改善する方法はないかとか考えているような人だと新しい気付きがありそうな本です。

読書メモ

「最短で達成する 全体最適のプロジェクトマネジメント」読書メモ · GitHub

CircleCIでbatsによるbashのテストがエラー #Bash #CircleCI

概要

CircleCIでbatsによるBashのテストをしてたんだけど、特に改修していないのにCIがコケるようになってしまった。

どうもbatsがtputなるコマンドを使っているようで、 tput$TERM という環境変数が必要なようだ。

CircleCIの使ってるビルド環境から $TERM 変数がアップデートとかでいなくなってしまったのだろうか。

config.yml

batsファイルをリストアップしてbatsコマンドで実行しているだけである

version: 2
jobs:
  build:
    machine:
      enabled: true
    steps:
      - checkout
      - run: find . -type f -name "*\.bats" | xargs bats -p

エラーメッセージ

Hangupとか言われているのが気になるが、 tput: No value for $TERM and no -T specified を解決してあげると動くみたい。

#!/bin/bash -eo pipefail
find . -type f -name "*\.bats" | xargs bats -p
tput: No value for $TERM and no -T specified
/usr/local/libexec/bats-exec-test: line 321:  6811 Hangup                  "$0" $BATS_EXTENDED_SYNTAX "$BATS_TEST_FILENAME" "$test_name" "$test_number"
Exited with code 123

原因

どうも tput はTerminalを操作するコマンドらしい。

表示する色を変えたりできるみたい。

んで、batsは結果表示するときなんかに tput を使用しているっぽくって、そこで ${TERM} 変数がなくてエラーになっているのではないかと。

github.com

対応

${TERM}環境変数に設定する。

export TERM="dumb"

意識したことないけど、 screen だとか tmux とかもこの変数に入ったりするみたい。

自分のローカルMacだと xterm-256color だった。

dumbは「ダム端末 - Wikipedia」に由来しているようだけど、何もしないターミナルってことを表現しているのだろうか。

余談

discuss.circleci.com

CircleCIのフォーラムっぽいので語られていたのが解決の糸口になった。

これ少し前の投稿なので、デグレかな?とも思ったけど、TerminalのことCIが気にするのも何か変な気がする。。

デグレだとしたらそのうち直る気がするけど、直らない可能性も十分にありそう。

いずれにせよ、CircleCIでは結構こういうこと(ユーザ側で何も変更していなくても、CI側の変更でCIが通らなくなってしまうようなこと)が多い気がする。

他のCIツールだとどうなんだろ。自前コンテナ作ってCI環境安定させたほうがいい気がしてきた。

参考

JJUGで発表してきました #jjug_ccc #ccc_l1

JJUGで「SpringBootとMyBatisでデータベースを可視化する」というテーマで発表してきました。

speakerdeck.com

CfPの書き方教えてくれたり、発表資料レビューしてくれた同僚たちには感謝しかない。

朝イチ・冬将軍・雨模様で果たして聞きに来てくれる人いるかなぁと不安だったのだけれど、結果満席になるくらいたくさんの人が来てくれました。

少しでも役に立つようなことが伝わってるといいなぁ。

割と早口で巻きで行ったので、質問や気になることとかあったらTwitterなりでメンション頂ければと思います。

登壇を終えて思ったこと

なんで登壇したのかなー、って考えてみたとき、 @bufferings さんのTweetを見てなるほどと思うことがあった。

ブログとかもそうだけど、僕にとってアウトプットって壮大な自己紹介なんだよなぁ。

  • こういうのが好き
  • こういうことをやっている
  • こういうのが気になっている

んで、アウトプットをきっかけに直接にしろ間接にしろどこかの誰かと繋がるんだよね。

もちろん実利もあるんだけど、単純に楽しい。

特に懇親会でポツンになってしまう人見知りタイプの僕にとってはw

ふりかえり

  • 登壇後ロビーで呆けてたら「セッション面白かった」って声かけてもらえた
  • 懇親会終わりに「Spock触ってみようと思いました」って声かけてもらえた
    • Spockの普及が裏テーマであったw
  • Demoちゃんと動いた!
  • Decksetでスライド作成したのだけれど、とても便利だった
    • Markdownでスライド作れるやつ
  • 朝イチだったので、残りの時間は何も気にせず楽しむことができた
  • 練習でいつも時間足りなくなったので、すこし急いだら5分巻きで終わった
    • やっぱり本番は早口になっていたのかも。。
  • せっかく初登壇だったのに記念写真とるの忘れた

印象に残ったセッションとか

10年前のレガシーシステムをサーバーサイドKotlinでフルリニューアルした話し

speakerdeck.com

KotlinはRubyistからもウケがいいらしい。

KotlinはIDEAのサポートも強力だし、書いてて楽しいだろうなぁというイメージはある。(ちょっとしか触ったことない)

気になるテスト周りなんだよね。。BDD系あんまり好きじゃないし、Spock(というかGroovyMock?)とあんまり相性よくないし。。JUnitするしかないのかしら。

Pivotal認定講師が徹底解説!Spring Bootの本当の理解ポイント

www.slideshare.net

登壇者の方が講師というだけあって、とても分かりやすかった。

Spring BootからSpringに触った自分としてはとても役立った気がする。

Springのことをもうちょっと勉強したほうがいいんだろうな。。しかし参考書籍がどれも分厚い。

Java SE 9の紹介: モジュール・システムを中心に

www.slideshare.net

モジュール思ったより大変そうな感じ。

Mavenとかで解決している依存管理と二重管理大変にならないかな。。

既存の移行もそうだし、新規にしてもライブラリやフレームワーク群がどういう感じで追従してくるのか。

あとKotlinとかScalaとか他のJVM言語への影響も気になる。

CPUから見たG1GC

www.slideshare.net

GCが起きてなくてもG1GCよりParallelGCの方が早い。なぜ?」って事象を掘り下げていく感じのセッション。

謎解きを聞いているような感じだったんだけど、途中からついていけなくなった。。

  • GCは発生するタイミングや回数だけを気にしているがそれだけでは解決できないことがある
  • アプリの作りによってGCアルゴリズムが影響することもある

っていう感じのテーマだったのかなぁ。

GCムズイ。

懇親会

オフラインコミュニケーション弱者っぷりを遺憾なく発揮していたのですが、昔同じプロジェクト(別チーム)にいたことがある人と巡り会いずっと相手してもらいました(申し訳ない)

LTはSpringBootの容量減らす話がLTっぽくて面白かった。

qiita.com

しれっとじゃんけん大会に勝利してdukeくんのマウスをゲットしました。

まとめ

はじめて登壇したということで、いつも以上に印象深いJJUGとなりました。

準備なかなか大変だったので、終わった直後は「もうやらない、今後はLTくらいでいい!」と思ってましたが(笑)、今はまた機会があったら何か話せるといいなと思っています。

f:id:su-kun1899:20171120230645p:plain

mysqlコマンドのエラー出力をログに吐く #mysql

mysqlコマンドは問題発生時はエラー出力にメッセージを吐くので、標準エラーをファイルにリダイレクトしてやればよい。

mysql -u root sample_db < test.sql >> result.log 2>> error.log

この場合だと、test.sqlを実行した結果、result.logに標準出力が、error.logに標準エラー出力が吐かれる。

どんなエラーが吐かれるか?

例えばDBと接続が切れた場合などは、下記のようなエラーが吐かれる。

ERROR 2013 (HY000) at line 3: Lost connection to MySQL server during query

検証にはSLEEPが便利

実際には下記のような流れで検証した。

  1. DBを起動する
  2. mysqlコマンドを実行する
  3. DBを停止する
  4. エラー出力を確認する

この際、mysqlコマンドが実行中にDBを停止する必要があるのだが、そんなに都合よく重いクエリなんてないと思ったら、MySQLsqlでsleepできる(SLEEP関数がある)。

SELECT SLEEP(10)

引数に止めたい秒を渡してあげると、その時間sleepしてくれる。

今回はmysqlコマンドの検証に使ったけど、重いクエリ発行時の挙動確認とか、テスト関連で使い所がありそう。

参考

https://dev.mysql.com/doc/refman/5.6/ja/miscellaneous-functions.html#function_sleep

gitでremoteに同名のtagがいる場合、 fetchにtagsオプションが必要 #git

概要

tagの向き先が意図しないコミットハッシュになっていて、調査したらローカルに同名のtagが存在していたのが原因だった。

詳細

tagの向き先を切り替える場合には、fetchしてからtagにチェックアウトするようにしていた。

$ git fetch
$ git checkout v2.0

tagがremoteにしかない場合は特に問題ないのだが、ローカルに同名のtagが存在する場合、ローカルのtagが優先される。

$ git tag

リモートのtagを反映させるには tags オプションが必要になる。

$ git fetch --tags

まとめ

  • GitHubみたいにremoteでtag作れるならそれに任せちゃったほうがよい
  • 自分でやるなら --tags 忘れずに

おまけ

  • コミットを含むtagを検索する
    • git tag --contains 6f66d52a

参考

qiita.com qiita.com d.hatena.ne.jp