無気力生活 (ノ ´ω`)ノ ~゜

脱力系エンジニア。てきとーに生きてます。

MYSQL8.0で作成したDBにCakePHPからアクセスできないときに確認しておくこと

ちょっと他の方のCakePHPコードを動かす機会が合ったんですが、微妙に詰まったので記録しておく。 DockerでサクッとMySQL8とCakePHP4系の環境を立ち上げたんですよ。でmigrateするじゃないですか。こうなるんですよ

2020-06-28 03:26:02 Error: [InvalidArgumentException] There was a problem connecting to the database: SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client in /var/www/html/mycakeapp/vendor/robmorgan/phinx/src/Phinx/Db/Adapter/PdoAdapter.php on line 82

はい(´・ω・`)

認証できないってやつですね。もちろんUSER/PASSは同じであることを確認済み。
しかし、ついでに入れていたPHPMyAdmin側では認証が通る。とても不思議。MySQL側のコンテナに入ってログインしてみても通る。
ここまでで「これはPHP環境に問題があるのだろう」と特定して深堀り。

まず、php側のDocker環境に入り、iputils-pingを入れて疎通をみる。OK、疎通している。 次に、mariadb_clientを入れてつなぎに行こうとすると

ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

なるほど。caching_sha2_passwordが設定されているユーザーになっているのが原因っぽそう。


ちょっと調べてみたところ、MYSQL8.0からデフォルトの認証プラグインが、caching_sha2_passwordに変わっているんですが、PDO_MySQLを使う場合この認証方式を使えない模様。 https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password-compatible-connectors

で、接続しようとしていたユーザーはcaching_sha2_passwordを使う設定になっていたため、USER/PASS合っても弾かれる問題が起こっていたようです。 PHPMyAdmin側でユーザー設定変えてやれば、ちゃんと疎通できるようになりました。

Terraform: s3をbackendに使う際にcredentialsをどう使うか

docker上でTerraform + aws cliの環境を作ってやってます 認証情報はshared-credentialで管理している。環境変数でもいいんですが、個人的にはcredential派。

んで、 s3をバックエンドにしてterraform initしようとしたらこうなる。

Error: No valid credential sources found for AWS Provider.
        Please see https://terraform.io/docs/providers/aws/index.html for more information on
        providing credentials for the AWS Provider

エラーの内容的に認証情報が解決できないらしい。特に指定なしだと対した情報が拾えないので、TF_LOG=TRACE terraform initとしてログをみたりしていた。

結論はprofileの指定がないこと。 https://www.terraform.io/docs/providers/aws/index.html を見る限りAWS_PROFILEで渡しても良いらしいんですが、都度都度書きたくないんですよね(´・ω・`)

結論、backend側設定書いてやれば動いた。

terraform {
  backend "s3" {
    bucket = "bucket_name"
    key       = "tf-saved-path"
    region  = "us-east-1"
    profile  = "profile_name" # これ
  }
}

Terraform has been successfully initialized!

良し(`・ω・´)

唐突にWSL2が[4294967295]をはくようになった

結論

さあ今すぐ、Windows Updateだ。

起きたこと

WSL 2
[プロセスはコード 4294967295 で終了しました]

朝起きてさて開発しようかとPCを起動し、「あれ? WSLターミナル落ちてるじゃん、起動しなおすか」から出てきた以上。 夜あれだけ元気に動いていたのに(´・ω・`)

ちなみに何度立ち上げてもだめ。普通にPowerShell側から呼び出しても、WSLという文字列だけ残して無反応。
再起動も試したが再現する。これじゃ仕事に差し支えるので調査を開始

調査

ここで使うのは、エラーコード。特徴あるコードだからすぐ見つかるだろうとググると即出る。

github.com

しかし内容を見ると、今年の2月3月あたりの話であって、今起きている問題とは関係ない気がする。
以下のコマンドが解決策として提示されていた。

I fixed same problem by "netsh winsock reset"

コマンド的にはWindowsが持っているSocket通信用ライブラリの、TCP/IP接続のリセットであることが分かったので、適当に叩いてもOKだろうととりあえず実行する。実行後、通知に促されるまま再起動。


しかしダメー
ヾ(:3ノシヾ)ノシ


再度調査に戻る。

WSL用のLinuxカーネルの提供方法が変わるらしい

そして見つけた以下の記事。

