RailsアプリでCircleCI設定時にハマったこと

結論

Databaseコンテナの起動を dockerize を使って待ちましょう。

以下のような感じ。

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

これの検証だけのために30回くらいビルドしたのは内緒🤬

[事の発端]自動テストでMySQL コンテナを利用しようと思った。

5.6を利用していたが、 rails db:create がCircleCI上で通らない。 でも何回かビルドしているとたまに通ったりする。(この時点でなにか非同期な処理によるものだと気づくべきだった。) (最初は、なぜか文字コードの問題だと思って戦っていた。)

エラーは以下のような感じ

#<Mysql2::Error::ConnectionError: Can't connect to MySQL server on '127.0.0.1' (111)>
Couldn't create database for {"adapter"=>"mysql2", "encoding"=>"utf8mb4", "charset"=>"utf8mb4", "collation"=>"utf8mb4_bin", "pool"=>5, "username"=>"root", "password"=>nil, "host"=>"127.0.0.1", "socket"=>"/tmp/mysql.sock", "database"=>"test"}, {:charset=>"utf8mb4", :collation=>"utf8mb4_bin"}
(If you set the charset manually, make sure you have a matching collation)
Created database 'test'

以下のようにして解決だと思った。(別に解決していない。)

config.yml

jobs:
  build:
    docker:
       - image: circleci/ruby:2.4.1-node-browsers 
         environment:
           RAILS_ENV: test
           DB_HOST: 127.0.0.1
           DB_USERNAME: 'root'
           DB_PASSWORD: ''
       - image: circleci/mysql:5.6
         environment:
           MYSQL_ALLOW_EMPTY_PASSWORD: yes

database.yml

efault: &default
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_bin
  pool: 5
  username: root
  password:
  host: localhost
  socket: /tmp/mysql.sock

test:
  <<: *default
  database: test
  username: <%= ENV['DB_USERNAME'] || 'root' %>
  password: <%= ENV['DB_PASSWORD'] || '' %>
  host: <%= ENV['DB_HOST'] || '127.0.0.1' %>

ポイント(だとおもっていたこと)

  • パスワードを設定しない場合は、config.ymlでmysqlコンテナに関して環境変数MYSQL_ALLOW_EMPTY_PASSWORDを設定すること。
  • database.ymlで encoding, charset, collation を設定すること。
    • この辺掘り下げてはいないが、collationを設定していないとコケる。
    • なんでだ。。。

エラー再発(当然である)

いろいろとググる。DB関係のブログを読んでいたらたまたまdockerizeについても言及してくれている方がいてこれかなと思うようになった。

dockerコンテナの立ち上げを待つ必要がある?(これが結論)

dockerizeを利用することで解決可能っぽい。

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

ぶつかっていた問題は文字コード云々ではなく、dockerコンテナの起動を待つことだった。そりゃ起動していないコンテナに命令は出せないよね。。。。精進します。

参考記事

ただ digdag コマンドを 叩くと 前回実行済みの タスクが実行されない件

run コマンドの オプションを確認してみると —session というものがある。

意訳すると これは 未指定のばあいは、 前回の実行の続きから始める、ということらしい。

Digdag は .digdag ディレクトリ以下で 進行状況を記憶しているのでそこを参照してすでに実行されたタスクに関してはもう実行しないようになる。

注意。

