Go Dockerfile 멀티스테이징 scratch를 이용한 경량화 + 타임존 맞추기

2020. 6. 26. 10:47Trouble Shooting

썸네일

 

how to make dockerfile with local timezone on go?

 

Go언어를 사용해 Docker를 이용하면 정말 찰떡궁합 같은 존재가 되는데,

기본적으로 scratch라는 이미지를 많이 사용합니다.

 

저는 주로 로컬 개발시에는 WSL2로 할 땐 goland에서 build 후 터미널에서 compose를 재구성하는데,

compose가 아직 현재 시점에선 jetbrains가 docker connect는 되는데 이상하게 windows wsl docker-compose로 구성돼있음에도 불구하고 linux가 아닌 window에서 실행되어 에러가 나네요...

혹시 방법을 아시는 분은 댓글 부탁드립니다!

 

 

Dockerfile

FROM golang:alpine as builder
COPY . /app
WORKDIR /app
RUN apk update && \
  apk upgrade && \
  apk add --no-cache ca-certificates && \
  apk add --update-cache tzdata && \
  update-ca-certificates && \
  CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -ldflags '-s' -o main .
  
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /usr/local/go/lib/time/zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip
ENV TZ=Asia/Seoul \
    ZONEINFO=/zoneinfo.zip
CMD ["/main"]

보통 용량을 더 축소시키기 위해 멀티 스테이징(Multi staging) 빌드 방식을 많이 사용하게 되는데,

멀티 스테이징을 사용하면 상단에서 alpine 이미지 나온 결과물만을 copy 하고 레이어는 무시하게 됩니다.

(따로 docer image prune 등을 사용해서 제거는 해줘야 함...)

 

golang:alpine 이미지로 6행의 ca-certificates12행의 certs파일은 선택적 사항인데,

본인이 만든 프로그램이 외부로 requests를 던져 통신할 경우에는 ssl 인증서가 없어서 오류가 나는데 이를 해결해주는 역할을 합니다.

 

 

타임존의 경우 7행과 13,14행이 핵심 부분인데,

TZ와 tzdata만으로 안돼서, ZONEINFO를 추가해 zoneinfo.zip을 이용해야 합니다.

 

 

 

결과

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println(time.Now().Zone())
}

 

결과

빌드 전 main파일에서 타임존을 출력해보면

KST가 출력되는 것을 볼 수 있고 gin 등을 이용한다면 로그를 확인할 경우

이 부분은 증명이 애매하지만 정상적으로 KST시간이 출력되고 있는 것을 볼 수 있습니다!

 

구글 검색 결과 requests 통신 ca-certs 관련해서는 정보를 찾기 쉬운데,

타임존의 경우는 대부분이 정상 동작을 안 하는데 일본의 한 게시물을 발견 후 빌더의 zonezip을 카피하는 방식으로 가능할 수 있었네요!

 

 

 

 

 

참고: https://qiita.com/fuubit/items/f432f16d1a356e27749e

 

golang multi-stage build でscratchを使う際にタイムゾーンを設定する方法 - Qiita

Dockerfile example FROM golang:1.14.2-alpine3.11 AS builder RUN apk --update-cache add tzdata WORKDIR $GOPATH/sr...

qiita.com