japan.zdnet.com

 Microsoftは米国時間6月10日、「Windows 10 Insider Preview Build 19645」を「Windows Insider」プログラムの「Fast」リング向けに公開した。このビルドでは、「Windows Subsystem for Linux(WSL)2」用のLinuxカーネルがOSイメージから削除されている。

なるほど。タイミング的にこれが当たってしまったらしい。
イベントビューワーでWindows Updateのログを見てみる。

情報   2020/06/13 4:09:31  WindowsUpdateClient 41  Windows Update エージェント
- EventData 
  updateTitle Windows 10 Insider Preview 19645.1 (mn_release) 
  updateGuid {3e1470ab-9107-460a-87ad-f801336beb4a} 
  updateRevisionNumber 1 

確かに当たってるな。

記事を見る限りだと、

カーネルを最新の状態に保つことを確実にするために、そのアップデートを他のドライバーのアップデートと同様に「Windows Update」経由にするという考え方に基づいている。

とある。つまりWindows Updateで落ちてくる可能性が高いことを示す。Windows Update開いて更新をチェックすると1つヒットしたものがあるらしい。適用して再起動。

f:id:gdgd-shinoyu:20200613152044p:plain
生き返ったWSL

よしきた( ゚д゚)

結局何を入れなければいけなかったのか

動作するようになったとき、何が反映されたかをチェックしておく。

情報   2020/06/13 14:43:58 WindowsUpdateClient 41  Windows Update エージェント

- EventData 
  updateTitle Windows Subsystem for Linux Update - 4.19.104 
  updateGuid {d995d77f-fc67-467b-bcbd-950ea217623d} 
  updateRevisionNumber 200 

確かにLinuxの何らかの変更が落ちてきていた。 お前だったのか。

Docker上のruby:alpineにて、bundlerがrails-assets.orgに繋がらなくなっていた

タイトルどおりではあるが、急にbundlerが外部と疎通できなくなっていた(´・ω・`)

ほんの数日前までは特に問題なく動いていたんですが、さて個人の仕事をやらねばなと腰をあげたところ食らってしまい、起きているのがシンドい時間まで突入してしまいました。

環境はWSL2 Ubuntu上の、ruby:2.6.2-alpine docker-compose run --rm {service} bundle installで動かすと発生しました。

Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from https://rails-assets.org/

うーむ。まあエラーの内容通り外部と疎通できないのが要因だろうけれども。curlなりpingなり、存在しているところに飛ばしてもbad accessが発生してる。
調査のためにdigいれようと、apkでbind-toolsを引っ張ろうとしてもコケるので、コンテナ内部でなにか名前解決に問題が発生しているような気がしている。あ、IPアドレスで疎通できるかの確認してなかった(´・ω・`)

どちらにせよ、bundleの問題ではないと判断。まあこういうときは一度コンテナをビルドし直すと解消することがこれまで多かったので、今回もザクッとつくりなおしてみることにした。

docker-compose build --no-cache {service}

実行するとすくなくともapkは正常に走っていることがわかる。コンテナ内部の問題ではなさそう

doker-compose run --rm {service} bundle install

どうやら正常に名前解決できるようになった模様。

Bundle complete! 63 Gemfile dependencies, 150 gems now installed.
Bundled gems are installed into `/usr/local/bundle`

原因が不明だとちょっと気持ち悪い(´・ω・`)


いろいろと調べてみると、resolve.confにnameserver 8.8.8.8すると解決するという話がちらほらとあるわけで。名前解決になにか問題があることは理解したんですが、なぜ急に動かなくなったかは不明でした。

ちょっと深堀りしてみたら、ひとつ気になるものを見つけたんですが。
https://qiita.com/frost-tb-voo/items/fcc0c0fe7561b9101bf4

何も設定していない状態の dockerd では,ホストの /etc/resolv.conf をマスク(上書き)したファイルがコンテナ内部の /etc/resolv.conf として mount される.

WSL2では、resolve.confにはWSLホストであるWindowsIPアドレスが入ってるんですよね。確か。WSLでX Window試してみたことある人はわかると思うんですが、WSL起動ごとにこのresolve.confのIPアドレスが変わるわけですよ。
https://qiita.com/SoraKumo/items/388a1315a6bdc16b4d2e


つまり、dockerのコンテナ生成したタイミングでは、その時のWSL側のresolve.confがコピーされて使われる。しかし、WSLを起動し直すなどしてWSLのIPが変わってしまうと、その場合でもDockerのコンテナ側のresolve.confには古いIPが記録されており、ここに名前解決をしにこうとする。当然そのIPで応答するやつはいないので、解決できずに死ぬ。という動きが考えられるかもしれない。

普段再現しないのは、そもそもWindowsPCを終了することがほとんどなく、スリープ運用しているからで説明はつく。


まあ、状況から考えた仮説でしかないので、実際に何が問題としてあったかはわからずじまい(´・ω・`) 先にnameserver 8.8.8.8追加を試すべきだった。

