日本語処理を行う開発時などDockerfileで日本語ロケールの設定を行う場合の設定です。
せっかちな人のために
次の記述をglibcの更新処理(yum updateやyum reinstall glibc)より後方に記述します。
後方に記述しないと、glibcの更新によってlocaledefによるja_JP.UTF-8ロケールの追加がリセットされ、エラーが発生します。
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などと同様にエラーになります。
[user@container ~]# sudo localectl
Failed to create bus connection: No such file or directory
環境変数を直接設定する
Dockerfileでは環境変数を直接セットして日本語ロケールを設定します。
ところが、CentOS7の公式イメージでは設定できる既定ロケールが次の3つだけです。
[user@container ~]# locale -a
C
POSIX
en_US.utf8
このため、Dockerfileでは次のコマンドでロケールの追加を行う必要があります。
(この方法で作成するロケールをカスタムロケールというらしいです)
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
上記で作成した日本語ロケールを次のコマンドで環境変数にセットします。
ENV LANG="ja_JP.UTF-8" \
LANGUAGE="ja_JP:ja" \
LC_ALL="ja_JP.UTF-8"
これで日本語環境のコンテナを作成できます。
ロケールエラーが発生する場合の回避方法
上記までの方法でDockerfileを作成したところ、テスト用コンテナでは問題なかったのですが、
複数の設定を入れた実用のDockerfileで次のようなエラーが発生するようになりました。
RUNコマンドの実行時などに発生します。
(error)
/bin/sh: warning: setlocale: LC_ALL: cannot change locale (ja_JP.UTF-8)
Failed to set locale, defaulting to C
作成されたコンテナで locale を確認すると LC_ALLなどの設定が落ちているようです。
[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より先に実行する
**2018/7/10追記**
次の記事で解説されている方法で回避可能と思われます。
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