Universal Base Images (UBI) 8 を日本語ロケールにする

配布されている Universal Base Images (UBI) 8 のロケールは C.utf8 ですが、用途によっては日本語ロケール ja_JP.utf8 で使用したいことがあります。そこで、UBI 8 を日本語ロケールにする方法を調べてみました。
ここで扱うのは、UBI 8 で UBI minimal ではありません。

## まずは、調査してみる
`docker run --rm -it registry.access.redhat.com/ubi8/ubi:latest bash` で起動して、淡い期待をもって `locale -a` を実行してみましたが、やはり最初から日本語ロケールが組み込まれているということはありませんでした。

```
C:\>docker run --rm -it registry.access.redhat.com/ubi8/ubi:latest bash
[root@61670851e75a /]# locale -a
C
C.utf8
POSIX
```

次に、利用できる langpacks をサーチしてみましたが、提供されているのは英語のものだけです。
`glibc-all-langpacks.x86_64` がありますが、これを インストールしてもロケールは追加されませんでした。

```
[root@61670851e75a /]# dnf search langpacks
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
Last metadata expiration check: 0:02:02 ago on Fri Jan 10 07:24:31 2020.
========================================================= Name & Summary Matched: langpacks ==========================================================
langpacks-en.noarch : English langpacks meta-package
langpacks-en.noarch : English langpacks meta-package
============================================================== Name Matched: langpacks ===============================================================
glibc-all-langpacks.x86_64 : All language packs for glibc.
```

locale でサーチすると、いくつかパッケージが見つかりました。
`glibc-common.x86_64` をインストールすると、en_XX 系のロケールはインストールできましたが、日本語は追加されません。
残るは、`glibc-locale-source.x86_64` なるパッケージです。source とあるので、これを使って日本語ロケールを定義することにします。

```
[root@61670851e75a /]# dnf search locale
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register.
Last metadata expiration check: 0:17:23 ago on 2020年01月10日 07時24分31秒.
=========================================================== Name & Summary Matched: locale ===========================================================
glibc-locale-source.x86_64 : The sources for the locales
perl-Encode-Locale.noarch : Determine the locale encoding
perl-Locale-Codes.noarch : Distribution of modules to handle locale codes
perl-Locale-Maketext-Simple.noarch : Simple interface to Locale::Maketext::Lexicon
================================================================ Name Matched: locale ================================================================
perl-Locale-Maketext.noarch : Framework for localization
============================================================== Summary Matched: locale ===============================================================
glibc-langpack-en.x86_64 : Locale data for en
glibc-common.x86_64 : Common binaries and locale data for glibc
glibc-common.x86_64 : Common binaries and locale data for glibc
```
## 日本語ロケールを組み込む
`dnf install -y glibc-locale-source` で source をインストールし、localedef で日本語ロケールを定義することで、日本語ロケールが使用できるようになりました。
手順は以下の通りですが、分かってしまうと簡単ですね。

```
C:\>docker run --rm -it registry.access.redhat.com/ubi8/ubi:latest bash
[root@0f88101d5c72 /]# dnf install -y glibc-locale-source
(出力は省略)
[root@0f88101d5c72 /]# localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
[root@0f88101d5c72 /]# locale -a
C
C.utf8
POSIX
ja_JP.utf8
[root@0f88101d5c72 /]# echo LANG=ja_JP.UTF-8 > /etc/locale.conf
[root@0f88101d5c72 /]# export LANG=ja_JP.UTF-8
[root@0f88101d5c72 /]# export LC_ALL=ja_JP.UTF-8
[root@0f88101d5c72 /]# date
2020年  1月 10日 金曜日 07:53:26 UTC
```

## タイムゾーンを変更する
`date` コマンドの出力を見て、タイムゾーンの変更が必要なことを思い出しました。
まずは、調査ですが、zoneinfo を確認してみると、各地域のゾーン情報(tzdata)が入っていて、Asia/Tokyo もありました。

```
[root@0f88101d5c72 /]# ls /usr/share/zoneinfo/
Africa      Atlantic   Canada  EST5EDT  GB       GMT0       Indian   Kwajalein  Mexico   PST8PDT   ROK        UTC        iso3166.tab  tzdata.zi
America     Australia  Chile   Egypt    GB-Eire  Greenwich  Iran     Libya      NZ       Pacific   Singapore  Universal  leapseconds  zone.tab
Antarctica  Brazil     Cuba    Eire     GMT      HST        Israel   MET        NZ-CHAT  Poland    Turkey     W-SU       posix        zone1970.tab
Arctic      CET        EET     Etc      GMT+0    Hongkong   Jamaica  MST        Navajo   Portugal  UCT        WET        posixrules
Asia        CST6CDT    EST     Europe   GMT-0    Iceland    Japan    MST7MDT    PRC      ROC       US         Zulu       right
[root@0f88101d5c72 /]# ls /usr/share/zoneinfo/Asia/Tokyo
/usr/share/zoneinfo/Asia/Tokyo
```

タイムゾーンは、普通の方法で変更するだけで済みました。

```
[root@0f88101d5c72 /]# ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
[root@0f88101d5c72 /]# export TZ=Asia/Tokyo
[root@0f88101d5c72 /]# date
2020年  1月 10日 金曜日 17:03:05 JST
```

## 日本語ロケールにしたイメージをビルドする
手順が分かったので、Dockerfile を作ってイメージをビルドします。以下のような Dockerfile にしてみました。

``` Dockerfile
FROM registry.access.redhat.com/ubi8/ubi:latest
RUN  dnf update -y \
  && dnf install -y glibc-locale-source \
  && localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 \
  && echo LANG=ja_JP.UTF-8 > /etc/locale.conf \
  && dnf remove -y glibc-locale-source \
  && dnf clean all \
  && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
ENV LANG="ja_JP.UTF-8" \
    LC_ALL="ja_JP.UTF-8" \
    TZ="Asia/Tokyo"
```

ビルドして確認してみます。

```
C:\ubi-jp>docker build -t ubi8-jp .
Sending build context to Docker daemon  2.048kB
(省略)
Successfully tagged ubi8-jp:latest
(省略)

C:\ubi-jp>docker run --rm -it ubi8-jp bash
[root@143587d7dbf8 /]# date
2020年  1月 10日 金曜日 17:09:51 JST
[root@143587d7dbf8 /]# ls -al
total 60
drwxr-xr-x   1 root root 4096  1月 10 17:09 .
(省略)
drwxr-xr-x   1 root root 4096 12月 11 02:50 var
[root@143587d7dbf8 /]# sss
bash: sss: command not found
[root@143587d7dbf8 /]#
```

## 最後に
UBI 8 を日本語ロケールに変更することができました。
詳細は触れませんが、UBI-minimal 8 や UBI 7 でもチャレンジしてみました。

UBI-minimal 8 は、UBI 8 と同じ方法で日本語ロケールを追加できました。但し、localedef が使用する gzip が入っていないので、追加する必要があります。
さらに、ゾーン情報(tzdata)は自力で追加する必要がありました。`microdnf install -y tzdata` で追加したいところですが、インストール後に不要なものを rm コマンドで削除しているようで、`microdnf install -y tzdata` を実行しても追加できませんでした。
rpm パッケージをダウンロードして rpm2cpio と cpio -idv を使って力ずくで追加するしか方法がなさそうでした。

```
microdnf install -y cpio
curl https://cdn-ubi.redhat.com/content/public/ubi/dist/ubi8/8/x86_64/baseos/os/Packages/t/tzdata-2019c-1.el8.noarch.rpm | rpm2cpio | cpio -idv
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
microdnf remove -y cpio
```