エラー詳細
DL3008 · hadolint/hadolint Wiki · GitHub
Docker イメージにパッケージをインストールするときに、バージョンが決め手になることは全然ないのですが、それだと hadolint が警告を出してきました。
無視したり、警告を抑制しても良いのですけれども、パッケージのバージョンをできるだけ細かく指定するべき、というのは、まあそうだよね、と思いましたので対応することにいたしました。
今回の例で取り上げるパッケージ
unzip
、および libpq-dev
にバージョンを指定していないので、これらを例に取り上げます。もともと、この警告に対応してバージョンを明記していたのですけれども、久しぶりに Docker イメージのビルドを行ったところ、そんなバージョンは無い、と言われてしまったので、今回の投稿に繋がった背景もあります。そもそも、このようなケースの場合、バージョン指定などしなくてもよさそうな気もします。。。
対応流れまとめ。
- バージョン指定をしないまま、最新のパッケージを Docker イメージにインストールする。
- コンテナを立ち上げ、インストールしたパッケージのバージョンを調べる。
- Dockerfile に調べたバージョンをコピペする。
このうち、最初の手順である、 Docker イメージへの問題となるバージョン未設定パッケージのインストールは完了しているところから始まります。
修正対象のコード部分
RUN apt-get update && apt-get install -y --no-install-recommends \
libicu-dev=67.1-7 \
libjpeg-dev=1:2.0.6-4 \
libpng-dev=1.6.37-3 \
libpq-dev \
libzip-dev=1.7.3-1 \
unzip \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-configure \
gd --with-jpeg \
&& docker-php-ext-install \
bcmath \
gd \
intl \
pdo_mysql \
pdo_pgsql \
zip
そもそも、Debian の場合、パッケージのバージョンの確認はどうやったらできるのだろう?
php:8.1.9-apache
イメージを使っていますけれども、これは一体どんな Linux ディストロビューションを使っているのでしょうか? 結構な頻度で調べています。。。
php – Official Image | Docker Hub のページから、 docs/README.md at master · docker-library/docs · GitHub へとび、さらに php/Dockerfile at 1eda47a53c9c23c906c53148c0d6f3f88232e572 · docker-library/php · GitHub へ行くと、 Debian ということがわかります。
念の為、確認してみました。
app@2da372626249:/var/www/html/laravel$ cat /etc/issue
Debian GNU/Linux 11 \n \l
app@2da372626249:/var/www/html/laravel$
確かに、 Debian でした。
問題となるバージョン未設定パッケージのバージョンを調べる方法と実践
次に、 Debian でのパッケージバージョンを調べる方法を調べました。
apt-cache policy
を使います。
root@2da372626249:/var/www/html/laravel# apt-get update
Get:1 http://deb.debian.org/debian bullseye InRelease [116 kB]
Get:2 http://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB]
Get:3 http://deb.debian.org/debian bullseye-updates InRelease [44.1 kB]
Get:4 http://deb.debian.org/debian bullseye/main amd64 Packages [8184 kB]
Get:5 http://deb.debian.org/debian-security bullseye-security/main amd64 Packages [186 kB]
Get:6 http://deb.debian.org/debian bullseye-updates/main amd64 Packages [6344 B]
Fetched 8585 kB in 5s (1642 kB/s)
Reading package lists... Done
root@2da372626249:/var/www/html/laravel#
root@2da372626249:/var/www/html/laravel#
root@2da372626249:/var/www/html/laravel#
root@2da372626249:/var/www/html/laravel# apt-cache policy libpq-dev unzip
libpq-dev:
Installed: 13.8-0+deb11u1
Candidate: 13.8-0+deb11u1
Version table:
*** 13.8-0+deb11u1 500
500 http://deb.debian.org/debian bullseye/main amd64 Packages
100 /var/lib/dpkg/status
13.7-0+deb11u1 500
500 http://deb.debian.org/debian-security bullseye-security/main amd64 Packages
unzip:
Installed: 6.0-26+deb11u1
Candidate: 6.0-26+deb11u1
Version table:
*** 6.0-26+deb11u1 500
500 http://deb.debian.org/debian bullseye/main amd64 Packages
500 http://deb.debian.org/debian-security bullseye-security/main amd64 Packages
100 /var/lib/dpkg/status
root@2da372626249:/var/www/html/laravel#
セマンティック バージョニング 2.0.0 | Semantic Versioning でバージョニングされていると思い込んでおりましたが、そうでもないようです。とにかく、 Installed の部分をコピーして、バージョンを得ることができました。
Dockerfile 修正して、バージョンを指定したもの
RUN apt-get update && apt-get install -y --no-install-recommends \
libicu-dev=67.1-7 \
libjpeg-dev=1:2.0.6-4 \
libpng-dev=1.6.37-3 \
libpq-dev \
libzip-dev=1.7.3-1 \
unzip \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-configure \
gd --with-jpeg \
&& docker-php-ext-install \
bcmath \
gd \
intl \
pdo_mysql \
pdo_pgsql \
zip
おわりに
バージョンをワイルドカードを使って緩やかに指定することもできるようです。
- RUN apt-get Best practices for writing Dockerfiles | Docker Documentation
You can also achieve cache-busting by specifying a package version. This is known as version pinning, for example:
RUN apt-get update && apt-get install -y \ package-bar \ package-baz \ package-foo=1.3.*
Version pinning forces the build to retrieve a particular version regardless of what’s in the cache. This technique can also reduce failures due to unanticipated changes in required packages.
ここまで来て、思い違いをしていたことに気がつきました。上記引用のベストプラクティスでは、 キャッシュ無効化を有効活用する観点から、バージョンを指定するべき 、とのこと。バージョンを細かく指定することが目的、では無かったです。よって、大雑把にメジャーバージョンの指定だけであとはワイルドカードにする、という決定でも、それで問題がなければよさそうです。
また、そもそも警告だし、メインとなるパッケージ以外はそこまでバージョンにこだわる必要がない、と割り切る場合は、警告を抑制する方法もありだと思います。
ただ単に方法を調べるだけではなく、投稿を書いていく中で考えを深めることができました。とても嬉しく感じたところで♪、以上です。