ツー

日常の記録

DockerfileのFROMにlatestを書くな。バージョンを書け。

タイトルの通り。

経緯

GitHubにpush→wercker→CodeDeploy→EC2にデプロイという構成のアプリがある。

werckerではDockerが使えるので、amazonlinuxをベースに開発用のあれこれをいれた自作コンテナを作成して使用していた。 サーバ側であるPerldependency install & buildと、クライアント側であるNodeJSのdependency install & buildを行っている。

長らく放置していて、やっとの思いでリファクタリングを始めたが、クライアント側アプリのモジュールのバージョンを上げていくと、 nodeのモジュールが version imcompatible と言われて死ぬので、自作コンテナのバージョンアップせざるを得なくなった。

ちなみに node -v0.9 で、更新日付は 3 years ago だった。放置しすぎだろ。

フンフフンとかいいながらDockerfileを書き換えdocker build & push、なんだそんなに苦労しないやんけと思いながらwerckerでデプロイしたら 下記のようなエラーが出る。

/home/ec2-user/app/local/bin/plackup: relocation error: /home/ec2-user/app/local/lib/perl5/x86_64-linux/auto/DBD/mysql/mysql.so: symbol mysql_init, version libmysqlclient_18 not defined in file libmysqlclient.so.18 with link time reference

とりあえずライブラリのリンクがうまくいってないことはわかったが、なんでかがわからない。

perlDBD::mysqlmysql.so を作成するのでそれがおかしいのかなと思ったが、それを ldd してもちゃんとパスの先にはファイルがいるし、 LD_LIBRARY_PATH の読込順がおかしいのかと思い find / | grep libmysqlclient.so.18.0.0 とかやってもファイルが一つしかない。 ファイルがないとは言ってないし、読み込みはしているっぽい。

なんでや、と小一時間頭を抱えていた。

そこで気が付いた。AmazonLinux2ってだいたいそれくらい前(3年前)に一般公開になったよね。

aws.amazon.com

あたり。

もしかしてAmazonLinux1とAmazonLinux2で yum install mysql-devel で入るものが違う?となり実証した。

AmazonLinux1の場合。

$ docker run -it amazonlinux:1

bash-4.2# yum install mysql-devel
...

bash-4.2# ls -la /usr/lib64/mysql
total 2936
drwxr-xr-x 2 root root    4096 Jul 21 04:10 .
dr-xr-xr-x 1 root root    4096 Jul 21 04:10 ..
lrwxrwxrwx 1 root root      20 Jul 21 04:10 libmysqlclient.so -> libmysqlclient.so.18
lrwxrwxrwx 1 root root      24 Jul 21 04:10 libmysqlclient.so.18 -> libmysqlclient.so.18.0.0
-rwxr-xr-x 1 root root 2983624 Dec  3  2018 libmysqlclient.so.18.0.0
lrwxrwxrwx 1 root root      17 Jul 21 04:10 libmysqlclient_r.so -> libmysqlclient.so
-rwxr-xr-x 1 root root    7035 Dec  3  2018 mysql_config
lrwxrwxrwx 1 root root      12 Jul 21 04:10 mysql_config55 -> mysql_config

AmazonLinux2の場合。

$ docker run -it amazonlinux:latest

bash-4.2# yum install mysql-devel
...

bash-4.2# ls -la /usr/lib64/mysql/
total 3092
drwxr-xr-x 3 root root    4096 Jul 21 04:11 .
dr-xr-xr-x 1 root root    4096 Jul 21 04:11 ..
lrwxrwxrwx 1 root root      20 Jul 21 04:11 libmysqlclient.so -> libmysqlclient.so.18
lrwxrwxrwx 1 root root      24 Jul 21 04:11 libmysqlclient.so.18 -> libmysqlclient.so.18.0.0
-rwxr-xr-x 1 root root 3139440 Oct 15  2020 libmysqlclient.so.18.0.0
lrwxrwxrwx 1 root root      17 Jul 21 04:11 libmysqlclient_r.so -> libmysqlclient.so
-rwxr-xr-x 1 root root    6758 Oct 15  2020 mysql_config
drwxr-xr-x 2 root root    4096 Jul 21 04:11 plugin

ファイルが違ったわ。予想はあってた。

EC2、自作コンテナ上、それぞれの libmysqlclient.so.18.0.0 を調べたところ、EC2はAmazonLinux1、DockerはAmazonLinux2と同じサイズだった。

ここでDockerfileに latest を指定していたからだと気が付く。

三年前のlatestはv1、現在のlatestはv2ですね。あーあ。 なので自作コンテナのほうで指定している FROM のバージョンを AmazonLinux1 にした。

他にもいろいろエラーはあったが、おおもとの原因は上記だったので解決。

いやそもそもAmazonLinux1使ってるなよというのはごもっともなので、頃合いを見て置き換える。

まとめ

FROM amazonlinux:latest

latestではなく

FROM amazonlinux:1

バージョンをちゃんと書きましょう。

放置しすぎたものを最新に追随しようとすると苦行しかないぞ。(おまえこの前も似たようなこと言ってたよな)

参考