5

Go code:

package main

import (
    "fmt"
    "time"
)

func main() {
    var local,_ = time.LoadLocation("Asia/Shanghai")
    fmt.Println(time.Now())
    fmt.Println(time.Now().In(local))
}

Dockerfile:

FROM scratch
COPY ./main /main
CMD [ "/main" ]

build.sh:

rm -rf main
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main  . 
docker build -t hello-go .
docker run hello-go

All the file are in one folder named hello-go. When I run my Go code in my osx. It works.

➜  hello-go go run main.go
2017-12-13 21:50:53.482933 +0800 CST m=+0.000350077
2017-12-13 21:50:53.483007 +0800 CST

When i build the docker image and start it. one error like this:

➜  hello-go ./build.sh
Sending build context to Docker daemon  1.937MB
Step 1/3 : FROM scratch
 --->
Step 2/3 : COPY ./main /main
 ---> 80da783f6c5d
Step 3/3 : CMD /main
 ---> Running in 85cb022b3ce2
 ---> 485ddd3a08dd
Removing intermediate container 85cb022b3ce2
Successfully built 485ddd3a08dd
Successfully tagged hello-go:latest
2017-12-13 13:52:59.861173734 +0000 UTC m=+0.000252335
panic: time: missing Location in call to Time.In

goroutine 1 [running]:
time.Time.In(0xbe846a0ef355744e, 0x4d607, 0x539b80, 0x0, 0x0, 0x0, 0xc420037f70)
        /usr/local/go/src/time/time.go:1073 +0xc0
main.main()
        /Users/liujichun/Desktop/workspace/docker/hello-go/main.go:11 +0xee
➜  hello-go

I know the scratch image is empty. What should i do to make it.

JimB
  • 104,193
  • 13
  • 262
  • 255
JICHUN
  • 103
  • 3
  • 9

4 Answers4

5

I think the proper way to solve this is to import tzdata as the library wants it to be. You can make use of the TZ environment variable.

The solution is indicated in a Dockerfile which I found on GitHub here

To wrap up everything:

FROM golang:alpine AS build
RUN apk update && apk add ca-certificates && apk add tzdata
WORKDIR /app
ADD . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp

FROM scratch AS final
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /app/myapp /

ENV TZ Australia/Sydney
ENTRYPOINT ["/myapp"]
Dharman
  • 30,962
  • 25
  • 85
  • 135
5

Starting from Go 1.15, time/tzdata is available, just import the package in your main package.

Reference: https://golang.org/pkg/time/tzdata/

3

Docker FROM alphine

RUN apk --no-cache add tzdata

see answer in: https://stackoverflow.com/a/62159987/4143613

erajuan
  • 2,224
  • 20
  • 31
  • Using alpine opens your container up to more attack vectors and is a heavy-handed approach. Using scratch is not only fine, but a good idea if you're going for security or performance. If you want access to platform-independent timezones, the above answer to use tz is honestly better. – Jyosua Oct 19 '20 at 02:27
2

Using this library https://godoc.org/4d63.com/tz

Their example (see tz.LoadLocation):

t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
fmt.Println(t)

syd, _ := tz.LoadLocation("Australia/Sydney")
fmt.Println(t.In(syd))

// Output:

// 2009-11-10 23:00:00 +0000 UTC
// 2009-11-11 10:00:00 +1100 AEDT
luismartingil
  • 1,029
  • 11
  • 16
  • This is no longer necessary (as of Go 1.15). You only need to import "time/tzdata" (prefix it with underscore) to get an embedded time zone database. – Mani Dec 20 '22 at 23:13