$ digdag run --help
Usage: digdag run <workflow.dig> [+task] [options...]
  Options:
        --project DIR                use this directory as the project directory (default: current directory)
    -a, --rerun                      ignores status files saved at .digdag/status and re-runs all tasks
    -s, --start +NAME                runs this task and its following tasks even if their status files are stored at .digdag/status
    -g, --goal +NAME                 runs this task and its children tasks even if their status files are stored at .digdag/status
    -e, --end +NAME                  skips this task and its following tasks
    -o, --save DIR                   uses this directory to read and write status files (default: .digdag/status)
        --no-save                    doesn't save status files at .digdag/status
    -p, --param KEY=VALUE            overwrites a parameter (use multiple times to set many parameters)
    -P, --params-file PATH.yml       reads parameters from a YAML file
    -d, --dry-run                    dry-run mode doesn't execute tasks
    -E, --show-params                show task parameters before running a task
        --session <daily | hourly | schedule | last | "yyyy-MM-dd[ HH:mm:ss]">  set session_time to this time
                                     (default: last, reuses the latest session time stored at .digdag/status)
    --max-task-threads               Limit maximum number of task execution threads on the execution
    -L, --log PATH                   output log messages to a file (default: -)
    -l, --log-level LEVEL            log level (error, warn, info, debug or trace)
    -X KEY=VALUE                     add a performance system config
    -c, --config PATH.properties     Configuration file (default: /root/.config/digdag/config)

digdag 環境を docker で 構築したときにハマった問題

メモ程度に。

現象

脳死して centos 上の java8 環境を作るときに webdizz/centos-java8 既存イメージを利用した際にコケた。こういうのサボらないほうがいいね。理解していないものを使っちゃだめだなーと。 以下は詳細なJavaのバージョン

# java -version
java version "1.8.0_11"
Java(TM) SE Runtime Environment (build 1.8.0_11-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode)

digdag push とかするときにタイムスタンプ付きのログが出るんだが、そのときに Javaの 時間関係のライブラリのAPIがうまく動かないことが原因だったぽい。

Unable to obtain Instant なんちゃら、、、っていうエラーが発生していた。

解決法

ちなみに以下のバージョンでは問題なく動いた。

# java -version
openjdk version "1.8.0_171"
OpenJDK Runtime Environment (build 1.8.0_171-b10)
OpenJDK 64-Bit Server VM (build 25.171-b10, mixed mode)

Dockerfile での install は 以下のような感じ

FROM centos:latest

RUN \
    yum update -y && yum install -y \
      java-1.8.9-openjdk \
      java-1.8.0-openjdk-devel

Java には問題がなくて、 JAVA_HOME の設定が間違っているのかと思って再度設定し直して試してみたが結局再現したのでやっぱりjavaのばーじょんがよくなかったぽい。

他の解決策もあるかもなので こうだよってのあったら教えてほしいです。

追記

(Qiitaの方で)コメント欄で教えていただいた公式ドキュメントの記述によると、digdagの実行にはJava8 u72以降が必要とのこと。

問題が発生していたときの Java の バージョンは 調べるとたしかに u72 よりも古いものでした。

http://docs.digdag.io/getting_started.html#got-error

vimgrep 使い方

vimgrep 使い方

下記参考にした。使ったところだけ。 vimgrepとQuickfix知らないVimmerはちょっとこっち来い

Vim内で手軽に検索できる方法, ruby 編集しているときに参照調べたりするのにたまに使う。

コマンド

Vim 内で以下のコマンドを実行する。

:vim {pattern} file

こっちのほうが幸せになれる。パイプでquickfixに渡している。マッチしたリストを別ペインで参照可能になる。

:vim {pattern} file | cw

ユースケース

GIt管理されているファイル群から検索する

:vim {pattern} `git ls-files`

カレントディレクトリ以下を全検索する(非推奨)

ライブラリとか読み出すとめちゃめちゃ時間かかるので全件検索はあまり良くない。

:vim {pattern} **

docker コンテナ内で 動かした web pack-devServerを外部に公開する

devServer.host を設定する。

DevServer を参考にして、以下のように 設定ファイルで 設定する。

devServer: {
    //他項目省略
    devServer.host: "0.0.0.0"
}

docker-compose.yml 内で volumes に 相対パスしてたらコケてたやつ。

docker-compose で volumes に 相対パスを指定したらこけた。

エラーが出る

docker-compose up すると 以下のエラーでコケる。初心者なのでよくわからん。

エラー内容

❯ docker-compose up
Creating frontend_appserver_1 ... error

