Golang(hello world)을 Docker Container로 띄우기

Go 코딩

비어있는 아무 이름의 폴더에서 시작한다.

Gin은 Go로 짜여진 HTTP web framework으로 아주 빠르고, 사용하기 쉽다.

Gin을 이용해 우선 hello world를 짜보자.

Go를 처음 사용하는 맥북 사용자는 처음에 Go 모듈이 disable 되어있을 것이다.

다음과 같이 enable로 바꾼다.

echo 'export GO111MODULE=auto' >> ~/.zshrc
source ~/.zshrc

초기화

go mod init containerized-go-app

go.mod 가 자동 생성된다.


Gin을 가져온다.

go get -u github.com/gin-gonic/gin


main.go를 작성한다.

package main
import (
    "github.com/gin-gonic/gin"
)

func main() {
    // create router
    r := gin.Default()

    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run()
}

 

endpoint '/ping'을 요청으로 보내면 'pong'이라는 JSON 형태의 메세지를 보내주는 간단한 헬로 월드 앱이다.

 

Local에서 우선 실행해본다.

> go run main.go
> curl http://localhost:8080/ping
{"message":"pong"}

 

잘 실행된다. 그러면 docker로 말아보자.

 

Dockerfile

  • Dockerfile 생성
  • golang image에서 출발 : https://hub.docker.com/_/golang/tags?name=alpine
    현재는 1.23.7이 최신 버전이지만 1.23.1을 쓰겠다.
  • Working directory 명시
  • Copy files → COPY <source> <destination>
  • go build로 빌드하기 → binary 생성
  • 용량을 줄이기 위해 Multi-stage build를 이용하여 일반 alpine 이미지를 base image로 해서 binary를 옮긴다.
  • docker run -p 8080:8080로 port expose
    우선은 용량 비교를 위해 간단하게 빌드참고: Dockerfile에서는 go mod downloadgo get보다 낫다 → 예측 가능

그러나 multi-stage가 얼마나 용량을 줄이는지 보기 위해

우선은 다음 Dockerfile로 single stage로 빌드해보자.

 

FROM golang:1.23.1-alpine
WORKDIR /app
COPY . .
RUN go mod download
RUN go build -o bin .
ENTRYPOINT ["/app/bin"]

 

도커 빌드 후에 컨테이너 실행

docker build . -t go-api:latest
docker run -d -p 8080:8080 go-api:latest
curl http://localhost:8080/ping
{"message":"pong"}

 

이미지 용량을 보면 568메가다.

❯ docker images
REPOSITORY         TAG       IMAGE ID       CREATED             SIZE
go-api             latest    1d357f3ddeed   4 minutes ago       568MB

 

이제는 multi-stage로 빌드를 해보자.

 

Multi-stage Dockerfile

Dockerfile.multi

FROM golang:1.23.1-alpine AS builder

ENV CGO_ENABLED=0 \
    GOARCH=arm64

WORKDIR /build
COPY . .
RUN go mod download
RUN go build -o bin .

FROM alpine:latest as runner

WORKDIR /app
COPY --from=builder /build/bin /app

EXPOSE 8080

CMD ["/app/bin"]

 

환경에 GOARCH=arm64는 내 애플실리콘 맥북에서 돌리기 위해 넣었고
CGO_ENABLE=0는 minimal base image에서 statically linked binary를 사용하기 위해 넣었다.

주의: Linux나 K8s에 배포할 때는 위 `GOARCH=arm64`을 `GOARCH=amd64`로 변경한다.

 

docker build -f Dockerfile.multi -t go-multi:latest .
docker run -d -p 8080:8080 go-multi:latest
curl http://localhost:8080/ping
{"message":"pong"}

 

용량을 보면

❯ docker images                                             
REPOSITORY      TAG       IMAGE ID       CREATED          SIZE
go-multi        latest    bf44ff25b74e   3 minutes ago    19.1MB
go-api          latest    1d357f3ddeed   4 minutes ago     568MB

 

용량이 568 Mb에서 19 Mb로 대폭 줄었다.

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유