まあ仮説どおりだとするとまた再現しそうな気はしているので、その時調べればいいかなというお気持ちです。

2019年、何をしてきたのかを振り返る

去年の年末にこんなエントリを上げました。 gdgd-shinoyu.hatenablog.com

あれからもう一年経ってしまいましたね(´・ω・`) 気を抜くと一年あっという間に終わってしまう現象に見舞われてしまい、年々時の過ぎ去りし速度が増していく感覚を味わってます。

ちょっとこちらの更新が色々と止まっていましたが、その分仕事に追われる一年でしたね...まだこの流れは続きそうですが可能な限りアウトプットをしていくようにはしたいですねぇ....

今年の振り返り

さて、去年のエントリで「ここ数年で一番動きがあった一年」と書いていましたが、今年は更に大きな動きのあった一年だったと思います。


大きく2点あるのですが、まず本格的に副業を始めたこと。

もともと知り合い経由でちょっとした作業をもらうくらいはやっていたんですが、本格的に仕事として請けるって経験はなかったんですよね。そんな中、とあるスタートアップ企業からTwitterで回ってきた募集から始まった仕事がありまして、それに手伝わせてもらいました。

今も仕事を頂いていて大変ありがたい限りなのですが、参画した当初は活躍できなかったなーという反省が大きかった一年です。 Golangを本格的に書いたのは初で私としてはとても良い経験をさせてもらっていたんですが、やはり事業としてやられているので力不足なのは否めず。結局Golangではなく慣れたRails側のタスクを回してもらっていました。

まあ、後で書く話に繋がるんですがこの件に関しては、大いに力不足を感じさせる一年ですね... 当時の所属会社ではエンジニアリングから離れて初のプロダクトマネジメントの仕事をやることになり、開発から離れていたのも焦る要因でした。「このままではいけない」の気持ちを強くした一年だったと思います。


もう一つは、小さな会社に転職したこと

今年の10月くらいなのでまだ最近の話ではあるんですが、まともにプロダクト開発ができない職場から、受託で生計立てている会社に転職することになりました。ここもまあ、色々と悩んだ選択ではあったのですが、すでに仕事が完成された企業ではないところを選びたかった、というのが理由でした。

所属していた会社で感じたことなんですが、ある程度事業の柱となる製品がある会社では、現状から逸脱した何かをやりにくい、という課題が見えたんですね。 ECモール事業をやっていた会社で、もともと楽天Amazonに勝てる方法を考えてプロダクト開発をしていく体で入社したんですよ。ただ、蓋を開けてみると楽天ベンチマークの施策を行うことが多く、最終的には親会社の意向に沿って開発するだけの会社になってしまい。 そういうところを経験したこともあって、よいプロダクトを志向していくためには新たに作り上げるところから入っていかないとダメだ、と結論付けました。プロダクト本体もそうですが、それを作るチーム、組織も作っていくべきだと。

そういう想いを持って、様々なジャンルの事業をされているいろいろな会社とお話をさせていただいたときに感じたんですが、 ある程度会社が大きくなり回すだけになっている会社では諸々整理されていることが多く、新しく何かを作り上げていくという経験があまり狙えないんですよね。

ガンガン新規事業を作っている会社もいくつかあったんですが、そういうところは大量に募集をかけて人を取っているため、自分の動ける範囲はかなり限定されてしまう。各事業の責任者はその会社でも要職な人が多くプロダクトを作る組織は概ねもうできている。そこに自分が動ける可能性を感じることができなかったのです。 単純に1エンジニアとして働くならそういう企業を選んでメンバーとしてJoinするのがおそらく最適解ではあったのでしょうね。


で、そういう会社の話を伺って散々悩んだ結果今の会社にJoinすることになります。成長意欲はあるが実態なかなか伸ばせていない。そういう課題を持っている企業です。

まあ待遇は前より下がってはいるんですが、会社を伸ばすために何をするべきか?のところから任せてもらえる数少ない会社でした。そのへんをやってもらいたいと言われる。自分のやりたい方向性にマッチしていたのと、伸ばし甲斐の高さに惹かれてJoinを決めてます。

まだ入社して2ヶ月、3ヶ月ほどですが会社の「次」を見据えた評価制度を考えさせてもらったり、社内にエンジニア文化を広げるための活動を主導させてもらったりと、いろいろと動かせてもらっています。幸い、自分が動いた分の効果が芽吹いてきており、今後一年本腰を入れて立ち会って行けるとおもしろい光景をつくれそうだな、という確信があるので、今後も楽しくい仕事はできそうだと思っています。

その話の片鱗は、 https://qiita.com/shinoyu/items/5888fa769a3f28b23f45 とかを見ていただくとなんとなく分かるかと思います。このアドベントカレンダー自体もその一部ですね。

とにかく動かしてみて結果を追わせてもらえる。そういう活動を今後もしていきたいと考えてます。



さて、今の時点で結構長くなっちゃったんですが、今年一年を統括して言えることは、『やってみる』を体現してきた一年だった、ということですかね( ・`ω・´) 転職して、組織づくり会社づくりから携われる。これまでの1開発者から一歩踏み出した先の仕事にチャレンジできている。 つまり、去年誓った「期待以上の一年にする」という点について、無事達成できたのではと感じてます。

