RHEL8小ネタ: 大量にある"glibc-langpack-*" パッケージの謎からコンテナイメージのサイズ削減の工夫をみる

大量のglibc-langpack-* パッケージ

レッドハットの森若です。

RHEL 8 betaで、yum search glibc のようなコマンドを打つと、大量の glibc-langpack-* というパッケージが出力されて画面が埋めつくされます。RHEL 7までには無かったものなので、ちょっと見てみましょう。

f:id:mrwk:20190117204241p:plain
glibc-langpack-*で埋めつくされたyum search glibcの出力

glibc-langpack-* パッケージって何だろう?

試しにglibc-langpack- で始まるパッケージを数えてみると199個もありました。

[root@client ~]# yum list --available glibc-langpack-\*|wc
    199     609   15988

もう少しくわしく見るために、実際にインストールされている glibc-langpack-en パッケージに含まれるファイルを見てみます。

[root@client ~]# rpm -ql glibc-langpack-en
/usr/lib/locale
/usr/lib/locale/en_AG
/usr/lib/locale/en_AG/LC_ADDRESS
/usr/lib/locale/en_AG/LC_COLLATE
/usr/lib/locale/en_AG/LC_CTYPE
/usr/lib/locale/en_AG/LC_IDENTIFICATION
/usr/lib/locale/en_AG/LC_MEASUREMENT
/usr/lib/locale/en_AG/LC_MESSAGES
/usr/lib/locale/en_AG/LC_MESSAGES/SYS_LC_MESSAGES
/usr/lib/locale/en_AG/LC_MONETARY
/usr/lib/locale/en_AG/LC_NAME
/usr/lib/locale/en_AG/LC_NUMERIC
/usr/lib/locale/en_AG/LC_PAPER
/usr/lib/locale/en_AG/LC_TELEPHONE
/usr/lib/locale/en_AG/LC_TIME
/usr/lib/locale/en_AU
/usr/lib/locale/en_AU.utf8
/usr/lib/locale/en_AU.utf8/LC_ADDRESS
/usr/lib/locale/en_AU.utf8/LC_COLLATE
/usr/lib/locale/en_AU.utf8/LC_CTYPE
/usr/lib/locale/en_AU.utf8/LC_IDENTIFICATION
(以下略)

どうやらlocaleのenjaをサポートするためのファイルが、言語毎に別パッケージになっているようです。localeとは、日付や時刻の表記、"1,000,000.4" のような数値や通貨の表記、メッセージなどを言語や地域の習慣にあわせて切り替えるための仕組みです。

なぜパッケージを分割したのか?

なぜこのような変更をしたのでしょうか? パッケージ構成の変更などはFedoraで行われたものがRHELに反映されていくので、Fedora Projectのwikiを探します。以下のページが見つかり、どのような議論を経てこの変更が行われたかがわかります。

fedoraproject.org

Detailed Description

Currently the file /usr/lib/locale/locale-archive contains all locales and is thus huge (103MB).

For small systems (and containers) it would be useful to be able to install only a small number of locales.

「小さなシステムやコンテナイメージのサイズを縮小するため、必要最小限のlocaleだけをインストールできるようにしたい」という理由でした。さらにこのページを読んでいくと glibc-all-langpacks というパッケージが提供されており、(RHEL7までと同様に)全てのlocaleが利用できるシステムも簡単に利用できるようになっていることもわかります。

fedoraproject.org

fedoraproject.org

この話はglibcだけに特化した話ではありません。Language Packsと呼ばれるパッケージ群により、ソフトウェアの各言語に対応する部分を別パッケージにして必要な言語への対応だけを自動的にインストールするプロジェクトの一部です。

具体的には、langpack-jaのようなlangpack-<言語名> というパッケージをインストールしておき、その後に各ソフトウェアをインストールすることで自動的に必要な言語をサポートした環境を構築できるようにします。この仕組みには、RHEL 8で導入されるRPMのweak dependencyが活用されています。

どれくらい効果があったのか?

では実際どのくらい効果があったのか、Red Hat Container Catalogを見てみます。 access.redhat.com

RHEL 7 のbase imageは 72.2MB に対して、RHEL 8 betaのbase imageは66.5MB ということで、あまり変わりません。そもそもlocale-archiveファイルが100MBほどあるという記述を考えると、RHEL 7のイメージからもどうにかして削除されていそうです。

コンテナイメージの中をみてみる

両方のイメージを docker pull (RHEL8のdockerコマンドはpodman-dockerパッケージで提供されます)して比較してみます。RHELのコンテナイメージは、どのように作成されたかがanaconda-ks.cfgでわかるようになっています。

# docker pull registry.access.redhat.com/rhel7
# docker pull registry.access.redhat.com/rhel8-beta/rhel

RHEL7のanaconda-ksでは、以下のようにlocale-archiveを削除してからen_US.UTF-8だけを生成しなおしていました。

rm -f /usr/lib/locale/locale-archive
#setup at least some locale, https://bugzilla.redhat.com/show_bug.cgi?id=1129697
localedef -v -c -i en_US -f UTF-8 en_US.UTF-8

RHEL8では、この処理は無くなり、glibc-minimal-langpackパッケージをインストールするだけになっています。小さなコンテナイメージを作成する際の「特別な工夫」がひとつ排除されています。

まとめ

  • 大量にあるglibc-langpack-* は、必要最低限のlocaleデータだけをインストールできるように工夫されたもの
  • Red Hatが配布しているイメージでは、RHEL7でもkickstartのpostスクリプトでlocale-archiveを一旦削除しているためサイズへの影響はほとんどない
  • この変更の結果、RHEL7までは必要だった小さなコンテナイメージを作成する際の「特別な工夫」が不要になっている

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません