Libertyコンテナにロケールとタイムゾーンを設定する方法のメモ。
ロケールの設定
Libertyの公式DockerHubでDockerfileをたどっていくと、
websphere-liberty:javaee8 > websphere-liberty:kernel > ibmjava:8-jre > ubuntu:16.04
となっており元のイメージはUbuntuである。
ロケールを確認するとPOSIXとなっている。
$ docker run --rm -it websphere-liberty:18.0.0.3-kernel locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=
$
日本語ロケールを組み込むには以下のようにする。18.0.0.3のある変更からUSER
がroot
ではなく1001
となっているので、apt-get
を実行するためにはUSER
を変更する必要がある。
FROM websphere-liberty:18.0.0.3-kernel
USER 0
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y language-pack-ja && \
rm -rf /var/lib/apt/lists/*
USER 1001
ENV LANG ja_JP.UTF-8
language-pack-jaをインストールすると依存性でlocales、language-pack-ja-baseもインストールされる。
LANGではなくLC_ALLを設定することもできるが、LANGのほうがよさそう。
ビルドする。
docker build -t websphere-liberty:18.0.0.3-kernel-ja .
コンテナを実行して確認する。
$ docker run --rm -it websphere-liberty:18.0.0.3-kernel-ja locale
LANG=ja_JP.UTF-8
LANGUAGE=
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=
$
localesだけインストールして以下とすることも可能。
FROM websphere-liberty:18.0.0.3-kernel
USER 0
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y locales && \
rm -rf /var/lib/apt/lists/* && \
locale-gen ja_JP.UTF-8
USER 1001
ENV LANG ja_JP.UTF-8
Shift_JISの場合はlocale-gen
ではなくlocaledef
を使用する必要がある。
FROM websphere-liberty:18.0.0.3-kernel
USER 0
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y locales && \
rm -rf /var/lib/apt/lists/* && \
localedef -f SHIFT_JIS -i ja_JP ja_JP.SJIS
USER 1001
ENV LANG ja_JP.SJIS
docker build -t websphere-liberty:18.0.0.3-kernel-ja-sjis .
$ docker run --rm -it websphere-liberty:18.0.0.3-kernel-ja-sjis locale
LANG=ja_JP.SJIS
LANGUAGE=
LC_CTYPE="ja_JP.SJIS"
LC_NUMERIC="ja_JP.SJIS"
LC_TIME="ja_JP.SJIS"
LC_COLLATE="ja_JP.SJIS"
LC_MONETARY="ja_JP.SJIS"
LC_MESSAGES="ja_JP.SJIS"
LC_PAPER="ja_JP.SJIS"
LC_NAME="ja_JP.SJIS"
LC_ADDRESS="ja_JP.SJIS"
LC_TELEPHONE="ja_JP.SJIS"
LC_MEASUREMENT="ja_JP.SJIS"
LC_IDENTIFICATION="ja_JP.SJIS"
LC_ALL=
タイムゾーンの設定
タイムゾーンはCentOSは環境変数を設定するだけでよいが、Ubuntuはそれだけでは足りないようだ。+9時間になっていない。
$ docker run --rm -it centos:7 date
Tue Oct 30 12:55:12 UTC 2018
$ docker run --rm -it -e "TZ=Asia/Tokyo" centos:7 date
Tue Oct 30 21:55:21 JST 2018
$ docker run --rm -it ubuntu:16.04 date
Tue Oct 30 12:55:34 UTC 2018
$ docker run --rm -it -e "TZ=Asia/Tokyo" ubuntu:16.04 date
Tue Oct 30 12:55:43 Asia 2018
tz-dataをインストールしてあれこれする。
FROM websphere-liberty:18.0.0.3-kernel
USER 0
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata && \
rm -rf /var/lib/apt/lists/* && \
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata
USER 1001
ENV TZ Asia/Tokyo
最後のENV TZ Asia/Tokyo
はなくてもよい。
ビルドする。
docker build -t websphere-liberty:18.0.0.3-kernel-jst .
確認。
$ docker run --rm -it liberty-jst:kernel date
Mon Oct 15 17:07:55 JST 2018
$
オフライン環境でビルドする場合
事前にインターネットにつながる環境でパッケージを取得しておき、オフライン環境でビルドする。
オンライン環境でのパッケージの取得
カレントディレクトリーをマウントし、rootユーザーを指定してコンテナを起動して中に入る。
docker run --rm -it -u 0 -v $PWD:/work websphere-liberty:18.0.0.3-kernel bash
必要なパッケージをダウンロードオンリーモードで取得する。
apt-get update
apt-get install -y -d language-pack-ja
apt-get install -y -d tzdata
/var/cache/apt/archives
にダウンロードしたファイルがあるので、マウントしたディレクトリーにコピーする。
root@de5cc55463e1:/# ls -l /var/cache/apt/archives
total 6404
-rw-r--r-- 1 root root 2016058 Jun 28 2016 language-pack-ja-base_1%3a16.04+20160627_all.deb
-rw-r--r-- 1 root root 1147434 Jan 9 2018 language-pack-ja_1%3a16.04+20171210_all.deb
-rw-r--r-- 1 root root 3212542 Jan 17 2018 locales_2.23-0ubuntu10_all.deb
-rw-r----- 1 root root 0 Oct 5 18:08 lock
drwx------ 2 _apt root 4096 Oct 30 13:09 partial
-rw-r--r-- 1 root root 165668 Oct 29 10:08 tzdata_2018g-0ubuntu0.16.04_all.deb
root@de5cc55463e1:/# cp /var/cache/apt/archives/*.deb /work
root@de5cc55463e1:/# exit
exit
$ ls -l
total 12808
-rw-r--r-- 1 sotoiwa staff 278 10 30 21:52 Dockerfile
-rw-r--r-- 1 sotoiwa staff 2016058 10 30 22:10 language-pack-ja-base_1%3a16.04+20160627_all.deb
-rw-r--r-- 1 sotoiwa staff 1147434 10 30 22:10 language-pack-ja_1%3a16.04+20171210_all.deb
-rw-r--r-- 1 sotoiwa staff 3212542 10 30 22:10 locales_2.23-0ubuntu10_all.deb
-rw-r--r-- 1 sotoiwa staff 165668 10 30 22:10 tzdata_2018g-0ubuntu0.16.04_all.deb
$
オンライン環境でのビルド
Dockerfileは以下のようにする。以下は日本語ロケールの設定とタイムゾーンの設定を両方やる例。
FROM websphere-liberty:18.0.0.3-kernel
USER 0
COPY *.deb /tmp/
RUN DEBIAN_FRONTEND=noninteractive dpkg -i \
/tmp/language-pack-ja-base_1%3a16.04+20160627_all.deb \
/tmp/language-pack-ja_1%3a16.04+20171210_all.deb \
/tmp/locales_2.23-0ubuntu10_all.deb \
/tmp/tzdata_2018g-0ubuntu0.16.04_all.deb && \
rm -rf /tmp/*.deb && \
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata
USER 1001
ENV LANG ja_JP.UTF-8
ENV TZ Asia/Tokyo
おまけ
Javaからどう見えるかも確認する。
確認用の簡単なJavaプログラムを作成する。
import java.util.Date;
import java.util.Locale;
public class Main
{
public static void main (String[] args) throws java.lang.Exception
{
System.out.println("file.encoding = " + System.getProperty("file.encoding"));
System.out.println("console.encoding = " + System.getProperty("console.encoding"));
System.out.println("Date() = " + new Date());
System.out.println("Locale Code = " + Locale.getDefault());
System.out.println("こんにちは!");
}
}
Main.javaをコンパイルしてLibertyのコンテナの中にクラスファイルを配置するDockerfileを作成する。LibertyのコンテナにはJDKが入っていないので、マルチステージビルドを使う。
FROM ibmjava:8-sdk as builder
COPY Main.java /
RUN javac -encoding UTF-8 /Main.java
FROM websphere-liberty:18.0.0.3-kernel
COPY --from=builder /Main.class /
ビルドする。
docker build -t liberty-test:18.0.0.3-kernel .
$ docker run --rm -it liberty-test:18.0.0.3-kernel java Main
file.encoding = ANSI_X3.4-1968
console.encoding = null
Date() = Tue Oct 30 13:54:28 UTC 2018
Locale Code = en_US
??????
ロケールとタイムゾーンを設定してビルドする。
FROM ibmjava:8-sdk as builder
COPY Main.java /
RUN javac -encoding UTF-8 /Main.java
FROM websphere-liberty:18.0.0.3-kernel
USER 0
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y language-pack-ja && \
rm -rf /var/lib/apt/lists/*
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata && \
rm -rf /var/lib/apt/lists/* && \
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata
USER 1001
ENV LANG ja_JP.UTF-8
ENV TZ Asia/Tokyo
COPY --from=builder /Main.class /
ビルドする。
docker build -t liberty-test2:18.0.0.3-kernel .
確認する。
$ docker run --rm -it liberty-test2:18.0.0.3-kernel java Main
file.encoding = UTF-8
console.encoding = null
Date() = Tue Oct 30 22:57:43 JST 2018
Locale Code = ja_JP
こんにちは!
$
補足
コンテナにロケールやタイムゾーンを指定する必要があるかというと、そもそもあまり必要でないかもしれない。また、OSのレベルで設定しなくても、Javaのシステムプロパティーでfile.encoding
やconsole.encoding
やuser.timezone
を設定すればすむかもしれない。
$ docker run --rm -it liberty-test:18.0.0.3-kernel java -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Tokyo Main
file.encoding = UTF-8
console.encoding = null
Date() = Tue Oct 30 22:58:35 JST 2018
Locale Code = en_US
こんにちは!
$
参考リンク
Ubuntu 16.04(xenial)のDockerコンテナのタイムゾーンを日本(JST)にする(Dockerfileで)
reconfigure timezone inside docker not working