来年目指していきたいこと

ここまでは今年の話。ここからは来年の話。


いろいろと展望は考えているんですが、まずなにより今の会社の「次」を作り出すことですかね。 今動いている評価制度の切り替えもそうですし、新しく自社プロダクトを走らせようとしているタイミングです。 まずはこの辺を実行に移して確かなものにしていく。そういうところに注力していこうかと。


あとは純粋に開発者としての技術力を高めること。 少なくとも思いついた事業をすぐ形にできるプロトタイピング力を強化することを目的にしていきたいです。 今のところ、バックエンドはだいたい分かるようになってきました。フロントエンドとインフラ部分の知識が弱いのでここを強化した上で、 更にグラフィックデザインあたりを履修して、自分でPoCできる精度くらいのモノを作る力を得たいと考えています。



ザクッとした目標なのでどこかのタイミングで精緻化は必要ですが、まずはこの2つを確実に達成していく一年にしていく。まずは今見えている山に向けて一歩から。来年また同じように報告できるよう、やっていきします!

alpine+Railsでの ld-linux-x86-64.so.2: No such file or directory 問題について

使っているイメージ: ruby:2.6.5-alpine

techblog.gmo-ap.jp

この症状と全く同じ。ld-linux-x86-64.soが不足していると言われる。

LoadError: Error loading shared library ld-linux-x86-64.so.2: No such file or directory (needed by /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so) - /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so

このときのDockerfileは以下の通り

FROM ruby:2.6.5-alpine
ENV LANG C.UTF-8
ENV BUNDLE_JOBS 4
WORKDIR /usr/local/src

... いろいろディレクトリのADDとかやっているところ

