Dockerfileで日本語ロケールを設定する方法。およびロケールエラーの回避方法。

日本語処理を行う開発時などDockerfileで日本語ロケールの設定を行う場合の設定です。

## せっかちな人のために

次の記述をglibcの更新処理（yum updateやyum reinstall glibc）より後方に記述します。
後方に記述しないと、glibcの更新によってlocaledefによるja_JP.UTF-8ロケールの追加がリセットされ、エラーが発生します。

```{Docker}
RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG="ja_JP.UTF-8" \
    LANGUAGE="ja_JP:ja" \
    LC_ALL="ja_JP.UTF-8"
```

上記はCentOS7の場合です。Ubuntuの場合は次のサイトなどを参照すると良いかもしれません。
https://qiita.com/suin/items/856bf782d0d295352e51

## テスト環境

 - ホストOS: CentOS Linux release 7.4.1708 (Core)
 - Docker: Docker version 17.12.0-ce, build c97c6d6
 - コンテナOS: CentOS Linux release 7.4.1708 (Core)

## ディストリビューションの設定コマンドは使えない

CentOS7のロケール設定コマンドである localectl はコンテナ上で実行できません。
systemctlなどと同様にエラーになります。

```{sh}
[user@container ~]# sudo localectl
Failed to create bus connection: No such file or directory
```

## 環境変数を直接設定する

Dockerfileでは環境変数を直接セットして日本語ロケールを設定します。
ところが、CentOS7の公式イメージでは設定できる既定ロケールが次の3つだけです。

```{sh}
[user@container ~]# locale -a
C
POSIX
en_US.utf8
```

このため、Dockerfileでは次のコマンドでロケールの追加を行う必要があります。
（この方法で作成するロケールをカスタムロケールというらしいです）

```{Docker}
RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
```

localedefコマンドの詳細については次のサイトなどを参照ください。
https://www.ibm.com/support/knowledgecenter/ja/SSLTBW_2.2.0/com.ibm.zos.v2r2.bpxa500/comlcdf.htm

上記で作成した日本語ロケールを次のコマンドで環境変数にセットします。

```{Docker}
ENV LANG="ja_JP.UTF-8" \
    LANGUAGE="ja_JP:ja" \
    LC_ALL="ja_JP.UTF-8"
```

これで日本語環境のコンテナを作成できます。

## ロケールエラーが発生する場合の回避方法

上記までの方法でDockerfileを作成したところ、テスト用コンテナでは問題なかったのですが、
複数の設定を入れた実用のDockerfileで次のようなエラーが発生するようになりました。
RUNコマンドの実行時などに発生します。

```{sh}
(error)
/bin/sh: warning: setlocale: LC_ALL: cannot change locale (ja_JP.UTF-8)
Failed to set locale, defaulting to C
```

作成されたコンテナで locale を確認すると LC_ALLなどの設定が落ちているようです。

```{sh}
[user@container ~]# locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=ja_JP.UTF-8
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
```

どうやら glibc関連のパッケージを更新すると、カスタムロケールが消えてしまうようです。
（なぜ、LANGなどの環境変数には値が残っているのか不思議ですが）
作成したja_JP.UTF-8が消えてしまったので、環境変数の内容と不整合が起きてエラーが発生しているようです。
例えばyumは実行時にLC_ALLの内容を確認しているようです。

回避策は
・ yum update などglibcを更新するようなタスクはlocaledefより先に実行する

<font color="Red">＊＊2018/7/10追記＊＊</font>
次の記事で解説されている方法で回避可能と思われます。
https://qiita.com/teruo-oshida/items/08cb84efc2b581b0a439
（コメントいただきありがとうございます。）

私の場合日本語設定に関する記述をDockerfileの比較的上の方に記載していたので、後方で実施していたyum updateでglibcが更新され、追加したロケールが消えていたようです。

## 参考

次のサイトを参考にしています
Ubuntuでの設定方法
https://qiita.com/suin/items/856bf782d0d295352e51

Ubuntu / CentOSでの設定方法
https://qiita.com/yuki2006/items/6cea8c352e38f047b52a#comment-8e863c71962008035d0d

glibcとロケールについて
（こちらではカスタムロケールを保存場所を指定して作成する回避策が紹介されています）
https://qiita.com/kaikusakari/items/9fa7fcab0bb07b5122be

localeの詳細
https://qiita.com/aosho235/items/58e2e7acd5c2ee3641ff

localedefコマンドの詳細
https://www.ibm.com/support/knowledgecenter/ja/SSLTBW_2.2.0/com.ibm.zos.v2r2.bpxa500/comlcdf.htm