背景
Alpine Linuxはデフォルトではtzdataが含まれていないため、以下のような
package main import ( "log" "time" ) func main() { loc, err := time.LoadLocation("Asia/Tokyo") if err != nil { log.Fatal("%w", err) } log.Printf("%v", loc) }
time.LoadLocation()が含まれるコードだと
unknown time zone Asia/Tokyo
といったエラーが発生します。
なのでこれまではワークアラウンドとして
FROM golang:1.20-alpine as builder WORKDIR /go/src/ COPY go.* main.go . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main main.go FROM alpine:3.18 RUN apk add --no-cache tzdata COPY --from=builder /go/src/main . CMD ["./main"]
のようにtzdata
をapk addしていましたが、Go 1.15からはそれをしなくて済むというお話です。
環境
- Go v1.20.4
- Alpine v3.18.0
time/tzdata
Go 1.15からtime/tzdataがimportしたりbuild時に埋め込めるようになっています。
埋め込むことでバイナリサイズが800 KB
ほど増えますが、
- ベースのコンテナが変わった
- Bazel使ってるのでパッケージ追加がし辛い
といったこともあるので、tzdataについてはこちらに寄せることをオススメします。
導入方法
方法は2つあります。
a) time/tzdataをブランクインポート
time/tzdataを次のようにインポートするとtzdataを埋め込んでくれます。
package main import ( "log" "time" _ "time/tzdata" // here ) func main() { loc, err := time.LoadLocation("Asia/Tokyo") if err != nil { log.Fatal("%w", err) } log.Printf("%v", loc) }
b) go build時にtagを指定
build時に-tags timetzdata
を設定するとtzdataを埋め込んでくれます。
$ go build -tags timetzdata -o main main.go
動作確認
Dockerfileからapk add tzdata
を抜いて
FROM golang:1.20-alpine as builder WORKDIR /go/src/ COPY go.* main.go . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main main.go FROM alpine:3.18 COPY --from=builder /go/src/main . CMD ["./main"]
docker buildします。
$ docker build -t time-zone .
期待通りに動きます。
$ docker run time-zone 2023/06/07 05:49:32 Asia/Tokyo
まとめ
Go 1.15リリース時に一度話題に挙がっていましたが、検索してみても未だにapk addのやり方を紹介するケースが検索上位にあがるので紹介してみました。