Goのタイムゾーンの変更をalpineのDockerコンテナ内で行なう
はじめに
Goのtimeパッケージにはいくつかタイムゾーンを指定するための関数が生えていますが、それらはすべて、
the IANA Time Zone database
と呼ばれる世界各地の標準時間を集めたDatabaseを利用してタイムゾーンの情報を取得します。これはubuntuの環境などで動かす場合は特に問題ないのですが、alpine Linuxを用いたコンテナ内では少し注意必要で、先日少し戸惑ったのでメモとして残しておきます。
Goのタイムゾーン操作について
Goのtimeは例えば、以下のようにタイムゾーンを指定することができます。
const location = "Asia/Tokyo" loc, err := time.LoadLocation(location) if err != nil{ panic(err) } nowWithLocation := time.Now().In(loc) log.Printf("time = %s", nowWithLocation.String()) log.Printf("location = %s", location)
これをubuntuなどの環境で動かすと普通に動きます。
# 動作環境はこんな感じ $ uname -srvmpio Linux 5.3.0-46-generic #38~18.04.1-Ubuntu SMP Tue Mar 31 04:17:56 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux $ go build -o ./go-location-sample $ ./go-location-sample 2020/04/12 19:32:40 time = 2020-04-12 19:32:40.986375152 +0900 JST 2020/04/12 19:32:40 location = Asia/Tokyo
alpineやscrach Linuxでイメージを作成した際の問題点
先程のコードを以下のようにDockerイメージを作成し動かそうとするとエラーになります。
FROM golang:1.10.1-alpine3.7 as builder COPY ./main.go ./ RUN go build -o /go-location-sample ./main.go FROM alpine:3.7 COPY --from=builder /go-location-sample . ENTRYPOINT ["./go-location-sample"]
ビルドして実行します。
$ docker -v Docker version 19.03.8, build afacb8b7f0 $ docker build -t go-location-sample:1.0 . $ docker images -a | grep go-location-sample go-location-sample 1.0 b762fd786613 About a minute ago 6.32MB $ docker run b762fd786613 panic: open /usr/local/go/lib/time/zoneinfo.zip: no such file or directory goroutine 1 [running]: main.main() /go/main.go:12 +0x182
ログにエラーの内容が出ていますが、これはTime Zone Databaseの実態であるzoneinfo.zip
がalpineなどに用意されていないことが問題で起こります。
(ちなみに、同様のことがscratchやbusyboxなどでも起こるみたいです。)
なので、実行イメージの方にzoneinfo.zip
追加してやるようにすれば動くようになります。
FROM golang:1.10.1-alpine3.7 as builder COPY ./main.go ./ RUN go build -o /go-location-sample ./main.go FROM alpine:3.7 COPY --from=builder /go-location-sample . # time zone databaseを取ってくる ADD https://github.com/golang/go/raw/master/lib/time/zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip ENTRYPOINT ["./go-location-sample"]
$ sudo docker build -t go-location-sample:1.0 . $ sudo docker images -a | grep go-location-sample go-location-sample 1.0 9fb7055e3f0b About a minute ago 7.1MB $ docker run 9fb7055e3f0b 2020/04/12 11:41:43 time = 2020-04-12 20:41:43.000606042 +0900 JST 2020/04/12 11:41:43 location = Asia/Tokyo
これで問題なく動くようになりました。
感想
仕事で若干ハマったので、メモとして残しておこうと思って書きました。
なんとなくもう少しいいやり方もあるように感じたので、もしご存知の方がいらっしゃったらコメント等で教えてほしいです。