カテゴリー
Linux コンピューター

[hadolint] warning: Pin versions in apt get install. Instead of apt-get install use apt-get install = (DL3008) を正当な修正をして黙らせるまでの手順メモ

エラー詳細

DL3008 · hadolint/hadolint Wiki · GitHub

Docker イメージにパッケージをインストールするときに、バージョンが決め手になることは全然ないのですが、それだと hadolint が警告を出してきました。

無視したり、警告を抑制しても良いのですけれども、パッケージのバージョンをできるだけ細かく指定するべき、というのは、まあそうだよね、と思いましたので対応することにいたしました。

今回の例で取り上げるパッケージ

unzip 、および libpq-dev にバージョンを指定していないので、これらを例に取り上げます。もともと、この警告に対応してバージョンを明記していたのですけれども、久しぶりに Docker イメージのビルドを行ったところ、そんなバージョンは無い、と言われてしまったので、今回の投稿に繋がった背景もあります。そもそも、このようなケースの場合、バージョン指定などしなくてもよさそうな気もします。。。

対応流れまとめ。

  1. バージョン指定をしないまま、最新のパッケージを Docker イメージにインストールする。
  2. コンテナを立ち上げ、インストールしたパッケージのバージョンを調べる。
  3. 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.

ここまで来て、思い違いをしていたことに気がつきました。上記引用のベストプラクティスでは、 キャッシュ無効化を有効活用する観点から、バージョンを指定するべき 、とのこと。バージョンを細かく指定することが目的、では無かったです。よって、大雑把にメジャーバージョンの指定だけであとはワイルドカードにする、という決定でも、それで問題がなければよさそうです。

また、そもそも警告だし、メインとなるパッケージ以外はそこまでバージョンにこだわる必要がない、と割り切る場合は、警告を抑制する方法もありだと思います。

ただ単に方法を調べるだけではなく、投稿を書いていく中で考えを深めることができました。とても嬉しく感じたところで♪、以上です。

コメントを残す