I'm using Docker to create a container application and then deploy it to kubernetes engine but when the application is been initialized I get this error:
err: open C:\Go/lib/time/zoneinfo.zip: no such file or directory
I'm using Docker to create a container application and then deploy it to kubernetes engine but when the application is been initialized I get this error:
err: open C:\Go/lib/time/zoneinfo.zip: no such file or directory
You might consider building your Go application with Go 1.15 (August 2020, two years later)
New embedded tzdata package
Go 1.15 includes a new package,
time/tzdata
, that permits embedding the timezone database into a program.
- Importing this package (as
import _ "time/tzdata"
) permits the program to find timezone information even if the timezone database is not available on the local system.- You can also embed the timezone database by building with
-tags timetzdata
.Either approach increases the size of the program by about 800 KB.
That way, once deployed to a Kubernetes engine as a Docker image, it won't have to try and load any timezone information, since said information is embedded in its program.
Caveat: as commented by dolmen:
This solution has the drawback that the timezone information version is linked to the version of Go you use for building.
If you keep using a fixed version of Go for your project, you will keep timezones from that version.
Being able to update the timezone information independently from the Go version (update every time you rebuild the Docker image for deploy) might be a better choice.
As an illustration, see dolmen's answer.
When using Go's time package, specifically the LoadLocation method, it looks for time zone database information in various locations. This is explained in the comments for LoadLocation in the source code at https://golang.org/src/time/zoneinfo.go. Specifically it looks in these places:
When you're programming on a Windows machine, Go is most likely defaulting to the 3rd option. However, there is no $GOROOT when you're working with a binary, so that won't work in your container. On most versions of Linux the 2nd option would work fine as they would have the necessary time zone database files. However, I have a strong suspicion that the optimized container you reference does not. This leaves you with option 1, which essentially consists of putting your own time zone database files on the container and then referencing their location with the ZONEINFO environment variable. This is both kind of a pain in the ass and I've also found that it fails silently when you request a time zone file that doesn't exist.
In my own addressing of this problem I ended up creating a package that utilizes the LoadLocationFromTZData method and tries to simplify the process of providing and working with your own copy of the time zone database. You can see my own stack overflow question here: Detect if ZONEINFO fails in Go. And you can see the repository for my time zone package here: https://github.com/slotheroo/knozone
Use the Dockerfile to build the zoneinfo.zip
as well as build your app.
FROM golang:1.17.1-alpine3.14 AS builder
...
WORKDIR /src
...
RUN GOOS=linux GO111MODULE=on go build -trimpath -o my_app
....
FROM alpine:latest as alpine
# Update timezone info and TLS certificates
RUN apk --no-cache add tzdata zip ca-certificates
WORKDIR /usr/share/zoneinfo
# -0 means no compression. Needed because go's
# tz loader doesn't handle compressed data.
RUN zip -r -0 /zoneinfo.zip .
# Final image.
FROM scratch
# Timezone data
ENV ZONEINFO /zoneinfo.zip
COPY --from=alpine /zoneinfo.zip /
# TLS certificates
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /src/my_app
You might also be interested in Google Distroless base Docker images.
I faced that same problem a week ago and ended up resolving like this on the Dockerfile.
First, you need to locate the zoneinfo.zip
file. For instance on a MacOS having Go installed via brew can get tricky.
tztest$ go env GOROOT
/usr/local/Cellar/go/1.12.7/libexec
tztest$ ls -l /usr/local/Cellar/go/1.12.7/libexec/lib/time/zoneinfo.zip
-rwxr-xr-x 1 mau staff 365447 Jul 8 16:29 /usr/local/Cellar/go/1.12.7/libexec/lib/time/zoneinfo.zip
So the workaround is copying zoneinfo.zip
and include in the same directory of the Dockerfile. From there, is just a matter of ADD the file to the docker build process and override the environment variable
ADD zoneinfo.zip /zoneinfo.zip
ENV ZONEINFO /zoneinfo.zip