RUN apk update \
  && apk add --update --no-cache \
    git \
    build-base \
    curl \
    tzdata \
    xz-dev \
    mariadb-client \
    mariadb-dev \
    mariadb-connector-c \
    libc6-compat \
    libssl1.1 \
  && rm -rf /var/lib/apt/lists/* \
  && gem update --system \
  && gem install bundler \
  && RAILS_ENV=$RAILS_ENV CFLAGS="-Wno-cast-function-type" BUNDLE_FORCE_RUBY_PLATFORM=1 bundle install --deployment

EXPOSE 3000

ld-linux-x86-64.so.2はlibc6-compatに入っているもので、apk addしているやつに含めている。

pkgs.alpinelinux.org

配置場所こそlibではなくlib64だが、64bit向けビルドするとシステム的に自動判定されるはず(´・ω・`)


考えても何もわからなかったので、冒頭のリンクで紹介されていた https://hub.docker.com/r/frolvlad/alpine-glibc/dockerfile を試すことに。 ただ、これをDockerfireに適用するのかなり大掛かりな気がして、このdockerfileの中で使われている以下の導入をそのまま実行。

github.com


検証なのでなるべくミニマムでな。これ通りやればすんなりdocker-compose build --no-cache nameで、イメージビルド自体は通った。

docker-compose runでコンテナの中に入り、まずは手動で実行してbundle install。 特に問題なくGemは入る。その後、consoleなりmigrationを実行すると以下のようなエラーが発生してしまう。

/usr/local/src # RAILS_ENV=development bundle exec rails db:migrate
/usr/local/bundle/gems/google-protobuf-3.9.2-x86_64-linux/lib/google/protobuf/any_pb.rb:17: [BUG] Segmentation fault at 0x0000000000019266
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux-musl]

セグフォをくらう(´・ω・`)うーん....


セグフォの情報を元に調査すると、似たような症状を食らっている人が報告しているIssueを見つけた。

github.com

これを一通り読んでいった結果、結論、これで問題が解消した。

Segmentation Fault (Segfault) on the ruby gem · Issue #4460 · protocolbuffers/protobuf · GitHub

gem "grpc", "1.21.0", platforms: ["ruby"]
gem "google-protobuf", "3.8.0", platforms: ["ruby"]


ただ、確かに問題は解決するんだが、原因が全然わからず気持ち悪い(´・ω・`)で、いろいろ探した結果、以下に行き着いた。

github.com

I did a bit of digging and found that it was due to alpine gcc not being able to compile boringssl library due to function type cast error.

alpineのgccだと、boringsslのビルド時にキャストエラーで落ちてしまうらしい。なるほど。


ここで重要なのはおそらくplatforms: ["ruby"]
このオプションを指定することで、強制的にCRuby (MRI)としてビルドするように指定している。そうするとalpine向けでないビルドになるので、Alpineのgcc起因の問題は回避できるのだろうと理解しました。

意外なところで使えるMakefile

昨今Dockerを用いたコンテナ開発しているところでは、割と採用されているのではないでしょうかMakefile何番煎じかわからない内容ですが、とっても便利ですよ( ・`ω・´)


C++触っていたときはMakefileに大変お世話になっていましたが、その後JavaC#と渡っていくうちに、言語ごとのビルドツール(当時はantとかmsbuildとか)を使うことになりしばらくご無沙汰だったわけですね(´・ω・`)

特にWeb開発でLL言語開発を長くやっていると使うケースがあまりありませんでした。複雑なビルド等しないわけだし、Railsだとrakeって生き物もいるわけで。ほとんど見ることはありませんでした(少なくとも私の周辺では)


しかし最近、何でも実行できるそのポテンシャルが、普段利用していない層の人々にも評価されたのか、Docker活用した開発現場での利用が増えてきたように感じます。

今自分が担当してるRailsとVue.jsのプロジェクトではこんな感じのものを入れてます。

update:
    @make rails/bundle # 別のコマンド叩く場合@make {command}
    @make yarn/install
    @make rails/migrate

yarn/install:
    docker-compose run --rm web yarn install # フロントはpackage.jsonで実体を管理しておいて呼び出すだけ
 
yarn/build:
    docker-compose run --rm web yarn build

yarn/clean-build:
    docker-compose run --rm web rm -rf node_modules/.cache/hard-source/
    @make yarn/build
 
rails/bundle:
    docker-compose run --rm app bundle install
 
rails/migrate:
    docker-compose run --rm app bundle exec rails db:create db:migrate
 
rails/restart:
    docker-compose run --rm app bundle exec rails unicorn:restart

すごく簡易的なやつですが、docker-compose系のコマンドを手打ちしなくて言い分すごく楽です。人によってはalias作ったりshファイルを作成したりしているかもしれませんが、1ファイルにそのプロジェクトで使うコマンドだけを管理できるので、他の方法より管理手間が省けるかと感じてます。


特に強いのがコマンドの補完が効く。make yarn/buildならmakeとtypeしてy + tab、b + tab、でコマンド実行できます。完全に覚えてなくても補完で乗り切れるのは嬉しい。

zsh、fish使っている方なら間違いなく補完できるかと思います。bashユーザーなら bash-completionを入れる必要がありますがMac使っている方ならHomebrewでサクッと入ります。


Makefileには無限の可能性があるんだ、ということを言いたいがための紹介でした。