ERROR: for frontend_appserver_1  Cannot create container for service appserver: b'invalid volume specification: \'/Users/natsuki/Practice/frontend/react-sample:nodejs/react-sample:rw\': invalid mount config for type "bind": invalid mount path: \'nodejs/react-sample\' mount path must be absolute'

ERROR: for appserver  Cannot create container for service appserver: b'invalid volume specification: \'/Users/natsuki/Practice/frontend/react-sample:nodejs/react-sample:rw\': invalid mount config for type "bind": invalid mount path: \'nodejs/react-sample\' mount path must be absolute'
ERROR: Encountered errors while bringing up the project.

bind タイプのコンフィグにしてはおかしいぞ?
絶対パス使えよ?

まじかってかんじ。一応絶対パスにすれば動くけど絶対にしたくない。

docker-compose.yml

は、こんなの。

appserver:
  build: .
  volumes:
    - ./react-sample:/nodejs/react-sample
  ports:
    - "3000:3000"
  command: npm run start
  tty: true

Dockerfile

#ubuntu をベースイメージにする
FROM centos:latest

# ENVをdevelopmentに設定する
ENV MYENV=development

# /appDirectoryをワークDirectoryに設定
WORKDIR /nodejs/react-sample

# nodejs-8.10.0のinstall
RUN ["yum", "update", "-y"]
RUN curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -
RUN ["yum", "install", "-y", "nodejs-8.10.0"]

# vim の install
RUN ["yum", "install", "-y", "vim"]

RUN ["mkdir", "react-sample"]
RUN ["npm", "init", "-y"]
RUN ["npm", "i", "react@16.2.0", "react-dom@16.2.0"]
RUN ["npm", "i", "-D", "webpack@4.4.1", "webpack-cli@2.0.11"]
COPY ./react-sample/package-lock.json package-lock.json

EXPOSE 3000

解決法

Dockerfile に

VOLUME [ "/nodejs/react-sample" ]

を追記した。

マウントされていなかったから動かなかったみたい。

日本語のソースなかったので同様の症状に悩んでいる人のためになれば嬉しい。

そしてもしかしたらこれはまちがった問題解消かもしれないので正しい方法を知っている人がいたら教えてほしい。

追記

先述のdocker-compose.yml のまま build からやりなおしたら動くようになった。ロースキルつら。。

近況報告001

近況報告

最近やっていること

読書と社内企画とか社内改善のチーム結成のお手伝いとかです。

読書

SQL

はい、これはあんまり基本情報試験でわからなかったので帰りの足で池袋ジュンク堂によってオライリーの『はじめてのSQL』とか『達人に学ぶSQL徹底指南書』買ったりして、ひたすら勉強してました。一週間で初めてのSQLのうち50%くらいは進んでいるのでこの漢字で着々と今週末には完了したいところです。

達人プログラマー

「う〜ん。名著w。」って感じの一冊でした。文句ないです。古い本ではあるので、具体例のふるさが気になる人がもしかしたらいるかもしれませんが、一般化して捉えると、今でも全然通じますね。最後の方はずっとマーカーで線引いてました。もし、次に読むなら最後の章から読んでもいいかな〜とか思ってました。

社内企画

いろいろと思うことがあって同期と一緒に企画して始めました。まー、初めてということもあり、準備不足やら想定不足やらで完成度としてはあまり高くなかったですね。ただ、課題を明確にできたので次回はより良くできるかなと思います。休憩とかね、結構重要ですね。

社内カイゼンチーム結成の手伝い

バックヤードのマンオペがとても多いとか、勤怠管理のシステムがやけに煩雑だとか色々課題はあるのでそれを解決していきましょうということで組織化してやっていきたいと思っています。

まとめ

動いてなんぼ感がだんだんと腹落ちしてきたので、動き回ることとします。一緒に動いてくれる人のありがたみを思い知りますね。そういう人を裏切らないで済むように頑張っていきたいと思います。マー、何をすればいいかはあんまりわかってないんですが、やらないよりはまし。。